メインコンテンツへスキップ
OpenClaw には 2 つの独立したストリーミング層があり、現時点ではチャンネルメッセージへの真の トークン差分ストリーミングはありません。
  • ブロックストリーミング(チャンネル): アシスタントが書き込みながら、完了したブロックを送信します。これらは通常のチャンネルメッセージであり、トークン差分ではありません。
  • プレビューストリーミング(Telegram/Discord/Slack/Matrix/Mattermost/MS Teams): 生成中に一時的なプレビューメッセージを更新します(送信 + 編集/追記)。

ブロックストリーミング(チャンネルメッセージ)

ブロックストリーミングは、アシスタント出力が利用可能になった時点で大きめのチャンクとして送信します。
Model output
  └─ text_delta/events
       ├─ (blockStreamingBreak=text_end)
       │    └─ chunker emits blocks as buffer grows
       └─ (blockStreamingBreak=message_end)
            └─ chunker flushes at message_end
                   └─ channel send (block replies)
  • text_delta/events: モデルストリームイベント(非ストリーミングモデルでは疎になる場合があります)。
  • chunker: 最小/最大境界 + 改行優先度を適用する EmbeddedBlockChunker
  • channel send: 実際の送信メッセージ(ブロック返信)。
制御(特記がない限り、すべて agents.defaults 配下):
キー値 / 形状デフォルト
blockStreamingDefault"on" / "off""off"
blockStreamingBreak"text_end" / "message_end"-
blockStreamingChunk{ minChars, maxChars, breakPreference? }-
blockStreamingCoalesce{ minChars?, maxChars?, idleMs? }(送信前にストリーミングされたブロックを結合)-
*.blockStreaming(チャンネル上書き)true / false、チャンネルごと(およびアカウントごと)にブロックストリーミングを強制-
*.textChunkLimit(例: channels.whatsapp.textChunkLimit数値、ハード上限4000
*.chunkMode"length" / "newline""length"
channels.discord.maxLinesPerMessage数値、UI のクリッピングを避けるために長い返信を分割するソフト行上限17
chunkMode: "newline" はすべての改行ではなく空行(段落境界)で分割し、テキストが上限を超えると長さによるチャンク化へフォールバックします。 blockStreamingBreak境界セマンティクス:
  • text_end: チャンクャーが送出したらすぐにブロックをストリーミングし、各 text_end でフラッシュします。
  • message_end: アシスタントメッセージが完了するまで待ち、バッファされた出力をフラッシュします。バッファされたテキストが maxChars を超える場合は引き続きチャンクャーを使うため、最後に複数のチャンクを送出できます。

ブロックストリーミングでのメディア配信

ストリーミングメディアは mediaUrlmediaUrls などの構造化ペイロードフィールドを使う必要があります。ストリーミングされたテキストは添付コマンドとして解析されません。ブロックストリーミングがメディアを早期送信すると、OpenClaw はそのターンの配信を記憶します。最終アシスタントペイロードが同じメディア URL を繰り返す場合、最終配信では添付を再送せず、重複メディアを取り除きます。 完全に重複する最終ペイロードは抑制されます。最終ペイロードが、すでにストリーミングされたメディアの周囲に別のテキストを追加する場合、OpenClaw はメディアを単一配信のまま維持し、新しいテキストは送信します。これにより、Telegram などのチャンネルでボイスメモやファイルが重複することを防ぎます。

チャンク化アルゴリズム(低/高境界)

ブロックチャンク化は EmbeddedBlockChunker によって実装されています。
  • 低境界: 強制されない限り、バッファ >= minChars になるまで送出しません。
  • 高境界: maxChars より前での分割を優先します。強制時は maxChars で分割します。
  • 改行優先度チェーン: paragraph -> newline -> sentence -> 空白 -> ハードブレーク。
  • コードフェンス: フェンス内では絶対に分割しません。maxChars で強制される場合は、Markdown の妥当性を保つためにフェンスを閉じて再度開きます。
maxChars はチャンネルの textChunkLimit にクランプされるため、チャンネルごとの上限を超えることはできません。

結合(ストリーミングされたブロックを結合)

ブロックストリーミングが有効な場合、OpenClaw は送信前に連続するブロックチャンクを結合できます。これにより、進行中の出力を提供しつつ、1 行のスパムを減らせます。
  • 結合はフラッシュ前にアイドル間隔idleMs)を待ちます。
  • バッファは maxChars で上限が設定され、超過するとフラッシュされます。
  • minChars は、十分なテキストが蓄積するまで小さな断片の送信を防ぎます(最終フラッシュでは残りのテキストを常に送信します)。
  • 結合子は blockStreamingChunk.breakPreference から導出されます: paragraph -> \n\nnewline -> \nsentence -> スペース。
  • チャンネル上書きは *.blockStreamingCoalesce(アカウントごとの設定を含む)で利用できます。
  • Discord、Signal、Slack は、上書きされない限りデフォルトで { minChars: 1500, idleMs: 1000 } に結合します。

ブロック間の人間らしいペーシング

ブロックストリーミングが有効な場合、複数バブルの応答がより自然に感じられるように、最初のブロック以降のブロック返信間にランダム化された一時停止を追加します。
agents.defaults.humanDelay.mode動作
off(デフォルト)一時停止なし
natural800-2500ms のランダム一時停止
customminMs/maxMs
エージェントごとに agents.list[].humanDelay で上書きします。ブロック返信にのみ適用され、最終返信やツール要約には適用されません。

「チャンクをストリーミングするか、すべてを送るか」

  • チャンクをストリーミング: blockStreamingDefault: "on" + blockStreamingBreak: "text_end" (生成しながら送出)。Telegram 以外のチャンネルでは *.blockStreaming: true も必要です。
  • 最後にすべてをストリーミング: blockStreamingBreak: "message_end"(1 回フラッシュし、非常に長い場合は複数チャンクになる可能性があります)。
  • ブロックストリーミングなし: blockStreamingDefault: "off"(最終返信のみ)。
ブロックストリーミングは、*.blockStreaming が明示的に true に設定されない限りオフです。チャンネルはブロック返信なしでライブプレビュー(channels.<channel>.streaming)をストリーミングできます。blockStreaming* のデフォルトは設定ルートではなく agents.defaults 配下にあります。

プレビューストリーミングモード

正規キー: channels.<channel>.streaming(ネストされた { mode, ... }。トップレベルの真偽値はレガシーエイリアスです)。
モード動作
offプレビューストリーミングを無効化
partial単一プレビューを最新テキストで置き換え
blockプレビューをチャンク化/追記されたステップで更新
progress生成中に進行状況/ステータスプレビューを表示し、完了時に最終回答を送信
streaming.mode: "block" は、Discord や Telegram など編集可能なチャンネル向けのプレビューストリーミングモードです。それ自体では、そのチャンネルでのチャンネルブロック配信を有効にしません。通常のブロック返信には streaming.block.enabled(またはレガシーの blockStreaming チャンネルキー)を使います。Microsoft Teams は例外です。下書きプレビューブロックのトランスポートがないため、streaming.mode: "block" はネイティブストリーミングを完全に無効化し、返信はネイティブの partial/progress ストリーミングではなく通常のブロック配信として到着します。

チャンネルマッピング

チャンネルoffpartialblockprogress
Telegramはいはいはい編集可能な進行状況下書き
Discordはいはいはい編集可能な進行状況下書き
Slackはいはいはいはい
Mattermostはいはいはいはい
MS Teamsはいはいはいネイティブ進行状況ストリーム
プレビューチャンク設定(streaming.preview.chunk.*、例: channels.discord.streaming または channels.telegram.streaming 配下)は、デフォルトで minChars: 200maxChars: 800(チャンネルの textChunkLimit にクランプ)、breakPreference: "paragraph" です。 Slack のみ:
  • channels.slack.streaming.nativeTransport は、channels.slack.streaming.mode="partial" のときに Slack ネイティブストリーミング API 呼び出し(chat.startStream/chat.appendStream/chat.stopStream)を切り替えます(デフォルト: true)。
  • Slack ネイティブストリーミングと Slack アシスタントスレッドステータスには返信スレッドターゲットが必要です。トップレベルの DM ではそのスレッド形式のプレビューは表示されませんが、Slack の下書きプレビュー投稿と編集は引き続き使用できます。

レガシーキー移行

チャンネルレガシーキーステータス
TelegramstreamMode、スカラー/真偽値 streamingdoctor/設定互換パスによって検出され、streaming.mode へ移行されます
DiscordstreamMode、真偽値 streamingstreaming enum のランタイムエイリアス。永続化された設定を書き換えるには openclaw doctor --fix を実行してください
SlackstreamMode、真偽値 streaming、レガシー nativeStreamingstreaming.mode(および真偽値/レガシー形式では streaming.nativeTransport)のランタイムエイリアス。永続化された設定を書き換えるには openclaw doctor --fix を実行してください

ランタイム動作

Telegram

  • DM とグループ/トピック全体で sendMessage + editMessageText のプレビュー更新を使います。最終テキストはアクティブなプレビューをその場で編集します。Telegram の一時的な 30 秒「入力中」下書き(sendMessageDraft)は回答ストリーミングには使われません。
  • 短い初期プレビューはプッシュ通知 UX のため引き続きデバウンスされますが、アクティブな実行が視覚的に無音のままにならないよう、境界付き遅延の後に実体化されます。
  • 長い最終回答では、最初のチャンクにプレビューメッセージを再利用し、残りのチャンクのみ送信します。
  • block モードは、streaming.preview.chunk.maxChars(デフォルト 800、Telegram の 4096 編集上限でキャップ)でプレビューを新しいメッセージへローテーションします。他のモードでは、1 つのプレビューを最大 4096 文字まで伸ばします。
  • progress モードは、ツール進行状況を編集可能なステータス下書きに保持し、回答ストリーミングがアクティブだがツール行がまだ利用できない場合にステータスラベルを実体化し、完了時に下書きをクリアして、通常の配信を通じて最終回答を送信します。
  • 完了したテキストが確認される前に最終編集が失敗した場合、OpenClaw は通常の最終配信を使い、古いプレビューをクリーンアップします。
  • 二重ストリーミングを避けるため、Telegram ブロックストリーミングが明示的に有効な場合、プレビューストリーミングはスキップされます。
  • /reasoning stream は、最終配信後に削除される一時プレビューへ reasoning を書き込めます。
  • Telegram の選択引用返信は例外です。replyToMode"off" ではなく、選択引用テキストが存在する場合、そのターンでは OpenClaw は回答プレビューストリームをスキップします(最終回答はネイティブの引用返信パスを通る必要があります)。そのため、ツール進行状況のプレビュー行はレンダリングできません。選択引用テキストがない現在メッセージへの返信では、プレビューストリーミングは維持されます。詳細は Telegram チャンネルドキュメント を参照してください。

Discord

  • send + edit プレビュー メッセージを使用します。
  • block モードはドラフトのチャンク化 (draftChunk) を使用します。
  • Discord のブロック ストリーミングが明示的に有効化されている場合、プレビュー ストリーミングはスキップされます。
  • 最終メディア、エラー、明示的な返信ペイロードは、新しいドラフトをフラッシュせずに保留中のプレビューをキャンセルし、その後通常の配信を使用します。

Slack

  • partial は、利用可能な場合に Slack ネイティブ ストリーミング (chat.startStream/append/stop) を使用できます。
  • block は追記スタイルのドラフト プレビューを使用します。
  • progress はステータス プレビュー テキストを使用し、その後に最終回答を送信します。
  • 返信スレッドのないトップレベル DM は、Slack ネイティブ ストリーミングの代わりにドラフト プレビュー投稿と編集を使用します。
  • ネイティブおよびドラフト プレビュー ストリーミングは、そのターンのブロック返信を抑制するため、Slack の返信は 1 つの配信パスだけでストリーミングされます。
  • 最終メディア/エラー ペイロードと進行状況の最終結果は、使い捨てのドラフト メッセージを作成しません。プレビューを編集できるテキスト/ブロックの最終結果だけが、保留中のドラフト テキストをフラッシュします。

Mattermost

  • 思考、ツール アクティビティ、部分返信テキストを単一のドラフト プレビュー投稿にストリーミングし、最終回答を安全に送信できるときにその場で確定します。
  • プレビュー投稿が削除されたか、確定時に何らかの理由で利用できない場合は、新しい最終投稿の送信にフォールバックします。
  • 最終メディア/エラー ペイロードは、一時的なプレビュー投稿をフラッシュする代わりに、通常の配信前に保留中のプレビュー更新をキャンセルします。

Matrix

  • 最終テキストがプレビュー イベントを再利用できる場合、ドラフト プレビューはその場で確定します。
  • メディアのみ、エラー、返信先不一致の最終結果は、通常の配信前に保留中のプレビュー更新をキャンセルします。すでに表示されている古いプレビューは編集削除されます。

ツール進行状況のプレビュー更新

プレビュー ストリーミングには、ツール進行状況 の更新も含めることができます。ツールの実行中、最終返信の前に、同じプレビュー メッセージ内に表示される「ウェブを検索中」、「ファイルを読み取り中」、「ツールを呼び出し中」のような短いステータス行です。Codex app-server モードでは、Codex の前置き/コメンタリー メッセージもこの同じプレビュー パスを使用するため、「確認しています…」のような短い進行状況メモを、最終回答の一部にせずに編集可能なドラフトへストリーミングできます。これにより、複数ステップのツール ターンは、最初の思考プレビューと最終回答の間で沈黙するのではなく、視覚的に動き続けます。 長時間実行されるツールは、返る前に型付きの進行状況を出力することがあります。たとえば、web_fetch は開始時に 5 秒のタイマーを設定します。フェッチがまだ保留中の場合、プレビューには Fetching page content... が表示されます。その前にフェッチが完了またはキャンセルされた場合、進行状況行は出力されません。後続の最終ツール結果は、通常どおりモデルに配信されます。 サポートされるサーフェス:
  • DiscordSlackTelegramMatrix は、プレビュー ストリーミングが有効な場合、デフォルトでツール進行状況と Codex の前置き更新をライブ プレビュー編集にストリーミングします。Microsoft Teams は個人チャットでネイティブの進行状況ストリームを使用します。
  • Telegram は v2026.4.22 以降、ツール進行状況プレビュー更新を有効にした状態で出荷されています。有効のままにすることで、そのリリース済みの動作を維持できます。
  • Mattermost は、すでにツール アクティビティを単一のドラフト プレビュー投稿に組み込んでいます(上記を参照)。
  • ツール進行状況の編集は、アクティブなプレビュー ストリーミング モードに従います。プレビュー ストリーミングが off の場合、またはブロック ストリーミングがメッセージを引き継いでいる場合はスキップされます。Telegram では、streaming.mode: "off" は最終結果のみです。汎用的な進行状況の雑談も、単独のステータス メッセージとして配信される代わりに抑制されます。一方で、承認プロンプト、メディア ペイロード、エラーは引き続き通常どおりルーティングされます。
  • プレビュー ストリーミングは維持しつつツール進行状況行を非表示にするには、そのチャネルの streaming.preview.toolProgressfalse に設定します(デフォルトは true)。コマンド/実行テキストを非表示にしつつツール進行状況行を表示したままにするには、streaming.preview.commandText"status" に設定するか、streaming.progress.commandText"status" に設定します。リリース済みの動作を維持するため、デフォルトは "raw" です。このポリシーは、OpenClaw のコンパクト進行状況レンダラーを使用するドラフト/進行状況チャネルで共有されます。これには Discord、Matrix、Microsoft Teams、Mattermost、Slack ドラフト プレビュー、Telegram が含まれます。プレビュー編集を完全に無効化するには、streaming.modeoff に設定します。

進行状況ドラフトのレンダリング

進行状況モードのドラフト (streaming.progress.*) は、チャネルごとに制限および設定できます。
キーデフォルト動作
streaming.progress.maxLines8ドラフト ラベルの下に保持されるコンパクト進行状況行の最大数
streaming.progress.maxLineChars120切り詰め前のコンパクト行あたりの最大文字数(単語を考慮)
streaming.progress.label"auto"ドラフト タイトル。カスタム文字列、または非表示にする false
streaming.progress.labels組み込みプールlabel: "auto" のときに使用される候補ラベル

コメンタリー進行状況レーン

ツール進行状況に加えて、コンパクト進行状況レンダラーはドラフト内にもう 1 つのレーンを表示できます。
  • streaming.progress.commentary - モデルのツール実行前の コメンタリー(短い「確認してから…」のようなナレーション)を、進行状況ドラフト内でツール行と交互にレンダリングします。
{
  "channels": {
    "discord": {
      "streaming": { "mode": "progress", "progress": { "commentary": true } }
    }
  }
}
進行状況行は表示したまま、生のコマンド/実行テキストを非表示にします。
{
  "channels": {
    "telegram": {
      "streaming": {
        "mode": "partial",
        "preview": {
          "toolProgress": true,
          "commandText": "status"
        }
      }
    }
  }
}
同じ形を別のコンパクト進行状況チャネル キーの下で使用します。たとえば channels.discordchannels.matrixchannels.msteamschannels.mattermost、または Slack ドラフト プレビューです。進行状況ドラフト モードでは、同じポリシーを streaming.progress の下に置きます。
{
  "channels": {
    "telegram": {
      "streaming": {
        "mode": "progress",
        "progress": {
          "toolProgress": true,
          "commandText": "status"
        }
      }
    }
  }
}

関連