Mainstream messaging
Telegram
本番運用に対応した bot の DM とグループを grammY 経由で利用できます。デフォルトのモードはロングポーリングです。Webhook モードは任意です。
Telegram のデフォルト DM ポリシーはペアリングです。
チャネル横断の診断と修復プレイブックです。
チャネル設定の完全なパターンと例です。
クイックセットアップ
BotFather で bot トークンを作成する
Telegram を開いて @BotFather とチャットします(ハンドルが正確に @BotFather であることを確認してください)。
/newbot を実行し、プロンプトに従って、トークンを保存します。
トークンと DM ポリシーを設定する
{
channels: {
telegram: {
enabled: true,
botToken: "123:abc",
dmPolicy: "pairing",
groups: { "*": { requireMention: true } },
},
},
}
環境変数のフォールバック: TELEGRAM_BOT_TOKEN=...(デフォルトアカウントのみ)。
Telegram は openclaw channels login telegram を使用しません。config/env でトークンを設定してから、gateway を起動してください。
gateway を起動して最初の DM を承認する
openclaw gateway
openclaw pairing list telegram
openclaw pairing approve telegram <CODE>
ペアリングコードは 1 時間後に期限切れになります。
bot をグループに追加する
bot をグループに追加してから、アクセスモデルに合わせて channels.telegram.groups と groupPolicy を設定します。
Telegram 側の設定
プライバシーモードとグループでの可視性
Telegram bots のデフォルトは Privacy Mode で、これにより受信できるグループメッセージが制限されます。
bot がすべてのグループメッセージを見る必要がある場合は、次のいずれかを行います。
/setprivacyでプライバシーモードを無効にする、または- bot をグループ管理者にする。
プライバシーモードを切り替えたら、Telegram が変更を適用できるように、各グループで bot を削除して再追加してください。
グループ権限
管理者ステータスは Telegram のグループ設定で制御されます。
管理者 bot はすべてのグループメッセージを受信します。これは、常時有効なグループ動作に役立ちます。
便利な BotFather 切り替え
/setjoingroupsでグループ追加を許可/拒否/setprivacyでグループでの可視性の動作を設定
アクセス制御と有効化
DM ポリシー
channels.telegram.dmPolicy はダイレクトメッセージのアクセスを制御します。
pairing(デフォルト)allowlist(allowFromに少なくとも 1 つの送信者 ID が必要)open(allowFromに"*"を含める必要あり)disabled
dmPolicy: "open" と allowFrom: ["*"] を組み合わせると、bot のユーザー名を見つけた、または推測した任意の Telegram アカウントが bot にコマンドを送れるようになります。厳密に制限されたツールを持つ意図的に公開された bot にのみ使用してください。単一所有者の bot では、数値ユーザー ID を指定した allowlist を使用してください。
channels.telegram.allowFrom は数値の Telegram ユーザー ID を受け付けます。telegram: / tg: プレフィックスは受け付けられ、正規化されます。
マルチアカウント設定では、制限的なトップレベルの channels.telegram.allowFrom は安全境界として扱われます。アカウントレベルの allowFrom: ["*"] エントリは、マージ後の有効なアカウント許可リストに明示的なワイルドカードが残っていない限り、そのアカウントを公開状態にはしません。
空の allowFrom を伴う dmPolicy: "allowlist" はすべての DM をブロックし、config 検証で拒否されます。
セットアップでは数値ユーザー ID のみが求められます。
アップグレード後に config に @username の許可リストエントリが含まれている場合は、openclaw doctor --fix を実行して解決してください(ベストエフォート。Telegram bot トークンが必要です)。
以前にペアリングストアの許可リストファイルに依存していた場合、openclaw doctor --fix は許可リストフローでエントリを channels.telegram.allowFrom に復元できます(たとえば dmPolicy: "allowlist" に明示的な ID がまだない場合)。
単一所有者の bot では、以前のペアリング承認に依存するのではなく、明示的な数値 allowFrom ID を指定した dmPolicy: "allowlist" を優先し、アクセスポリシーを config 内で永続化してください。
よくある混乱: DM のペアリング承認は「この送信者はどこでも承認されている」という意味ではありません。
ペアリングは DM アクセスを付与します。コマンド所有者がまだ存在しない場合、最初に承認されたペアリングは commands.ownerAllowFrom も設定し、所有者専用コマンドと exec 承認に明示的なオペレーターアカウントを持たせます。
グループ送信者の承認は引き続き明示的な config 許可リストから取得されます。
「一度承認されれば DM とグループコマンドの両方が動作する」ようにしたい場合は、数値の Telegram ユーザー ID を channels.telegram.allowFrom に入れてください。所有者専用コマンドについては、commands.ownerAllowFrom に telegram:<your user id> が含まれていることを確認してください。
Telegram ユーザー ID を見つける
より安全な方法(サードパーティ bot なし):
- 自分の bot に DM します。
openclaw logs --followを実行します。from.idを読み取ります。
公式 Bot API の方法:
curl "https://api.telegram.org/bot<bot_token>/getUpdates"
サードパーティの方法(プライバシーは低め): @userinfobot または @getidsbot。
グループポリシーと許可リスト
2 つの制御が一緒に適用されます。
-
許可されるグループ(
channels.telegram.groups)groupsconfig がない場合:groupPolicy: "open"の場合: 任意のグループがグループ ID チェックを通過可能groupPolicy: "allowlist"(デフォルト)の場合:groupsエントリ(または"*")を追加するまでグループはブロックされます
groupsが設定されている場合: 許可リストとして動作します(明示的な ID または"*")
-
グループ内で許可される送信者(
channels.telegram.groupPolicy)openallowlist(デフォルト)disabled
groupAllowFrom はグループ送信者のフィルタリングに使用されます。設定されていない場合、Telegram は allowFrom にフォールバックします。
groupAllowFrom エントリは数値の Telegram ユーザー ID である必要があります(telegram: / tg: プレフィックスは正規化されます)。
Telegram のグループまたはスーパーグループのチャット ID を groupAllowFrom に入れないでください。負のチャット ID は channels.telegram.groups の下に置きます。
数値でないエントリは送信者承認では無視されます。
セキュリティ境界(2026.2.25+): グループ送信者認証は DM ペアリングストアの承認を継承しません。
ペアリングは DM 専用のままです。グループでは、groupAllowFrom またはグループごと/トピックごとの allowFrom を設定してください。
groupAllowFrom が未設定の場合、Telegram はペアリングストアではなく config の allowFrom にフォールバックします。
単一所有者の bot の実用的なパターン: ユーザー ID を channels.telegram.allowFrom に設定し、groupAllowFrom は未設定のままにして、対象グループを channels.telegram.groups の下で許可します。
ランタイム注記: channels.telegram が完全に存在しない場合、channels.defaults.groupPolicy が明示的に設定されていない限り、ランタイムは fail-closed の groupPolicy="allowlist" にデフォルト設定されます。
例: 1 つの特定グループ内の任意のメンバーを許可する:
{
channels: {
telegram: {
groups: {
"-1001234567890": {
groupPolicy: "open",
requireMention: false,
},
},
},
},
}
例: 1 つの特定グループ内で特定ユーザーのみを許可する:
{
channels: {
telegram: {
groups: {
"-1001234567890": {
requireMention: true,
allowFrom: ["8734062810", "745123456"],
},
},
},
},
}
メンションの動作
グループ返信ではデフォルトでメンションが必要です。
メンションは次から取得できます。
- ネイティブの
@botusernameメンション、または - 次のメンションパターン:
agents.list[].groupChat.mentionPatternsmessages.groupChat.mentionPatterns
セッションレベルのコマンド切り替え:
/activation always/activation mention
これらはセッション状態のみを更新します。永続化には config を使用してください。
永続 config の例:
{
channels: {
telegram: {
groups: {
"*": { requireMention: false },
},
},
},
}
グループチャット ID の取得:
- グループメッセージを
@userinfobot/@getidsbotに転送する - または
openclaw logs --followからchat.idを読み取る - または Bot API の
getUpdatesを確認する
ランタイム動作
- Telegram は gateway プロセスによって所有されます。
- ルーティングは決定的です。Telegram の受信は Telegram に返信されます(モデルはチャネルを選択しません)。
- 受信メッセージは、返信メタデータとメディアプレースホルダーを含む共有チャネルエンベロープに正規化されます。
- グループセッションはグループ ID で分離されます。フォーラムトピックでは、トピックを分離するために
:topic:<threadId>が追加されます。 - DM メッセージは
message_thread_idを持つことがあります。OpenClaw は返信用にスレッド ID を保持しますが、デフォルトでは DM をフラットなセッションのままにします。DM トピックのセッション分離を意図的に行いたい場合は、channels.telegram.dm.threadReplies: "inbound"、channels.telegram.direct.<chatId>.threadReplies: "inbound"、requireTopic: true、または一致するトピック config を設定してください。 - ロングポーリングは、チャットごと/スレッドごとのシーケンス制御を備えた grammY runner を使用します。runner 全体の sink 並行性には
agents.defaults.maxConcurrentが使用されます。 - ロングポーリングは各 gateway プロセス内で保護されているため、一度に 1 つのアクティブな poller だけが bot トークンを使用できます。それでも
getUpdatesの 409 競合が表示される場合は、別の OpenClaw gateway、スクリプト、または外部 poller が同じトークンを使用している可能性があります。 - ロングポーリングの watchdog 再起動は、デフォルトでは完了した
getUpdatesの liveness が 120 秒間ない場合にトリガーされます。長時間実行される作業中に、デプロイ環境で誤った polling-stall 再起動がまだ発生する場合にのみ、channels.telegram.pollingStallThresholdMsを増やしてください。値はミリ秒単位で、30000から600000まで許可されます。アカウントごとの上書きもサポートされています。 - Telegram Bot API は既読確認をサポートしていません(
sendReadReceiptsは適用されません)。
機能リファレンス
ライブストリームプレビュー(メッセージ編集)
OpenClaw は部分返信をリアルタイムでストリーミングできます。
- ダイレクトチャット: プレビューメッセージ +
editMessageText - グループ/トピック: プレビューメッセージ +
editMessageText
要件:
channels.telegram.streamingはoff | partial | block | progressです(デフォルト:partial)progressはツール進捗用の編集可能なステータス下書きを 1 つ保持し、完了時にそれをクリアして、最終回答を通常メッセージとして送信しますstreaming.preview.toolProgressは、ツール/進捗更新が同じ編集済みプレビューメッセージを再利用するかどうかを制御します(プレビューストリーミングが有効な場合のデフォルト:true)streaming.preview.commandTextは、それらのツール進捗行内のコマンド/exec 詳細を制御します:raw(デフォルト、リリース済みの動作を保持)またはstatus(ツールラベルのみ)- レガシーの
channels.telegram.streamModeと boolean のstreaming値は検出されます。openclaw doctor --fixを実行してchannels.telegram.streaming.modeに移行してください
ツール進捗プレビュー更新は、ツールの実行中に表示される短いステータス行です。たとえば、コマンド実行、ファイル読み取り、計画更新、パッチ要約などです。Telegram では、v2026.4.22 以降のリリース済み OpenClaw 動作に合わせるため、これらはデフォルトで有効です。回答テキスト用の編集済みプレビューは保持しつつツール進捗行を非表示にするには、次を設定します。
{
"channels": {
"telegram": {
"streaming": {
"mode": "partial",
"preview": {
"toolProgress": false
}
}
}
}
}
ツール進捗を表示したままコマンド/exec テキストを非表示にするには、次を設定します。
{
"channels": {
"telegram": {
"streaming": {
"mode": "partial",
"preview": {
"commandText": "status"
}
}
}
}
}
最終回答を同じメッセージに編集し込まず、目に見えるツール進行状況を出したい場合は progress モードを使用します。コマンドテキストポリシーは streaming.progress の下に置きます。
{
"channels": {
"telegram": {
"streaming": {
"mode": "progress",
"progress": {
"toolProgress": true,
"commandText": "status"
}
}
}
}
}
最終結果だけを配信したい場合にのみ streaming.mode: "off" を使用します。Telegram のプレビュー編集は無効になり、汎用的なツール/進行状況の雑談は単独のステータスメッセージとして送信される代わりに抑制されます。承認プロンプト、メディアペイロード、エラーは引き続き通常の最終配信経路を通ります。回答プレビュー編集だけを維持し、ツール進行状況のステータス行を隠したい場合は streaming.preview.toolProgress: false を使用します。
テキストのみの返信の場合:
- 短い DM/グループ/トピックのプレビュー: OpenClaw は同じプレビューメッセージを維持し、その場で最終編集を実行します
- 複数の Telegram メッセージに分割される長いテキストの最終結果では、可能な場合は既存のプレビューを最初の最終チャンクとして再利用し、その後に残りのチャンクだけを送信します
- progress モードの最終結果では、ステータス下書きをクリアし、下書きを回答に編集する代わりに通常の最終配信を使用します
- 完了テキストが確認される前に最終編集が失敗した場合、OpenClaw は通常の最終配信を使用し、古いプレビューをクリーンアップします
複雑な返信(たとえばメディアペイロード)の場合、OpenClaw は通常の最終配信にフォールバックし、その後プレビューメッセージをクリーンアップします。
プレビューストリーミングはブロックストリーミングとは別です。Telegram でブロックストリーミングが明示的に有効になっている場合、OpenClaw は二重ストリーミングを避けるためにプレビューストリームをスキップします。
Telegram のみの推論ストリーム:
/reasoning streamは生成中に推論をライブプレビューへ送信します- 推論プレビューは最終配信後に削除されます。推論を表示したままにする必要がある場合は
/reasoning onを使用します - 最終回答は推論テキストなしで送信されます
フォーマットと HTML フォールバック
送信テキストは Telegram parse_mode: "HTML" を使用します。
- Markdown 風のテキストは Telegram 安全な HTML にレンダリングされます。
- 生のモデル HTML は、Telegram の解析失敗を減らすためにエスケープされます。
- Telegram が解析済み HTML を拒否した場合、OpenClaw はプレーンテキストとして再試行します。
リンクプレビューはデフォルトで有効であり、channels.telegram.linkPreview: false で無効にできます。
ネイティブコマンドとカスタムコマンド
Telegram コマンドメニュー登録は起動時に setMyCommands で処理されます。
ネイティブコマンドのデフォルト:
commands.native: "auto"は Telegram のネイティブコマンドを有効にします
カスタムコマンドのメニュー項目を追加します:
{
channels: {
telegram: {
customCommands: [
{ command: "backup", description: "Git backup" },
{ command: "generate", description: "Create an image" },
],
},
},
}
ルール:
- 名前は正規化されます(先頭の
/を取り除き、小文字化) - 有効なパターン:
a-z、0-9、_、長さ1..32 - カスタムコマンドはネイティブコマンドを上書きできません
- 競合/重複はスキップされ、ログに記録されます
注記:
- カスタムコマンドはメニュー項目のみです。動作を自動実装するものではありません
- plugin/skill コマンドは、Telegram メニューに表示されていない場合でも、入力すれば引き続き動作できます
ネイティブコマンドが無効な場合、組み込みコマンドは削除されます。設定されていれば、カスタム/plugin コマンドは引き続き登録されることがあります。
よくあるセットアップ失敗:
BOT_COMMANDS_TOO_MUCHを伴うsetMyCommands failedは、トリミング後も Telegram メニューがまだ上限を超えたことを意味します。plugin/skill/カスタムコマンドを減らすか、channels.telegram.commands.nativeを無効にしてください。- 直接の Bot API curl コマンドは動作するのに、
deleteWebhook、deleteMyCommands、またはsetMyCommandsが404: Not Foundで失敗する場合、channels.telegram.apiRootが完全な/bot<TOKEN>エンドポイントに設定されていた可能性があります。apiRootは Bot API ルートのみである必要があり、openclaw doctor --fixは誤って末尾に付いた/bot<TOKEN>を削除します。 getMe returned 401は、Telegram が設定済みの bot token を拒否したことを意味します。botToken、tokenFile、またはTELEGRAM_BOT_TOKENを現在の BotFather token で更新してください。OpenClaw はポーリング前に停止するため、これは Webhook クリーンアップ失敗としては報告されません。- ネットワーク/fetch エラーを伴う
setMyCommands failedは通常、api.telegram.orgへの送信 DNS/HTTPS がブロックされていることを意味します。
デバイスペアリングコマンド(device-pair plugin)
device-pair plugin がインストールされている場合:
/pairがセットアップコードを生成します- iOS アプリにコードを貼り付けます
/pair pendingが保留中のリクエストを一覧表示します(ロール/スコープを含む)- リクエストを承認します:
- 明示的な承認には
/pair approve <requestId> - 保留中のリクエストが 1 件だけの場合は
/pair approve - 最新のものには
/pair approve latest
- 明示的な承認には
セットアップコードには短命のブートストラップトークンが含まれます。組み込みのブートストラップ引き渡しは、プライマリノードトークンを scopes: [] のまま維持します。引き渡された operator token は operator.approvals、operator.read、operator.talk.secrets、operator.write に制限されたままです。ブートストラップのスコープチェックにはロールプレフィックスが付くため、その operator allowlist は operator リクエストだけを満たします。operator 以外のロールでは、それぞれのロールプレフィックス配下のスコープが引き続き必要です。
デバイスが変更された認証詳細(たとえばロール/スコープ/公開鍵)で再試行した場合、以前の保留中リクエストは置き換えられ、新しいリクエストは異なる requestId を使用します。承認前に /pair pending を再実行してください。
詳細: ペアリング。
インラインボタン
インラインキーボードのスコープを設定します:
{
channels: {
telegram: {
capabilities: {
inlineButtons: "allowlist",
},
},
},
}
アカウントごとの上書き:
{
channels: {
telegram: {
accounts: {
main: {
capabilities: {
inlineButtons: "allowlist",
},
},
},
},
},
}
スコープ:
offdmgroupallallowlist(デフォルト)
従来の capabilities: ["inlineButtons"] は inlineButtons: "all" にマップされます。
メッセージアクションの例:
{
action: "send",
channel: "telegram",
to: "123456789",
message: "Choose an option:",
buttons: [
[
{ text: "Yes", callback_data: "yes" },
{ text: "No", callback_data: "no" },
],
[{ text: "Cancel", callback_data: "cancel" }],
],
}
コールバッククリックはテキストとしてエージェントに渡されます:
callback_data: <value>
エージェントと自動化向けの Telegram メッセージアクション
Telegram ツールアクションには次が含まれます:
sendMessage(to、content、任意のmediaUrl、replyToMessageId、messageThreadId)react(chatId、messageId、emoji)deleteMessage(chatId、messageId)editMessage(chatId、messageId、content)createForumTopic(chatId、name、任意のiconColor、iconCustomEmojiId)
チャンネルメッセージアクションは、使いやすいエイリアス(send、react、delete、edit、sticker、sticker-search、topic-create)を公開します。
ゲーティング制御:
channels.telegram.actions.sendMessagechannels.telegram.actions.deleteMessagechannels.telegram.actions.reactionschannels.telegram.actions.sticker(デフォルト: 無効)
注記: edit と topic-create は現在デフォルトで有効であり、個別の channels.telegram.actions.* トグルはありません。
ランタイム送信はアクティブな config/secrets スナップショット(起動/リロード)を使用するため、アクションパスは送信ごとにアドホックな SecretRef 再解決を行いません。
リアクション削除のセマンティクス: /tools/reactions
返信スレッドタグ
Telegram は生成された出力内の明示的な返信スレッドタグをサポートします:
[[reply_to_current]]はトリガー元メッセージに返信します[[reply_to:<id>]]は特定の Telegram メッセージ ID に返信します
channels.telegram.replyToMode は処理を制御します:
off(デフォルト)firstall
返信スレッドが有効で、元の Telegram テキストまたはキャプションが利用可能な場合、OpenClaw はネイティブ Telegram 引用抜粋を自動的に含めます。Telegram はネイティブ引用テキストを 1024 UTF-16 コードユニットに制限しているため、より長いメッセージは先頭から引用され、Telegram が引用を拒否した場合はプレーンな返信にフォールバックします。
注記: off は暗黙的な返信スレッドを無効にします。明示的な [[reply_to_*]] タグは引き続き尊重されます。
フォーラムトピックとスレッドの動作
フォーラムスーパーグループ:
- トピックセッションキーは
:topic:<threadId>を追加します - 返信と入力中表示はトピックスレッドを対象にします
- トピック設定パス:
channels.telegram.groups.<chatId>.topics.<threadId>
一般トピック(threadId=1)の特別扱い:
- メッセージ送信では
message_thread_idを省略します(Telegram はsendMessage(...thread_id=1)を拒否します) - 入力中アクションには引き続き
message_thread_idを含めます
トピック継承: トピック項目は、上書きされない限りグループ設定を継承します(requireMention、allowFrom、skills、systemPrompt、enabled、groupPolicy)。
agentId はトピック専用であり、グループのデフォルトからは継承されません。
トピックごとのエージェントルーティング: 各トピックは、トピック設定で agentId を設定することで、別のエージェントにルーティングできます。これにより、各トピックに独自の隔離されたワークスペース、メモリ、セッションが与えられます。例:
{
channels: {
telegram: {
groups: {
"-1001234567890": {
topics: {
"1": { agentId: "main" }, // General topic → main agent
"3": { agentId: "zu" }, // Dev topic → zu agent
"5": { agentId: "coder" } // Code review → coder agent
}
}
}
}
}
}
その後、各トピックには独自のセッションキーがあります: agent:zu:telegram:group:-1001234567890:topic:3
永続 ACP トピックバインディング: フォーラムトピックは、トップレベルの型付き ACP バインディング(type: "acp"、match.channel: "telegram"、peer.kind: "group"、および -1001234567890:topic:42 のようなトピック修飾 ID を持つ bindings[])を通じて ACP ハーネスセッションを固定できます。現在はグループ/スーパーグループ内のフォーラムトピックにスコープされています。ACP Agents を参照してください。
チャットからのスレッドバインド ACP spawn: /acp spawn <agent> --thread here|auto は現在のトピックを新しい ACP セッションにバインドします。後続のやり取りはそこへ直接ルーティングされます。OpenClaw はトピック内に spawn 確認を固定します。channels.telegram.threadBindings.spawnSessions が有効なままである必要があります(デフォルト: true)。
テンプレートコンテキストは MessageThreadId と IsForum を公開します。message_thread_id を持つ DMチャットは、デフォルトでフラットセッション上の DMルーティングと返信メタデータを維持します。threadReplies: "inbound"、threadReplies: "always"、requireTopic: true、または一致するトピック設定で構成されている場合にのみ、スレッド対応のセッションキーを使用します。アカウントのデフォルトにはトップレベルの channels.telegram.dm.threadReplies を、1つの DM には direct.<chatId>.threadReplies を使用します。
音声、動画、ステッカー
音声メッセージ
Telegram はボイスメモと音声ファイルを区別します。
- デフォルト: 音声ファイルの動作
- エージェントの返信内のタグ
[[audio_as_voice]]でボイスメモ送信を強制 - 受信したボイスメモの文字起こしは、エージェントコンテキスト内で機械生成の信頼できないテキストとして囲まれます。メンション検出は引き続き生の文字起こしを使用するため、メンションで制御された音声メッセージは動作し続けます。
メッセージアクションの例:
{
action: "send",
channel: "telegram",
to: "123456789",
media: "https://example.com/voice.ogg",
asVoice: true,
}
動画メッセージ
Telegram は動画ファイルとビデオメモを区別します。
メッセージアクションの例:
{
action: "send",
channel: "telegram",
to: "123456789",
media: "https://example.com/video.mp4",
asVideoNote: true,
}
ビデオメモはキャプションに対応していません。指定されたメッセージテキストは別途送信されます。
ステッカー
受信ステッカーの処理:
- 静的 WEBP: ダウンロードして処理されます(プレースホルダー
<media:sticker>) - アニメーション TGS: スキップされます
- 動画 WEBM: スキップされます
ステッカーコンテキストフィールド:
Sticker.emojiSticker.setNameSticker.fileIdSticker.fileUniqueIdSticker.cachedDescription
ステッカーキャッシュファイル:
~/.openclaw/telegram/sticker-cache.json
ステッカーは(可能な場合)一度説明され、繰り返しのビジョン呼び出しを減らすためにキャッシュされます。
ステッカーアクションを有効化:
{
channels: {
telegram: {
actions: {
sticker: true,
},
},
},
}
ステッカー送信アクション:
{
action: "sticker",
channel: "telegram",
to: "123456789",
fileId: "CAACAgIAAxkBAAI...",
}
キャッシュ済みステッカーを検索:
{
action: "sticker-search",
channel: "telegram",
query: "cat waving",
limit: 5,
}
リアクション通知
Telegram のリアクションは message_reaction 更新として届きます(メッセージペイロードとは別です)。
有効な場合、OpenClaw は次のようなシステムイベントをキューに入れます。
Telegram reaction added: 👍 by Alice (@alice) on msg 42
設定:
channels.telegram.reactionNotifications:off | own | all(デフォルト:own)channels.telegram.reactionLevel:off | ack | minimal | extensive(デフォルト:minimal)
注:
ownはボットが送信したメッセージへのユーザーリアクションのみを意味します(送信済みメッセージキャッシュによるベストエフォート)。- リアクションイベントも Telegram のアクセス制御(
dmPolicy、allowFrom、groupPolicy、groupAllowFrom)に従います。許可されていない送信者は破棄されます。 - Telegram はリアクション更新でスレッド ID を提供しません。
- 非フォーラムグループはグループチャットセッションにルーティングされます
- フォーラムグループは、正確な発生元トピックではなく、グループの一般トピックセッション(
:topic:1)にルーティングされます
ポーリング/Webhook の allowed_updates には message_reaction が自動的に含まれます。
Ack リアクション
ackReaction は、OpenClaw が受信メッセージを処理している間に確認用の絵文字を送信します。
解決順序:
channels.telegram.accounts.<accountId>.ackReactionchannels.telegram.ackReactionmessages.ackReaction- エージェントのアイデンティティ絵文字フォールバック(
agents.list[].identity.emoji、なければ "👀")
注:
- Telegram は Unicode 絵文字(例: "👀")を想定します。
- チャネルまたはアカウントのリアクションを無効化するには
""を使用します。
Telegram イベントとコマンドからの設定書き込み
チャネル設定の書き込みはデフォルトで有効です(configWrites !== false)。
Telegram によってトリガーされる書き込みには次が含まれます。
channels.telegram.groupsを更新するためのグループ移行イベント(migrate_to_chat_id)/config setと/config unset(コマンドの有効化が必要)
無効化:
{
channels: {
telegram: {
configWrites: false,
},
},
}
ロングポーリングと Webhook
デフォルトはロングポーリングです。Webhook モードの場合は channels.telegram.webhookUrl と channels.telegram.webhookSecret を設定します。任意で webhookPath、webhookHost、webhookPort(デフォルトは /telegram-webhook、127.0.0.1、8787)を設定できます。
ロングポーリングモードでは、OpenClaw は更新が正常にディスパッチされた後にのみ再起動ウォーターマークを永続化します。ハンドラーが失敗した場合、その更新は同じプロセス内で再試行可能なままとなり、再起動時の重複排除のために完了済みとして書き込まれません。
ローカルリスナーは 127.0.0.1:8787 にバインドします。公開入口には、ローカルポートの前にリバースプロキシを置くか、意図的に webhookHost: "0.0.0.0" を設定します。
Webhook モードは、Telegram に 200 を返す前に、リクエストガード、Telegram シークレットトークン、JSON 本文を検証します。
その後 OpenClaw は、ロングポーリングで使用されるものと同じチャット単位/トピック単位のボットレーンを通じて更新を非同期に処理するため、遅いエージェントターンが Telegram の配信 ACK を保持しません。
制限、再試行、CLI ターゲット
channels.telegram.textChunkLimitのデフォルトは 4000 です。channels.telegram.chunkMode="newline"は長さによる分割の前に段落境界(空行)を優先します。channels.telegram.mediaMaxMb(デフォルト 100)は、受信および送信の Telegram メディアサイズを制限します。channels.telegram.mediaGroupFlushMs(デフォルト 500)は、OpenClaw が Telegram アルバム/メディアグループを1つの受信メッセージとしてディスパッチする前にバッファする時間を制御します。アルバムの一部が遅れて届く場合は増やし、アルバム返信のレイテンシを下げるには減らします。channels.telegram.timeoutSecondsは Telegram API クライアントのタイムアウトを上書きします(未設定の場合は grammY のデフォルトが適用されます)。ボットクライアントは、構成値が 60 秒の送信テキスト/タイピングリクエストガードを下回る場合にクランプするため、OpenClaw のトランスポートガードとフォールバックが実行される前に grammY が見える返信配信を中止することはありません。ロングポーリングでは引き続き 45 秒のgetUpdatesリクエストガードを使用するため、アイドルポーリングが無期限に放棄されることはありません。channels.telegram.pollingStallThresholdMsのデフォルトは120000です。誤検知のポーリング停止再起動に限り、30000から600000の間で調整してください。- グループコンテキスト履歴は
channels.telegram.historyLimitまたはmessages.groupChat.historyLimit(デフォルト 50)を使用します。0で無効化します。 - 返信/引用/転送の補足コンテキストは、現時点では受信したまま渡されます。
- Telegram の許可リストは主に、完全な補足コンテキストの編集境界ではなく、誰がエージェントをトリガーできるかを制御します。
- DM 履歴の制御:
channels.telegram.dmHistoryLimitchannels.telegram.dms["<user_id>"].historyLimit
channels.telegram.retry設定は、回復可能な送信 API エラーに対して Telegram 送信ヘルパー(CLI/ツール/アクション)に適用されます。受信の最終返信配信も Telegram の接続前失敗に対して境界付きの安全送信再試行を使用しますが、見えるメッセージが重複する可能性がある曖昧な送信後ネットワークエンベロープは再試行しません。
CLI とメッセージツールの送信ターゲットには、数値のチャット ID、ユーザー名、またはフォーラムトピックターゲットを使用できます。
openclaw message send --channel telegram --target 123456789 --message "hi"
openclaw message send --channel telegram --target @name --message "hi"
openclaw message send --channel telegram --target -1001234567890:topic:42 --message "hi topic"
Telegram ポーリングは openclaw message poll を使用し、フォーラムトピックに対応しています。
openclaw message poll --channel telegram --target 123456789 \
--poll-question "Ship it?" --poll-option "Yes" --poll-option "No"
openclaw message poll --channel telegram --target -1001234567890:topic:42 \
--poll-question "Pick a time" --poll-option "10am" --poll-option "2pm" \
--poll-duration-seconds 300 --poll-public
Telegram 専用のポーリングフラグ:
--poll-duration-seconds(5-600)--poll-anonymous--poll-public- フォーラムトピック用の
--thread-id(または:topic:ターゲットを使用)
Telegram 送信は次にも対応しています。
channels.telegram.capabilities.inlineButtonsで許可されている場合、インラインキーボード用のbuttonsブロックを持つ--presentation- ボットがそのチャットでピン留めできる場合にピン留め配信を要求する
--pinまたは--delivery '{"pin":true}' - 送信画像と GIF を、圧縮写真またはアニメーションメディアアップロードではなくドキュメントとして送信する
--force-document
アクション制御:
channels.telegram.actions.sendMessage=falseは、ポーリングを含む送信 Telegram メッセージを無効化しますchannels.telegram.actions.poll=falseは、通常の送信を有効にしたまま Telegram ポーリング作成を無効化します
Telegram での exec 承認
Telegram は承認者 DM で exec 承認に対応し、必要に応じて発生元のチャットまたはトピックにプロンプトを投稿できます。承認者は数値の Telegram ユーザー ID である必要があります。
設定パス:
channels.telegram.execApprovals.enabled(少なくとも1人の承認者を解決できる場合に自動有効化)channels.telegram.execApprovals.approvers(commands.ownerAllowFromの数値オーナー ID にフォールバック)channels.telegram.execApprovals.target:dm(デフォルト) |channel|bothagentFilter,sessionFilter
channels.telegram.allowFrom、groupAllowFrom、defaultTo は、誰がボットと会話できるか、および通常の返信をどこに送信するかを制御します。これらは誰かを exec 承認者にするものではありません。コマンドオーナーがまだ存在しない場合、最初に承認された DM ペアリングが commands.ownerAllowFrom をブートストラップするため、1人オーナー構成でも execApprovals.approvers の下で ID を重複させずに動作します。
チャネル配信ではコマンドテキストがチャットに表示されます。信頼済みのグループ/トピックでのみ channel または both を有効化してください。プロンプトがフォーラムトピックに届いた場合、OpenClaw は承認プロンプトとフォローアップのためにトピックを保持します。exec 承認はデフォルトで 30 分後に期限切れになります。
インライン承認ボタンでは、channels.telegram.capabilities.inlineButtons がターゲットサーフェス(dm、group、または all)を許可していることも必要です。plugin: が接頭辞の承認 ID は Plugin 承認を通じて解決されます。それ以外はまず exec 承認を通じて解決されます。
Exec 承認 を参照してください。
エラー返信制御
エージェントが配信エラーまたはプロバイダーエラーに遭遇した場合、Telegram はエラーテキストで返信するか、それを抑制できます。この動作は2つの設定キーで制御します。
| キー | 値 | デフォルト | 説明 |
|---|---|---|---|
channels.telegram.errorPolicy |
reply, silent |
reply |
reply はチャットに親しみやすいエラーメッセージを送信します。silent はエラー返信を完全に抑制します。 |
channels.telegram.errorCooldownMs |
数値(ms) | 60000 |
同じチャットへのエラー返信間の最小時間。障害中のエラースパムを防ぎます。 |
アカウント単位、グループ単位、トピック単位の上書きに対応しています(他の Telegram 設定キーと同じ継承)。
{
channels: {
telegram: {
errorPolicy: "reply",
errorCooldownMs: 120000,
groups: {
"-1001234567890": {
errorPolicy: "silent", // suppress errors in this group
},
},
},
},
}
トラブルシューティング
ボットがメンションなしのグループメッセージに応答しない
requireMention=falseの場合、Telegram のプライバシーモードは完全な可視性を許可している必要があります。- BotFather:
/setprivacy-> Disable - その後、グループからボットを削除して再追加します
- BotFather:
openclaw channels statusは、設定がメンションなしのグループメッセージを想定している場合に警告します。openclaw channels status --probeは明示的な数値グループ ID を確認できます。ワイルドカード"*"はメンバーシップ確認のプローブ対象にできません。- クイックセッションテスト:
/activation always。
ボットがグループメッセージをまったく認識しない
channels.telegram.groupsが存在する場合、グループが一覧に含まれている必要があります(または"*"を含めます)- グループ内のボットメンバーシップを確認します
- スキップ理由についてログを確認します:
openclaw logs --follow
コマンドが部分的にしか動作しない、またはまったく動作しない
- 送信者 ID を承認します(ペアリングや数値
allowFrom) - グループポリシーが
openの場合でも、コマンド承認は引き続き適用されます BOT_COMMANDS_TOO_MUCHを伴うsetMyCommands failedは、ネイティブメニューの項目が多すぎることを意味します。Plugin/Skills/カスタムコマンドを減らすか、ネイティブメニューを無効にしてくださいdeleteMyCommands/setMyCommandsの起動時呼び出しとsendChatActionの入力中呼び出しは制限され、リクエストタイムアウト時には Telegram のトランスポートフォールバック経由で 1 回再試行されます。永続的なネットワーク/フェッチエラーは通常、api.telegram.orgへの DNS/HTTPS 到達性の問題を示します
起動時に未承認トークンが報告される
getMe returned 401は、設定されたボットトークンに対する Telegram 認証エラーです。- BotFather でボットトークンを再コピーまたは再生成し、デフォルトアカウントの
channels.telegram.botToken、channels.telegram.tokenFile、channels.telegram.accounts.<id>.botToken、またはTELEGRAM_BOT_TOKENを更新します。 - 起動時の
deleteWebhook 401 Unauthorizedも認証エラーです。これを「webhook が存在しない」として扱うと、同じ不正なトークンによる失敗を後続の API 呼び出しまで先送りするだけです。
ポーリングまたはネットワークの不安定さ
- Node 22+ とカスタム fetch/proxy の組み合わせでは、AbortSignal 型が一致しない場合に即時中断動作が発生する可能性があります。
- 一部のホストは
api.telegram.orgを IPv6 で先に解決します。IPv6 の外向き通信が壊れていると、Telegram API の断続的な失敗を引き起こす可能性があります。 - ログに
TypeError: fetch failedまたはNetwork request for 'getUpdates' failed!が含まれる場合、OpenClaw はこれらを回復可能なネットワークエラーとして再試行するようになりました。 - ポーリング起動中、OpenClaw は成功した起動時
getMeプローブを grammY に再利用するため、ランナーは最初のgetUpdatesの前に 2 回目のgetMeを必要としません。 - ポーリング起動中に
deleteWebhookが一時的なネットワークエラーで失敗した場合、OpenClaw は別のポーリング前コントロールプレーン呼び出しを行わず、ロングポーリングへ進みます。まだアクティブな webhook はgetUpdatesの競合として表面化します。その後、OpenClaw は Telegram トランスポートを再構築し、webhook クリーンアップを再試行します。 - Telegram ソケットが短い固定周期でリサイクルされる場合は、低い
channels.telegram.timeoutSecondsを確認してください。ボットクライアントは、外向きリクエストとgetUpdatesリクエストのガード値を下回る設定値をクランプしますが、古いリリースではこの値がそれらのガード値を下回ると、すべてのポーリングまたは返信が中断される可能性がありました。 - ログに
Polling stall detectedが含まれる場合、OpenClaw はデフォルトで、ロングポールの生存確認が 120 秒間完了しないとポーリングを再起動し、Telegram トランスポートを再構築します。 openclaw channels status --probeとopenclaw doctorは、実行中のポーリングアカウントが起動猶予後にgetUpdatesを完了していない場合、実行中の webhook アカウントが起動猶予後にsetWebhookを完了していない場合、または最後に成功したポーリングトランスポートアクティビティが古くなっている場合に警告します。- 長時間実行される
getUpdates呼び出しが正常なのにホストが誤ったポーリング停止再起動を報告する場合にのみ、channels.telegram.pollingStallThresholdMsを増やしてください。永続的な停止は通常、ホストとapi.telegram.orgの間の proxy、DNS、IPv6、または TLS の外向き通信の問題を示します。 - Telegram は Bot API トランスポートについて、
HTTP_PROXY、HTTPS_PROXY、ALL_PROXYとそれらの小文字バリアントを含むプロセス proxy env も尊重します。NO_PROXY/no_proxyは引き続きapi.telegram.orgをバイパスできます。 - サービス環境で OpenClaw 管理 proxy が
OPENCLAW_PROXY_URLを通じて設定され、標準の proxy env が存在しない場合、Telegram も Bot API トランスポートにその URL を使用します。 - 直接の外向き通信/TLS が不安定な VPS ホストでは、Telegram API 呼び出しを
channels.telegram.proxy経由でルーティングします。
channels:
telegram:
proxy: socks5://<user>:<password>@proxy-host:1080
- Node 22+ はデフォルトで
autoSelectFamily=true(WSL2 を除く)です。Telegram の DNS 結果順序は、OPENCLAW_TELEGRAM_DNS_RESULT_ORDER、次にchannels.telegram.network.dnsResultOrder、次にNODE_OPTIONS=--dns-result-order=ipv4firstなどのプロセスデフォルトを尊重します。いずれも適用されない場合、Node 22+ はipv4firstにフォールバックします。 - ホストが WSL2 であるか、IPv4 のみの動作のほうが明示的にうまく動作する場合は、ファミリー選択を強制します。
channels:
telegram:
network:
autoSelectFamily: false
- RFC 2544 ベンチマーク範囲の回答(
198.18.0.0/15)は、デフォルトで Telegram メディアダウンロードにすでに許可されています。信頼済みの fake-IP または透過 proxy が、メディアダウンロード中にapi.telegram.orgを他のプライベート/内部/特殊用途アドレスへ書き換える場合は、Telegram 専用バイパスを有効にできます。
channels:
telegram:
network:
dangerouslyAllowPrivateNetwork: true
- 同じオプトインは、
channels.telegram.accounts.<accountId>.network.dangerouslyAllowPrivateNetworkでアカウントごとにも利用できます。 - proxy が Telegram メディアホストを
198.18.x.xに解決する場合は、まず危険なフラグをオフのままにしてください。Telegram メディアはデフォルトで RFC 2544 ベンチマーク範囲をすでに許可しています。
- 環境オーバーライド(一時的):
OPENCLAW_TELEGRAM_DISABLE_AUTO_SELECT_FAMILY=1OPENCLAW_TELEGRAM_ENABLE_AUTO_SELECT_FAMILY=1OPENCLAW_TELEGRAM_DNS_RESULT_ORDER=ipv4first
- DNS の回答を検証します。
dig +short api.telegram.org A
dig +short api.telegram.org AAAA
詳細ヘルプ: チャンネルのトラブルシューティング。
設定リファレンス
主なリファレンス: 設定リファレンス - Telegram。
高シグナルの Telegram フィールド
- 起動/認証:
enabled,botToken,tokenFile,accounts.*(tokenFileは通常ファイルを指す必要があります。シンボリックリンクは拒否されます) - アクセス制御:
dmPolicy,allowFrom,groupPolicy,groupAllowFrom,groups,groups.*.topics.*, トップレベルのbindings[](type: "acp") - exec 承認:
execApprovals,accounts.*.execApprovals - コマンド/メニュー:
commands.native,commands.nativeSkills,customCommands - スレッド/返信:
replyToMode,dm.threadReplies,direct.*.threadReplies - ストリーミング:
streaming(プレビュー),streaming.preview.toolProgress,blockStreaming - 書式設定/配信:
textChunkLimit,chunkMode,linkPreview,responsePrefix - メディア/ネットワーク:
mediaMaxMb,mediaGroupFlushMs,timeoutSeconds,pollingStallThresholdMs,retry,network.autoSelectFamily,network.dangerouslyAllowPrivateNetwork,proxy - カスタム API ルート:
apiRoot(Bot API ルートのみ。/bot<TOKEN>は含めないでください) - webhook:
webhookUrl,webhookSecret,webhookPath,webhookHost - アクション/機能:
capabilities.inlineButtons,actions.sendMessage|editMessage|deleteMessage|reactions|sticker - リアクション:
reactionNotifications,reactionLevel - エラー:
errorPolicy,errorCooldownMs - 書き込み/履歴:
configWrites,historyLimit,dmHistoryLimit,dms.*.historyLimit