Messages and delivery
メッセージ
受信メッセージは、ルーティング、重複排除/デバウンス、エージェント実行、送信配信の順に処理されます。
受信メッセージ -> ルーティング/バインディング -> セッションキー -> 重複排除 + デバウンス -> キュー(実行がすでにアクティブな場合) -> エージェント実行(ストリーミング + ツール) -> 送信返信(チャネル制限 + チャンク分割)主な設定項目:
messages.*:プレフィックス、キューイング、受信デバウンス、グループ動作。agents.defaults.*:ブロックストリーミング、チャンク分割、サイレント返信のデフォルト。- チャネルごとの上限とストリーミング切り替えに使用するチャネルオーバーライド(
channels.telegram.*、channels.whatsapp.*など)。
完全なスキーマについては、設定を参照してください。
受信メッセージの重複排除
チャネルでは、再接続後に同じメッセージが再配信される場合があります。OpenClaw は、エージェントスコープ、チャネルルート(チャネル + ピア + アカウント + スレッド)、メッセージ ID をキーとするインメモリキャッシュを保持するため、再配信されたメッセージによってエージェントが再度実行されることはありません。キャッシュエントリは、20 分経過するか、追跡対象が 5000 エントリに達した時点のいずれか早い方で期限切れになります。
受信メッセージのデバウンス
同じ送信者から短時間に連続して送られたテキストメッセージは、messages.inbound を使用して 1 回のエージェントターンにまとめられます。デバウンスはチャネル + 会話単位で適用され、返信のスレッド化/ID には最新のメッセージが使用されます。
{ messages: { inbound: { debounceMs: 2000, byChannel: { discord: 1500, slack: 1500, whatsapp: 5000, }, }, },}- デバウンスはテキストのみのメッセージに適用されます。メディア/添付ファイルは即座にフラッシュされます。
- 制御コマンド(停止/中止/ステータスなど)はデバウンスを迂回し、即座にディスパッチされます。
- デフォルトでは無効です。
messages.inbound.debounceMsには組み込みのデフォルト値がないため、デバウンスはグローバルまたはチャネルごとに設定した場合にのみ有効になります。 - iMessage にも同じ汎用デバウンスポリシーが適用されます。
imsg0.13.1 以降では、Apple の URL プレビューによる分割送信が OpenClaw に届く前に結合されるため、iMessage 固有のデバウンス設定は不要です。
セッションとデバイス
セッションはクライアントではなく Gateway が所有します。
- ダイレクトチャットは、エージェントのメインセッションキーに統合されます。
- グループ/チャネルには、それぞれ独自のセッションキーが割り当てられます。
- セッションストアとトランスクリプトは Gateway ホスト上に保存されます。
複数のデバイス/チャネルを同じセッションに対応付けることはできますが、履歴がすべてのクライアントに完全に同期されるわけではありません。コンテキストの不一致を避けるため、長い会話には 1 台のプライマリデバイスを使用してください。Control UI と TUI には常に Gateway が管理するセッショントランスクリプトが表示されるため、これらが信頼できる情報源となります。
詳細:セッション管理。
プロンプト本文と履歴コンテキスト
チャネル Plugin は、優先度の高いものから順に、受信コンテキストの複数のテキストフィールドを設定します。
| フィールド | 用途 |
|---|---|
BodyForAgent |
現在のターンでモデルに提示されるテキスト。未設定の場合は CommandBody/RawBody/Body にフォールバックします。 |
BodyForCommands |
ディレクティブ/コマンドの解析に使用されるクリーンなテキスト。未設定の場合は CommandBody/RawBody/Body にフォールバックします。 |
CommandBody |
レガシーな中間本文。BodyForCommands を優先してください。 |
RawBody |
CommandBody の非推奨エイリアス。 |
Body |
レガシーなプロンプト本文。チャネルエンベロープや履歴ラッパーが含まれる場合があります。 |
チャネルが履歴を提供する場合、次の要素でラップします。
[Chat messages since your last reply - for context][Current message - respond to this]
ダイレクトチャット以外(グループ/チャネル/ルーム)では、現在のメッセージ本文に、履歴エントリと同じ形式の送信者ラベルが付加されます。ディレクティブの除去は現在のメッセージ部分にのみ適用されるため、履歴はそのまま保持されます。履歴をラップするチャネルでは、BodyForCommands(またはレガシーな CommandBody/RawBody)に元のメッセージテキストを設定し、Body には結合後のプロンプトを保持する必要があります。
履歴バッファには保留中のメッセージだけが含まれます。実行をトリガーしなかったグループメッセージ(メンションが必須のメッセージなど)は含まれ、セッショントランスクリプトにすでに記録されているメッセージは除外されます。構造化された履歴、返信、転送、およびチャネルメタデータは、プロンプトの組み立て時に信頼されていないユーザーロールのコンテキストブロックとしてレンダリングされます。
履歴サイズは、messages.groupChat.historyLimit(グローバルデフォルト)または channels.slack.historyLimit や channels.telegram.accounts.<id>.historyLimit などのチャネル別オーバーライドで設定します(無効にするには 0 を設定します)。
ツール結果のメタデータ
ツール結果の content はモデルから見える結果であり、details は UI レンダリング、診断、メディア配信、Plugin に使用されるランタイムメタデータです。
toolResult.detailsは、プロバイダーへの再送前および Compaction の入力前に除去されます。- 永続化されたセッショントランスクリプトには、サイズ制限された
detailsのみが保持されます。サイズが大きすぎるメタデータは、persistedDetailsTruncated: trueとマークされた簡潔な要約に置き換えられます。 - Plugin とツールは、モデルが読む必要のあるテキストを
detailsだけでなく、contentに格納する必要があります。
キューイングとフォローアップ
実行がすでにアクティブな場合、デフォルトでは受信メッセージがその実行に誘導されます。messages.queue でモードを制御します。
| モード | 動作 |
|---|---|
steer(デフォルト) |
新しいプロンプトをアクティブな実行に注入します。 |
followup |
アクティブな実行の完了後にメッセージを実行します。 |
collect |
互換性のあるメッセージを、後続の 1 ターンにまとめます。 |
interrupt |
アクティブな実行を中止してから、最新のプロンプトを開始します。 |
キューでは、誘導、フォローアップ、収集のバッチ処理に組み込みの 500ms デバウンスが使用されます。messages.queue.cap のデフォルトはキュー内の 20 メッセージで、messages.queue.drop のデフォルトは summarize です(old と new も使用できます)。チャネル別オーバーライドは、messages.queue.byChannel と messages.queue.debounceMsByChannel で設定します。
チャネルによる実行の所有
チャネル Plugin は、メッセージがセッションキューに入る前に、順序の保持、入力のデバウンス、トランスポートのバックプレッシャー適用を行う場合があります。ただし、エージェントターン自体に対して別個のタイムアウトを課すべきではありません。メッセージがセッションにルーティングされた後は、セッション、ツール、ランタイムのライフサイクルが長時間実行される処理を管理するため、すべてのチャネルが遅いターンを一貫して報告し、回復できます。
ストリーミング、チャンク分割、バッチ処理
ブロックストリーミングは、モデルがテキストブロックを生成するたびに部分的な返信を送信します。チャンク分割ではチャネルのテキスト制限が考慮され、フェンス付きコードの途中で分割されることを防ぎます。
agents.defaults.blockStreamingDefault(on|off、デフォルトはoff)agents.defaults.blockStreamingBreak(text_end|message_end)agents.defaults.blockStreamingChunk(minChars|maxChars|breakPreference)agents.defaults.blockStreamingCoalesce(アイドル時間に基づくバッチ処理)agents.defaults.humanDelay(ブロック返信間の人間らしい間隔)- チャネルオーバーライド:同梱チャネルでは
*.streaming.block.enabledと*.streaming.block.coalesceを使用します。古いフラットキーはopenclaw doctor --fixによって移行されます。Telegram を含むすべてのチャネルで、明示的に有効にしない限りブロックストリーミングは無効です。QQ Bot は例外です。streaming.blockキーがなく、channels.qqbot.streaming.modeが"off"でない限り、ブロック返信をストリーミングします。
詳細:ストリーミング + チャンク分割。
推論の可視性とトークン
/reasoning on|off|streamで可視性を制御します。- モデルが推論内容を生成する場合、その内容もトークン使用量にカウントされます。
- Telegram は、最終配信後に削除される一時的な下書きバブルへの推論のストリーミングをサポートします。推論出力を永続化するには
/reasoning onを使用します。
詳細:思考 + 推論ディレクティブおよびトークン使用量。
プレフィックス、スレッド化、返信
- 送信プレフィックスは
channels.<channel>.responsePrefixとchannels.<channel>.accounts.<id>.responsePrefixにあります。アカウントの値が優先されます。これらの正規フィールドが未設定の場合、Doctor はグローバルフォールバックを設定済みのチャネルブロックにコピーします。messages.responsePrefixは、暗黙的チャネルとカスタムチャネルのフォールバックとして引き続き使用されます。 replyToModeとチャネル別デフォルトによる返信のスレッド化。
詳細:設定および各チャネルのドキュメント。
サイレント返信
サイレントトークン NO_REPLY(大文字と小文字を区別しないため、no_reply も一致)は、「ユーザーに見える返信を配信しない」ことを意味します。生成された TTS 音声など、ターンに保留中のツールメディアも含まれる場合、OpenClaw はサイレントテキストを除去しますが、メディア添付ファイルは引き続き配信します。
サイレンスポリシーは会話タイプに応じて解決されます。
- ダイレクト会話には、
NO_REPLYのプロンプトガイダンスは適用されません。ダイレクト実行が誤ってサイレントトークンだけを返した場合、OpenClaw はそれを書き換えたり配信したりせず、抑止します。 - グループ/チャネルでは、デフォルトでサイレンスが許可されます。
message_toolの可視返信モードでは、サイレンスはモデルがmessage(action=send)を呼び出さないことを意味します。 - 内部オーケストレーションでは、デフォルトでサイレンスが許可されます。
デフォルトは agents.defaults.silentReply 配下にあります。surfaces.<id>.silentReply では、サーフェスごとにグループ/内部ポリシーをオーバーライドできます。
OpenClaw は、ダイレクトチャット以外で発生した汎用的な内部ランナー障害にもサイレント返信を使用するため、グループ/チャネルには Gateway の定型エラーメッセージが表示されません。認証情報の欠如、レート制限、過負荷通知など、ユーザー向けの復旧メッセージが設定された分類済みの障害は、引き続き配信できます。ダイレクトチャットには、デフォルトで簡潔な障害メッセージが表示されます。ランナーの生の詳細は、/verbose full が有効な場合にのみ表示されます。
サイレントトークンだけの返信はすべてのサーフェスで破棄されるため、親セッションではセンチネルテキストがフォールバックの会話文に書き換えられず、静かな状態が維持されます。
関連項目
- メッセージライフサイクルのリファクタリング - 永続的な送受信設計の目標
- ストリーミング - リアルタイムのメッセージ配信
- 再試行 - メッセージ配信の再試行動作
- キュー - メッセージ処理キュー
- チャネル - メッセージングプラットフォームとの統合