Skip to content

OpenClaw 的流式输出分为两层:区块流式(Block Streaming) 向频道发送完整区块消息,预览流式(Preview Streaming) 在生成过程中更新临时预览消息。要开启区块流式,需设置 agents.defaults.blockStreamingDefault"on" 并为对应频道显式设置 *.blockStreaming: true;预览流式通过 channels.<channel>.streaming.mode 选择 partialblockprogress 模式。当前版本不支持真实 token-delta 推送,预览流式基于消息编辑实现。

OpenClaw 流式输出配置:区块流式 vs 预览流式

OpenClaw 有两套独立的流式层:

  • 区块流式(Block Streaming,频道消息):助手在写作过程中以完整的区块为单位向频道发送常规消息(非 token 增量)。
  • 预览流式(Preview Streaming,Telegram / Discord / Slack / Mattermost / MS Teams / Matrix):生成过程中更新一条临时预览消息

目前没有真实的 token-delta 流式推送到频道消息。预览流式基于消息发送与编辑/追加实现。

区块流式(频道消息)配置与排查

区块流式在输出可用时以粗粒度分块发送助手内容。以下是区块流式的数据流:

Model output
  └─ text_delta/events
       ├─ (blockStreamingBreak=text_end)
       │    └─ chunker 随缓冲区增长输出区块
       └─ (blockStreamingBreak=message_end)
            └─ chunker 在 message_end 时刷新
                   └─ channel send(区块回复)

说明:

  • text_delta/events:模型流事件(非流式模型可能较稀疏)。
  • chunkerEmbeddedBlockChunker,应用最小/最大字符限制及换行偏好。
  • channel send:实际出站消息(区块回复)。

核心控制参数

参数说明
agents.defaults.blockStreamingDefault全局开关,"on" / "off"(默认 off)。
*.blockStreaming频道级强制覆盖。例如 channels.telegram.blockStreaming: true。也支持每账号变体。
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(先按空行分段,再按长度分块)。
channels.discord.maxLinesPerMessageDiscord 软上限,默认 17,超高回复会自动拆分。

边界语义

  • text_end:chunker 一发出区块就立即推送,每次 text_end 都会刷新。
  • message_end:等待助手消息结束后,一次性刷新缓冲输出。若缓冲文本超过 maxChars,仍会使用 chunker 产生多个分块。

开启区块流式的完整步骤

  1. 设置 agents.defaults.blockStreamingDefault: "on"
  2. 为目标频道设置 channels.<name>.blockStreaming: true(非 Telegram 频道必须显式设置)。
  3. 选择边界策略:agents.defaults.blockStreamingBreak: "text_end"(实时推送)或 "message_end"(结束后一次发送)。
  4. 可选:调整 blockStreamingChunkblockStreamingCoalesce

配置位置提示:所有 blockStreaming* 默认值位于 agents.defaults 下,不是根配置

分块算法(低水位线 / 高水位线)

EmbeddedBlockChunker 的分块逻辑:

  • 低水位线:缓冲 < minChars 时不输出(除非强制)。
  • 高水位线:优先在 maxChars 之前找合适断点;强制时在 maxChars 截断。
  • 断点优先级paragraphnewlinesentencewhitespace → 硬截断。
  • 代码围栏保护:绝不在代码围栏内截断;强制截断时会关闭围栏再重新打开,保证 Markdown 合法。

maxChars 会被钳制到频道的 textChunkLimit,确保不超过每频道上限。

合并策略(Coalescing)

区块流式开启后,OpenClaw 可以合并连续区块后再发送,减少“单行刷屏”问题。

  • 等待空闲间隔(idleMs)后刷新缓冲。
  • 缓冲上限为 maxChars,超出即强制刷新。
  • minChars 防止过小片段发送,最终刷新时发送剩余文本。
  • 连接符由 blockStreamingChunk.breakPreference 决定:paragraph → 双换行、newline → 单换行、sentence → 空格。
  • 频道级覆盖:通过 *.blockStreamingCoalesce 配置(含每账号)。
  • 默认 minChars:Signal / Slack / Discord 为 1500,除非显式覆盖。

仿人类节奏(Human-like Pacing)

开启区块流式后,可在首块之后的回复之间添加随机停顿,让多气泡回复更自然。

  • 配置:agents.defaults.humanDelay(也可通过 agents.list[].humanDelay 按智能体覆盖)。
  • 模式:off(默认)、natural(800–2500ms 随机)、customminMs / maxMs)。
  • 仅作用于区块回复,不影响最终回复或工具摘要。

频道预览流式映射

channels.&lt;channel&gt;.streaming.mode 定义预览推送方式:

Channeloffpartialblockprogress
Telegrameditable progress draft
Discordeditable progress draft
Slack
Mattermost
MS Teamsnative progress stream

Slack 专用:

  • channels.slack.streaming.nativeTransport:当 streaming.mode="partial" 时,默认 true,启用 Slack 原生流式 API(chat.startStream/append/stop)。
  • 顶级私聊无回复线程时,使用草稿预览帖和编辑,无法使用原生流式。

旧版配置迁移

运行 openclaw doctor --fix 可自动迁移旧版配置:

  • Telegram:streamMode / 布尔值 streaming → 写入 streaming.mode
  • Discord:streamMode / 布尔值 streaming → 运行时别名,--fix 后持久化。
  • Slack:streamModestreaming.mode;布尔值 streamingstreaming.mode + streaming.nativeTransportnativeStreamingstreaming.nativeTransport

频道运行时行为

Telegram

  • 使用 sendMessage + editMessageText 更新预览。
  • progress 模式:工具进度显示为可编辑状态草稿,完成后清除草稿,最终答案正常发送。
  • 当 Telegram 区块流式显式开启时,预览流式被跳过(避免双重推送)。
  • /reasoning stream 可将推理过程写入临时预览,最终交付后删除。
  • 若最终编辑失败,OpenClaw 使用正常交付并清理失效预览。

Discord

  • 使用发送 + 编辑预览消息。
  • block 模式使用草稿分块(draftChunk)。
  • 当 Discord 区块流式显式开启时,预览流式被跳过。
  • 最终媒体/错误/显式回复负载会取消待处理的预览,不刷新新草稿。

Slack

  • partial 使用 Slack 原生流式(当 nativeTransport=true 且存在回复线程)。
  • block 使用追加式草稿预览。
  • progress 使用状态预览文本,完成后发最终答案。
  • 原生和草稿预览流式会抑制该轮的区块回复,一条 Slack 回复只走一种交付路径。
  • 最终媒体/错误负载不会创建临时草稿消息。

Mattermost

  • 将思考、工具活动和回复文本流式到单个预览帖,最终就位。
  • 若预览帖被删除,回退为发送新帖。
  • 最终媒体/错误负载取消待处理预览后正常交付。

Matrix

  • 预览草稿就位后直接替换该事件。
  • 纯媒体/错误/回复目标不匹配时,取消预览后正常交付,若预览已可见则撤回。

工具进度预览

预览流式可包含工具进度更新(如“正在搜索网页”、“正在读取文件”),在工具运行期间显示为同一预览消息中的短状态行。在 Codex 应用服务器模式下,Codex 前言/评论消息同样走此路径。

支持通道:

  • Discord、Slack、Telegram、Matrix:默认启用工具进度和 Codex 前言更新。
  • Telegram 自 v2026.4.22 已启用工具进度预览,保持启用以保留发布行为。
  • Mattermost 已将其纳入单个预览帖中。

隐藏工具进度或命令文本

  • 保持预览流式,但隐藏工具进度:设置 channels.&lt;channel&gt;.streaming.preview.toolProgress: false
  • 隐藏原始命令/执行文本:设置 streaming.preview.commandText: "status"(默认 "raw")或 streaming.progress.commandText: "status"
  • 该策略适用于所有使用 OpenClaw 紧凑进度渲染的起草/进度通道(Discord、Matrix、Teams、Mattermost、Slack 草稿预览、Telegram)。
  • 完全禁用预览编辑:设置 streaming.mode: off

Telegram 选中引用回复是个例外:当 replyToMode 不是 "off" 且存在选中引用文本时,该轮跳过预览流式,工具进度预览无法渲染。当前消息引用(无选中引用文本)仍保留预览流式。详见 Telegram 频道文档

示例:保持进度可见但隐藏原始命令文本:

json
{
  "channels": {
    "telegram": {
      "streaming": {
        "mode": "partial",
        "preview": {
          "toolProgress": true,
          "commandText": "status"
        }
      }
    }
  }
}

进度起草模式下同理:

json
{
  "channels": {
    "telegram": {
      "streaming": {
        "mode": "progress",
        "progress": {
          "toolProgress": true,
          "commandText": "status"
        }
      }
    }
  }
}

常见问题

为什么开了流式还是只发一条消息

确认 blockStreamingDefault 已设为 "on",且目标频道显式设置了 *.blockStreaming: true(非 Telegram 频道必须)。另外检查 blockStreamingBreak 是否为 "message_end"——该模式下输出会在消息结束后集中刷新,可能只发一次。

Telegram 预览流式不生效怎么解决

检查 channels.telegram.streaming 是否配置了 modepartialblockprogress)。旧版配置(streamMode、布尔值 streaming)需运行 openclaw doctor --fix 迁移。若 Telegram 区块流式已开启,预览流式会被自动跳过。

区块流式会不会发重复消息

区块流式中的 MEDIA: 指令重复会被识别:若最终回复包含已流式发送的相同媒体 URL,OpenClaw 会去重,不会再次发送附件。合并策略(coalescing)也通过 idleMsmaxChars 避免过度拆分的重复推送。