串流 + 分塊
OpenClaw 有兩個獨立的串流層:
- 區塊串流(頻道): 在助理撰寫過程中發送已完成的區塊。這些是一般的頻道訊息(不是 Token 差異)。
- 預覽串流(Telegram/Discord/Slack): 在生成過程中更新一則暫時的預覽訊息。
目前沒有真正的 Token 差異串流到頻道訊息。預覽串流是基於訊息的(傳送 + 編輯/附加)。
區塊串流(頻道訊息)
區塊串流在助理輸出可用時,以粗粒度的區塊傳送。
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)。- 頻道覆蓋:
*.blockStreaming(及各帳號的變體)可強制各頻道為"on"/"off"。 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:chunker 發出區塊時立即串流;每個text_end時清空。message_end:等待助理訊息完成後清空緩衝輸出。
message_end 在緩衝文字超過 maxChars 時仍會使用 chunker,所以最後可能發出多個區塊。
分塊演算法(下限/上限)
區塊分塊由 EmbeddedBlockChunker 實作:
- 下限: 緩衝區未達
minChars前不發出(除非被強制)。 - 上限: 偏好在
maxChars之前分割;被強制時則在maxChars處切分。 - 斷點偏好:
paragraph→newline→sentence→whitespace→ 硬切分。 - 程式碼區塊(Code fence): 絕不在 fence 內部切分;被強制在
maxChars處切分時,會關閉再重新開啟 fence 以保持 Markdown 格式正確。
maxChars 受頻道 textChunkLimit 限制,因此不會超過各頻道的上限。
合併(合併已串流的區塊)
啟用區塊串流時,OpenClaw 可以在傳送前合併連續的區塊片段。這能減少「單行刷屏」的現象,同時仍提供漸進式輸出。
- 合併會等待閒置間隔(
idleMs)後才清空。 - 緩衝區受
maxChars限制,超過時會清空。 minChars防止過小的片段被傳送,直到累積足夠文字(最終清空時一定會傳送剩餘文字)。- 連接符號依
blockStreamingChunk.breakPreference決定(paragraph→\n\n,newline→\n,sentence→ 空格)。 - 頻道覆蓋可透過
*.blockStreamingCoalesce(含各帳號設定)進行。 - Signal/Slack/Discord 的預設合併
minChars會提高到 1500,除非另有覆蓋。
區塊間的擬人化節奏
啟用區塊串流時,你可以在區塊回覆之間(第一個區塊之後)加入隨機停頓。這讓多氣泡回覆的節奏更自然。
- 設定:
agents.defaults.humanDelay(依 Agent 覆蓋:agents.list[].humanDelay)。 - 模式:
off(預設)、natural(800–2500ms)、custom(minMs/maxMs)。 - 僅適用於區塊回覆,不適用於最終回覆或工具摘要。
「串流區塊」vs「全部串流」
對應方式:
- 串流區塊:
blockStreamingDefault: "on"+blockStreamingBreak: "text_end"(邊生成邊發送)。非 Telegram 頻道還需要*.blockStreaming: true。 - 結束時全部串流:
blockStreamingBreak: "message_end"(完成後一次清空,若內容很長可能產生多個區塊)。 - 不使用區塊串流:
blockStreamingDefault: "off"(只有最終回覆)。
頻道注意事項: 區塊串流預設關閉,除非 *.blockStreaming 明確設為 true。頻道可以在不使用區塊回覆的情況下串流即時預覽(channels.<channel>.streaming)。
設定位置提醒:blockStreaming* 的預設值在 agents.defaults 下,不在根設定中。
預覽串流模式
標準 Key:channels.<channel>.streaming
模式:
off:停用預覽串流。partial:單一預覽,以最新文字取代。block:預覽以分塊/附加方式更新。progress:生成期間顯示進度/狀態預覽,完成時顯示最終答案。
頻道對應表
| 頻道 | off | partial | block | progress |
|---|---|---|---|---|
| Telegram | ✅ | ✅ | ✅ | 對應為 partial |
| Discord | ✅ | ✅ | ✅ | 對應為 partial |
| Slack | ✅ | ✅ | ✅ | ✅ |
Slack 專屬:
channels.slack.nativeStreaming在streaming=partial時切換是否使用 Slack 原生串流 API 呼叫(預設:true)。
舊版 Key 遷移:
- Telegram:
streamMode+ 布林值streaming自動遷移至streaming列舉。 - Discord:
streamMode+ 布林值streaming自動遷移至streaming列舉。 - Slack:
streamMode自動遷移至streaming列舉;布林值streaming自動遷移至nativeStreaming。
執行期間行為
Telegram:
- 在私訊和群組/主題中使用
sendMessage+editMessageText進行預覽更新。 - 當 Telegram 區塊串流明確啟用時,會跳過預覽串流(避免重複串流)。
/reasoning stream可將推理過程寫入預覽。
Discord:
- 使用傳送 + 編輯預覽訊息。
block模式使用草稿分塊(draftChunk)。- 當 Discord 區塊串流明確啟用時,會跳過預覽串流。
Slack:
partial可在支援時使用 Slack 原生串流(chat.startStream/append/stop)。block使用附加式草稿預覽。progress使用狀態預覽文字,然後是最終答案。