---
read_when:
    - チャネルでストリーミングまたはチャンク化がどのように機能するかを説明する
    - ブロックストリーミングまたはチャンネルのチャンク化動作の変更
    - 重複/早期のブロック返信またはチャネルプレビューのストリーミングのデバッグ
summary: ストリーミング + チャンク化の動作（ブロック返信、チャンネルプレビューのストリーミング、モードマッピング）
title: ストリーミングとチャンク化
x-i18n:
    generated_at: "2026-05-03T04:58:18Z"
    model: gpt-5.5
    provider: openai
    source_hash: 85f6cb33031a6c818bb709e0ed14d8dd0f8c30a3dd90468a40396b3a515b5e65
    source_path: concepts/streaming.md
    workflow: 16
---

OpenClaw には 2 つの別々のストリーミング層があります。

- **ブロックストリーミング（チャネル）:** アシスタントが書き込み中に、完成した**ブロック**を送信します。これらは通常のチャネルメッセージです（トークン差分ではありません）。
- **プレビューストリーミング（Telegram/Discord/Slack）:** 生成中に一時的な**プレビューメッセージ**を更新します。

現在、チャネルメッセージへの**真のトークン差分ストリーミング**はありません。プレビューストリーミングはメッセージベースです（送信 + 編集/追加）。

## ブロックストリーミング（チャネルメッセージ）

ブロックストリーミングは、利用可能になったアシスタント出力を粗いチャンクで送信します。

```
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"`（デフォルトはオフ）。
- チャネルオーバーライド: チャネルごとに `"on"`/`"off"` を強制する `*.blockStreaming`（およびアカウント単位のバリアント）。
- `agents.defaults.blockStreamingBreak`: `"text_end"` または `"message_end"`。
- `agents.defaults.blockStreamingChunk`: `{ minChars, maxChars, breakPreference? }`。
- `agents.defaults.blockStreamingCoalesce`: `{ minChars?, maxChars?, idleMs? }`（送信前にストリーミングされたブロックを結合）。
- チャネルのハード上限: `*.textChunkLimit`（例: `channels.whatsapp.textChunkLimit`）。
- チャネルのチャンクモード: `*.chunkMode`（デフォルトは `length`、`newline` は長さによるチャンク化の前に空行（段落境界）で分割します）。
- Discord のソフト上限: `channels.discord.maxLinesPerMessage`（デフォルトは 17）は、UI のクリッピングを避けるため長い返信を分割します。

**境界の意味:**

- `text_end`: チャンカーが送出したらすぐにブロックをストリームし、各 `text_end` でフラッシュします。
- `message_end`: アシスタントメッセージが完了するまで待ってから、バッファされた出力をフラッシュします。

バッファされたテキストが `maxChars` を超える場合、`message_end` でもチャンカーが使われるため、最後に複数のチャンクを送出できます。

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

`MEDIA:` ディレクティブは通常の配信メタデータです。ブロックストリーミングがメディアブロックを早期に送信すると、OpenClaw はそのターンの配信を記憶します。最終的なアシスタントペイロードが同じメディア URL を繰り返す場合、最終配信では添付ファイルを再送信せず、重複メディアを取り除きます。

完全に重複する最終ペイロードは抑制されます。最終ペイロードが、すでにストリーミングされたメディアの前後に別のテキストを追加している場合、OpenClaw はメディアを 1 回だけ配信したまま、新しいテキストを送信します。これにより、エージェントがストリーミング中に `MEDIA:` を送出し、プロバイダーも完了済み返信にそれを含める場合に、Telegram などのチャネルでボイスメモやファイルが重複するのを防ぎます。

## チャンク化アルゴリズム（下限/上限）

ブロックのチャンク化は `EmbeddedBlockChunker` によって実装されています。

- **下限:** 強制されない限り、バッファ >= `minChars` になるまで送出しません。
- **上限:** `maxChars` より前での分割を優先します。強制される場合は `maxChars` で分割します。
- **改行優先度:** `paragraph` → `newline` → `sentence` → `whitespace` → 強制改行。
- **コードフェンス:** フェンス内では分割しません。`maxChars` で強制分割される場合は、Markdown を有効に保つためフェンスを閉じてから再度開きます。

`maxChars` はチャネルの `textChunkLimit` にクランプされるため、チャネルごとの上限を超えることはできません。

## 結合（ストリーミングされたブロックのマージ）

ブロックストリーミングが有効な場合、OpenClaw は送信前に**連続するブロックチャンクを結合**できます。これにより、段階的な出力を維持しながら「1 行だけの連投」を減らせます。

- 結合は、フラッシュ前に**アイドルギャップ**（`idleMs`）を待ちます。
- バッファは `maxChars` で上限設定され、それを超えるとフラッシュされます。
- `minChars` は、十分なテキストが蓄積するまで小さな断片の送信を防ぎます（最終フラッシュでは残りのテキストを必ず送信します）。
- 結合文字は `blockStreamingChunk.breakPreference` から導出されます（`paragraph` → `\n\n`、`newline` → `\n`、`sentence` → スペース）。
- `*.blockStreamingCoalesce` でチャネルオーバーライドを利用できます（アカウント単位の設定を含む）。
- デフォルトの結合 `minChars` は、オーバーライドされない限り Signal/Slack/Discord で 1500 に引き上げられます。

## ブロック間の人間らしい間

ブロックストリーミングが有効な場合、ブロック返信の間（最初のブロックの後）に**ランダムな一時停止**を追加できます。これにより、複数バブルの応答がより自然に感じられます。

- 設定: `agents.defaults.humanDelay`（`agents.list[].humanDelay` でエージェントごとにオーバーライド）。
- モード: `off`（デフォルト）、`natural`（800〜2500ms）、`custom`（`minMs`/`maxMs`）。
- **ブロック返信**にのみ適用され、最終返信やツール要約には適用されません。

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

これは次に対応します。

- **チャンクをストリーム:** `blockStreamingDefault: "on"` + `blockStreamingBreak: "text_end"`（進行に応じて送出）。Telegram 以外のチャネルでは `*.blockStreaming: true` も必要です。
- **最後にすべてをストリーム:** `blockStreamingBreak: "message_end"`（一度フラッシュし、非常に長い場合は複数チャンクになる可能性があります）。
- **ブロックストリーミングなし:** `blockStreamingDefault: "off"`（最終返信のみ）。

**チャネルメモ:** `*.blockStreaming` が明示的に `true` に設定されていない限り、ブロックストリーミングは**オフ**です。チャネルはブロック返信なしでライブプレビュー（`channels.<channel>.streaming`）をストリームできます。

設定場所の注意: `blockStreaming*` のデフォルトはルート設定ではなく、`agents.defaults` の下にあります。

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

正規キー: `channels.<channel>.streaming`

モード:

- `off`: プレビューストリーミングを無効化します。
- `partial`: 最新のテキストで置き換えられる単一のプレビュー。
- `block`: チャンク化/追加ステップでプレビューを更新します。
- `progress`: 生成中に進捗/ステータスプレビューを表示し、完了時に最終回答を表示します。

### チャネルマッピング

| チャネル    | `off` | `partial` | `block` | `progress`        |
| ---------- | ----- | --------- | ------- | ----------------- |
| Telegram   | ✅    | ✅        | ✅      | `partial` にマップ |
| Discord    | ✅    | ✅        | ✅      | `partial` にマップ |
| Slack      | ✅    | ✅        | ✅      | ✅                |
| Mattermost | ✅    | ✅        | ✅      | ✅                |

Slack のみ:

- `channels.slack.streaming.nativeTransport` は、`channels.slack.streaming.mode="partial"` の場合に Slack ネイティブストリーミング API 呼び出しを切り替えます（デフォルト: `true`）。
- Slack ネイティブストリーミングと Slack アシスタントスレッドステータスには、返信スレッドのターゲットが必要です。トップレベルの DM ではそのスレッド形式のプレビューは表示されませんが、Slack の下書きプレビュー投稿と編集は引き続き使用できます。

レガシーキーの移行:

- Telegram: レガシーの `streamMode` とスカラー/ブールの `streaming` 値は検出され、doctor/config 互換パスによって `streaming.mode` に移行されます。
- Discord: `streamMode` + ブールの `streaming` は `streaming` 列挙型へ自動移行されます。
- Slack: `streamMode` は `streaming.mode` へ自動移行されます。ブールの `streaming` は `streaming.mode` と `streaming.nativeTransport` へ自動移行されます。レガシーの `nativeStreaming` は `streaming.nativeTransport` へ自動移行されます。

### ランタイム動作

Telegram:

- DM とグループ/トピック全体で、`sendMessage` + `editMessageText` によるプレビュー更新を使用します。
- プレビューが約 1 分間表示されていた場合、インプレース編集ではなく新しい最終メッセージを送信し、その後プレビューをクリーンアップして Telegram のタイムスタンプが返信完了を反映するようにします。
- Telegram のブロックストリーミングが明示的に有効な場合、二重ストリーミングを避けるためプレビューストリーミングはスキップされます。
- `/reasoning stream` は推論をプレビューに書き込めます。

Discord:

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

Slack:

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

Mattermost:

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

Matrix:

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

### ツール進捗プレビュー更新

プレビューストリーミングには、**ツール進捗**更新も含められます。これは「Web を検索中」「ファイルを読み取り中」「ツールを呼び出し中」のような短いステータス行で、ツールの実行中に最終返信より先に同じプレビューメッセージに表示されます。これにより、複数ステップのツールターンが、最初の思考プレビューから最終回答までの間に無音にならず、視覚的に動き続けます。

対応サーフェス:

- **Discord**、**Slack**、**Telegram**、**Matrix** は、プレビューストリーミングが有効な場合、デフォルトでツール進捗をライブプレビュー編集にストリームします。
- Telegram では `v2026.4.22` 以降、ツール進捗プレビュー更新が有効な状態で出荷されています。有効に保つことで、そのリリース済み動作を維持します。
- **Mattermost** はすでに、ツール活動を単一の下書きプレビュー投稿に折り込んでいます（上記参照）。
- ツール進捗の編集は有効なプレビューストリーミングモードに従います。プレビューストリーミングが `off` の場合、またはブロックストリーミングがメッセージを引き継いでいる場合はスキップされます。Telegram では、`streaming.mode: "off"` は最終のみです。一般的な進捗チャットも、スタンドアロンの「作業中...」メッセージとして配信される代わりに抑制されます。一方、承認プロンプト、メディアペイロード、エラーは通常どおりルーティングされます。
- プレビューストリーミングを維持しつつツール進捗行を非表示にするには、そのチャネルの `streaming.preview.toolProgress` を `false` に設定します。プレビュー編集を完全に無効化するには、`streaming.mode` を `off` に設定します。

例:

```json
{
  "channels": {
    "telegram": {
      "streaming": {
        "mode": "partial",
        "preview": {
          "toolProgress": false
        }
      }
    }
  }
}
```

## 関連

- [メッセージ](/ja-JP/concepts/messages) — メッセージのライフサイクルと配信
- [Retry](/ja-JP/concepts/retry) — 配信失敗時の再試行動作
- [チャネル](/ja-JP/channels) — チャネルごとのストリーミング対応
