Messages and delivery
メッセージ
受信メッセージは、ルーティング、重複排除/デバウンス、エージェント実行、送信処理の順に進みます。
受信メッセージ -> ルーティング/バインディング -> セッションキー -> 重複排除 + デバウンス -> キュー(実行がすでにアクティブな場合) -> エージェント実行(ストリーミング + ツール) -> 送信返信(チャンネル制限 + チャンク分割)主な設定項目:
- プレフィックス、キューイング、受信デバウンス、グループ動作には
messages.*。 - ブロックストリーミング、チャンク分割、サイレント返信のデフォルトには
agents.defaults.*。 - チャンネルごとの上限とストリーミング切り替えには、チャンネルオーバーライド(
channels.telegram.*、channels.whatsapp.*など)。
完全なスキーマについては、設定を参照してください。
受信メッセージの重複排除
チャンネルは再接続後に同じメッセージを再配信する場合があります。OpenClawは、エージェントスコープ、チャンネルルート(チャンネル + ピア + アカウント + スレッド)、メッセージIDをキーとするメモリ内キャッシュを保持するため、再配信されたメッセージが2回目のエージェント実行をトリガーすることはありません。キャッシュエントリは20分後、または追跡中のエントリが5000件に達した時点の、いずれか早い方で期限切れになります。
受信メッセージのデバウンス
同じ送信者から短時間に連続して送られたテキストメッセージは、messages.inboundを使用して1回のエージェントターンにまとめられます。デバウンスのスコープはチャンネル + 会話ごとで、返信のスレッド化/IDには最新のメッセージが使用されます。
{ messages: { inbound: { debounceMs: 2000, byChannel: { discord: 1500, slack: 1500, whatsapp: 5000, }, }, },}- デバウンスはテキストのみのメッセージに適用されます。メディア/添付ファイルは直ちにフラッシュされます。
- 制御コマンド(停止/中止/ステータスなど)はデバウンスを迂回し、直ちにディスパッチされます。
- デフォルトでは無効:
messages.inbound.debounceMsには組み込みのデフォルト値がないため、グローバルまたはチャンネルごとに設定した場合にのみデバウンスが有効になります。 - iMessageの
coalesceSameSenderDmsオプトインは唯一の例外です。同じ送信者からのすべてのDMテキスト(コマンドを含む)を、AppleのコマンドとURLの分割送信が1回のターンとして到着するのに十分な時間保持します。この設定にかかわらず、グループチャットは常に即時にディスパッチされます。
セッションとデバイス
セッションはクライアントではなく、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 レンダリング、診断、メディア配信、およびプラグイン用のランタイムメタデータです。
toolResult.detailsは、プロバイダーへのリプレイ前および Compaction 入力前に除去されます。- 永続化されたセッショントランスクリプトでは、制限内の
detailsのみが保持されます。サイズ超過のメタデータは、persistedDetailsTruncated: trueと記された簡潔な要約に置き換えられます。 - Plugin とツールは、モデルが読む必要のあるテキストを
detailsだけでなくcontentに格納する必要があります。
キューイングとフォローアップ
実行がすでにアクティブな場合、受信メッセージはデフォルトでその実行に指示を与えます。messages.queue でモードを制御します。
| モード | 動作 |
|---|---|
steer(デフォルト) |
新しいプロンプトをアクティブな実行に注入します。 |
followup |
アクティブな実行の完了後にメッセージを実行します。 |
collect |
互換性のあるメッセージを後続の1ターンにまとめます。 |
interrupt |
アクティブな実行を中止し、最新のプロンプトを開始します。 |
デフォルトでは、messages.queue.debounceMs は 500ms(steer、followup、collect のバッチ処理に同様に適用)、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(ブロック応答間の人間らしい間隔)- チャネルごとのオーバーライド:ネストされたストリーミング設定を持つチャネル(Telegram、Discord、Slack、iMessage、Microsoft Teams)では
*.streaming.block.enabledと*.streaming.block.coalesce、ネストされたストリーミング設定を持たないチャネルではフラットな*.blockStreaming/*.blockStreamingCoalesce。Telegram を含むすべてのチャネルで、明示的に有効にしない限りブロックストリーミングは無効です。
詳細:ストリーミングとチャンク分割。
推論の表示とトークン
/reasoning on|off|streamで表示を制御します。- モデルが推論内容を生成する場合、その内容もトークン使用量に含まれます。
- Telegram は、最終配信後に削除される一時的な下書きバブルへの推論ストリーミングをサポートします。推論出力を永続化するには
/reasoning onを使用します。
詳細:思考と推論ディレクティブとトークン使用量。
プレフィックス、スレッド、返信
- 送信プレフィックスのカスケード:
messages.responsePrefix、channels.<channel>.responsePrefix、channels.<channel>.accounts.<id>.responsePrefix。WhatsApp には受信プレフィックス用のchannels.whatsapp.messagePrefixもあります。 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 が有効な場合にのみ表示されます。
サイレントトークンだけの応答はすべてのサーフェスで破棄されるため、親セッションはセンチネルテキストを代替の会話文に書き換えることなく静かなままになります。
関連項目
- メッセージライフサイクルのリファクタリング - 永続的な送受信設計の目標
- ストリーミング - リアルタイムのメッセージ配信
- 再試行 - メッセージ配信の再試行動作
- キュー - メッセージ処理キュー
- チャネル - メッセージングプラットフォーム連携