Telegram Bot UI
Telegramボットのユーザーインターフェースの全ライフサイクル(監査 → 画面/状態マップ → テキスト、ボタン、ナビゲーション設計 → 実装 → 移行 → テスト → ドキュメント作成)をカバーする、ポータブルでSDKに依存しないスキル。
TelegramボットにはCSSもレイアウトエンジンもありません。そのインターフェース全体は、メッセージテキスト、フォーマット、キーボード、チャットレベルのクローム(コマンド、メニューボタン、ディープリンク)、そして状態間の遷移という5つの要素で構成されます。このスキルは、これら5つすべてを単一のデザインサーフェスとして扱います。
目的
エージェントがボットのインターフェースを明確で、一貫性があり、安全に変更できるように支援します。画面の内容とその表現方法の選択、ボタンのラベル付け、グループ化、順序付け、色付け、レイアウト、画面と状態間のナビゲーション設計、すべての画面の一貫性維持、ローカライゼーションの完全性保持、そしてあらゆる言語とあらゆるTelegram SDKにおいて、既存のハンドラやビジネスロジックを壊すことなく、最もリッチなフォーマットでメッセージ本文をレンダリングします。
使用するタイミング
- インターフェース作業: "ボットのUX/UIを改善する"、"このメニューを再設計する"、"キーボードが過負荷になっている"、"ユーザーがこの画面を理解できない"、"戻るボタンを追加する"、"これらのアクションをグループ化する"、"主要なアクションを目立たせる"。
- ボタンとキーボード: インラインキーボード、リプライキーボード、ボタンラベル、ボタンの順序とレイアウト、
styleカラー、icon_custom_emoji_idカスタム絵文字、Web App / URL / コピーテキスト / スイッチインラインボタン、ForceReply、キーボード削除、ページネーションと戻るナビゲーション。 - テキストとマイクロコピー: ボットメッセージ、タイトル、キャプション、プロンプト、確認、エラーと空の状態の書き換え、トーンと長さ、絵文字の使用。
- チャットクローム:
/commandsリストとスコープ、メニューボタン、/startとディープリンク、初回実行エクスペリエンス。 - 動的フィードバック: AI回答のストリーミング(
sendMessageDraft、sendRichMessageDraft、<tg-thinking>)、プログレスバー、"入力中"ステータス、ボタンローダー、"ボットが処理中でフリーズしているように見える"問題。 - パーソナライゼーションとリンク: ユーザー名の安全な呼びかけ、ロケールヒント、URLボタンとインラインリンク、リンクプレビュー、ディープリンク、メンション。
- 一貫性: 同じアクションが3つの異なる名前で呼ばれている、一部の画面にしかない戻るボタン、編集後の状態不一致。
- メッセージレンダリング: HTML / MarkdownV2 /
MessageEntity、テキスト内のカスタム絵文字、キャプション、テーブルとリッチメッセージ、リンクプレビュー / サイレント / 保護オプション、長文メッセージ分割、ストリーミングドラフト、編集、チャンネル投稿、ローカライゼーションとRTL、can't parse entities、壊れたメッセージやサイズ超過メッセージ。
使用しないタイミング
インターフェースに現れないボットロジック:ウェブフックインフラ、支払い処理、認可、データベースとマイグレーション、グループ管理とモデレーションロジック、スクレイピング、分析パイプライン、ミニアプリ内部(その独自のHTML/CSS UIは通常のWebフロントエンド作業です。このスキルはTelegram側のサーフェス、つまりそれを開くボタンやメニューのみをカバーします)。また、Microsoft .rtf ファイルには使用しません。
用語 — これらを混同しないでください
- インラインキーボード ≠ リプライキーボード。
InlineKeyboardMarkupは特定のメッセージに付加され、callback_queryを送信するかURLを開きます。ReplyKeyboardMarkupはユーザーの文字キーボードを置き換え、テキストを通常のメッセージとして送信します。異なるボタンクラス、異なるUX。 styleは色の値ではありません。 これはprimary、success、dangerのいずれか正確に1つです。TelegramにHEX/RGB/CSSのボタンカラーはありません。icon_custom_emoji_idはfile_idではありません。 絵文字パック名、リンク、Unicode絵文字のいずれでもありません。これは特定のカスタム絵文字1つのIDです。- TelegramリッチテキストはMicrosoft RTFではありません。 リッチメッセージを"RTF"と呼ぶことは絶対にしないでください。
- リッチマークダウン ≠ MarkdownV2。 MarkdownV2は通常のメッセージに対する
parse_modeであり、厳密なエスケープが必要です。リッチマークダウンはリッチメッセージのためのドキュメント構文です。 - リッチHTML ≠ 任意のブラウザHTML。 Telegramがサポートするタグセットのみです。
- キーボードの編集 ≠ 画面の再送信。
editMessageReplyMarkupとeditMessageTextはその場で更新します。新しいメッセージを送信すると画面が積み重なります。
信頼できる情報源ポリシー
以下の順序で信頼します:
- 最新の公式Telegramドキュメント(Bot API、Bot Features、フォーマットページ、公式ブログ)。
- 公式のBot API変更ログ。
- プロジェクトに実際にインストールされているSDKのドキュメント。
- SDKソースコード。
- SDK Issueトラッカー。
- サードパーティの記事 — 補足的なコンテキストとしてのみ使用。
以下の場合には、行動する前に公式ドキュメントを再検証してください:タスクが新しいAPIに触れる場合、今日が references/official-sources.md の"最終確認"日より後である場合、プロジェクトのBot APIバージョンが不明な場合、SDKドキュメントがBot APIと矛盾する場合、未知の型/フィールドに遭遇した場合、またはユーザーが"最新の機能"を求めた場合。このスキルはBot API 10.2で固定されていません。Telegramが新しいバージョンをリリースした場合はそれを使用してください。UI関連のバージョンゲート:references/ui-changelog.md。
コアワークフロー(再設計前に監査)
- プロジェクトの指示を読む(
AGENTS.md/CLAUDE.md/ README / ドキュメント)。 - 言語、フレームワーク、Telegram SDKと正確なバージョンを検出する。
- SDKが実際にサポートするBot APIバージョンを特定する。これにより、
styleとicon_custom_emoji_idが利用可能かどうかが決まる。 - 画面/状態マップを作成する:ユーザーが見られるすべてのメッセージ、すべてのキーボード、すべての
callback_data、すべてのコマンド、すべての遷移(references/navigation-and-flows.md)。 - 各画面を分類する:エントリ / メニュー / フォームステップ / 確認 / 結果 / エラー / 空 / 通知。
- 実際のUX欠陥を特定する(問題を作り出さない):曖昧なラベル、過負荷のキーボード、戻れない行き止まり、一貫性のない命名、誤って破壊的なアクションを実行しやすい配置、ローカライズされていない文字列、読みにくい本文。
- 修正を設計する:最初にテキスト、次に構造、次にレイアウト、最後に色/絵文字 — この順序で。色は最後のレイヤーであり、悪いラベルを修正する手段では決してありません。
- 使用予定のすべてのフィールドについてSDKのサポートを確認する(
references/sdk-compatibility.md)。 - プロジェクトの既存のスタイルとユーティリティで実装する(キーボードビルダーを重複させない)。
- ユーザーが明示的に変更を依頼しない限り、
callback_data、URL、ディープリンク、ハンドラルーティング、ローカライゼーションキーを保持する。 - フォールバックパスを追加し、古いクライアントも使用可能に保つ(
references/errors-and-fallbacks.md)。 - プロジェクトの既存のテストインフラでテストを追加する(
references/testing-playbook.md)。 - プロジェクトのlint / 型チェック / テスト / 該当するスモークチェックを実行する。
- 報告する:画面マップ、変更内容とその理由、意図的に変更しなかった点、制限、検証エビデンス。
ステップ1〜6が完了するまで、実装コードを書かないでください。
5つのUIレイヤー(この順序で設計)
| # | レイヤー | 回答する質問 | リファレンス |
|---|---|---|---|
| 1 | 言葉 | ユーザーはこれが何であり、次に何が起こるかを理解できるか? | references/microcopy-and-labels.md |
| 2 | 構造 | どのアクションが存在し、それらはどのようにグループ化され、順序付けられているか? | references/inline-keyboards.md、references/reply-keyboards.md |
| 3 | ナビゲーション | ここにどうやって来るのか、戻るのか、出るのか?今どの状態にいるのか? | references/navigation-and-flows.md |
| 4 | 本文レンダリング | コンテンツは読みやすいか — テーブル、リスト、見出し、プレーン? | references/format-selection.md、references/tables.md |
| 5 | 強調 | ここでの主要なアクションはどれか?危険なアクションはどれか? | references/buttons-and-styles.md、references/custom-emoji.md |
レイヤー1で失敗した画面は、レイヤー4〜5で救うことはできません。色から始めてはいけません。
ボタンの基本(完全なルールは references/buttons-and-styles.md)
インラインボタンはアクション1つにつき正確に1つ。 Bot APIによると、InlineKeyboardButton は text、icon_custom_emoji_id、style 以外のフィールド(url、callback_data、web_app、login_url、switch_inline_query*、copy_text、callback_game、pay)のうち正確に1つを必要とします。KeyboardButton は、text/icon/style 以外のフィールドを最大1つ許可します。
style(Bot API 9.4) — オプション、正確に次のいずれか:
style | 色 | 意味 | 典型的なラベル |
|---|---|---|---|
primary | 青 | 画面の主要な前進アクション | 続行、開始、開く、次へ、選択 |
success | 緑 | 肯定的にコミット/確認/完了 | 保存、確認、公開、送信、完了 |
danger | 赤 | 破壊的または不可逆的 | 削除、リセット、購読解除、退会、プランキャンセル |
| 省略 | アプリデフォルト | その他すべて | 戻る、設定、ヘルプ、二次オプション |
style が省略された場合、アプリ固有のスタイルが使用されます。画面ごとに primary は最大1つ。danger は本当に破壊的なアクションのみに使用し、確認ステップと組み合わせる。 "戻る" などの二次的なアクションは通常、スタイルを付けません。
icon_custom_emoji_id(Bot API 9.4) — ボタンテキストの前にカスタム絵文字を表示します。Fragmentで追加のユーザー名を購入したボット、またはボットの所有者がTelegram Premiumを持っている場合にボットからプライベート、グループ、スーパーグループチャットに直接送信されるメッセージでのみ使用可能。IDをでっち上げないでください — 取得するか(references/custom-emoji.md)、ユーザーに尋ねてください。
両フィールドは動作するボタンの装飾です。ラベルは色やアイコンがなくても意味が通らなければなりません。
メッセージ本文:最も役立つリッチな形式
| ニーズ | 使用する形式 |
|---|---|
| 行/列またはラベル→値データ | テーブル — references/tables.md |
| 構造化ドキュメント:レポート、AI回答、比較、チェックリスト | リッチマークダウン |
| サーバーテンプレートコンテンツ、正確なタグ制御 | リッチHTML |
| データ/CMS/ASTからの型付け生成 | InputRichBlock ブロック |
| キーボード付き画面:短いプロンプト+オプション | 通常のHTML、短く |
正確なオフセット制御、parse_mode 不要 | MessageEntity |
| スタイリングが本当に不要 | プレーンテキスト |
ルール:構造化データは実際のテーブルにします。等幅グリッドにはしません。 ただし、メニュー画面は短いプロンプトとボタンであり、エッセイではありません。完全なマトリックス:references/format-selection.md。
ボット動作中のフィードバック
シグナルなしの待機は、ボットにおける最も一般的なUX障害です。操作の種類に応じて選択します(完全なルール:references/dynamic-feedback-and-streaming.md):
| 状況 | メカニズム |
|---|---|
| インラインボタンがタップされた | answerCallbackQuery を最初に実行し、その後作業を行う |
| 2〜5秒の操作 | sendChatAction(typing、upload_photo など) — 最大5秒 |
| AIテキスト生成中(プライベートチャット) | sendMessageDraft — 同じ draft_id、sendMessage で確定 |
| 構造化されたAI回答 | sendRichMessageDraft + <tg-thinking> → sendRichMessage |
| 実際の名前付きステージ | editMessageText、スロットリング付き |
| 進行状況が測定不可能 | 名前付きステージ — 偽のパーセンテージは絶対に使わない |
| インタラクティブプロセス | ミニアプリ(BottomButton.showProgress()、WebApp.ready()) |
トークンごとに編集しないでください。約800〜1500ミリ秒、約30〜80の新しい文字、完了した文、または実際のステージ変更ごとに更新し、retry_after を尊重してください。操作ごとに1つの draft_id / message_id / operation_id を使用し、正確に1回確定します。
どのリファレンスを読むか(タスクに応じてルーティング — すべて読まない)
UI / UX
- ボタンラベル、メッセージの言い回し、トーン、テキスト内の絵文字 →
references/microcopy-and-labels.md styleカラー、強調、ボタンレイアウトとグループ化 →references/buttons-and-styles.md- インラインキーボード、
callback_data、ページネーション、その場での編集 →references/inline-keyboards.md - リプライキーボード、
ForceReply、キーボード削除、プレースホルダー →references/reply-keyboards.md - 画面、状態、戻る/ホーム、コマンド、メニューボタン、ディープリンク →
references/navigation-and-flows.md - ボタンとテキストのカスタム絵文字、IDの取得、資格 →
references/custom-emoji.md - ストリーミング回答、思考ブロック、プログレスバー、ローダー、チャットアクション →
references/dynamic-feedback-and-streaming.md - ユーザーデータによるパーソナライゼーション、リンク、プレビュー、ディープリンク →
references/personalization-and-links.md - 画面間の一貫性 + 完了前チェックリスト →
references/consistency-and-review.md - UI関連のBot API履歴とバージョンゲート →
references/ui-changelog.md - before/afterシナリオ例 →
references/examples-before-after.md
コンテンツレンダリング
- テーブル →
references/tables.md - リッチメッセージ / ブロック / 機能マトリックス →
references/telegram-capabilities.md - HTML / MarkdownV2 / エンティティ / キャプション / プレビュー →
references/regular-formatting.md - フォーマットの選択 →
references/format-selection.md - メディア →
references/rich-media.md - 制限と分割 →
references/limits-and-splitting.md - ストリーミングドラフトと編集 →
references/streaming-and-editing.md - チャンネル、通知、ブロードキャスト →
references/channels-and-broadcasting.md
エンジニアリング
- 未知のプロジェクトの調査 →
references/project-adaptation.md - エスケープ / インジェクション / ユーザーまたはAIコンテンツ →
references/security-and-escaping.md - ローカライゼーション、RTL、ボタンラベルの長さ →
references/localization-and-rtl.md - エラー、フォールバック、古いクライアント →
references/errors-and-fallbacks.md - SDKのギャップ / 生のBot APIペイロード →
references/sdk-compatibility.md - テスト →
references/testing-playbook.md - 情報源と最終確認日 →
references/official-sources.md
ローカルバリデーター:scripts/validate_skill.py、scripts/validate_references.py、scripts/validate_keyboard.py(キーボードJSONルール — オフライン、トークン不要)。トリガーシナリオ:evals/activation-evals.md。
絶対に妥協しないルール
- 動作を保持する。 既存の
callback_data、URL、ディープリンク、ペイロード、ハンドラルーティングを維持する。ビジュアルリデザインでハンドラを書き換えてはいけません。callback_dataの変更が避けられない場合は、その旨を伝え、同じ変更内ですべてのハンドラ/ルートを更新してください。 - ピクセルよりも言葉を優先。 色や絵文字を追加する前にラベルを修正する。
- 装飾的な色は禁止。 アクションの意味に基づいて
styleを割り当てる。すべてのボタンに色を付けない。色だらけのキーボードには階層がありません。 styleはprimary、success、danger、または省略のみ。color、bg_color、hexなどは存在しません。icon_custom_emoji_idを発明しない。 自分が責任を持つボットのために実際のIDを取得するか、ユーザーに提供を求めてください。- 既存のヘルパーを上書きしない。 プロジェクトに
buildInlineKeyboard、buildMainMenu、formatErrorなどがすでにある場合は、それを呼び出し、新しいものを書かない。 - 変更理由を説明する。 追加するすべての色、絵文字、テキスト変更、再グループ化には、それが閲覧者に与える影響に関する具体的な根拠が必要です。
- 一貫性をチェックする。 同じ操作("設定"、"キャンセル"、"保存"、"削除")は、ボット全体で同じラベル、同じ色、同じキーボード位置を使用する。
references/consistency-and-review.mdを参照。 - インラインボタンは正確に1つのアクション。 各
InlineKeyboardButtonには、text、icon_custom_emoji_id、styleを除き、url、callback_data、web_appなどのフィールドが1つだけ含まれます。 - **styl