diff --git a/docs/zh-CN/channels/telegram.md b/docs/zh-CN/channels/telegram.md index 5ac56b41e..e7db6bdfd 100644 --- a/docs/zh-CN/channels/telegram.md +++ b/docs/zh-CN/channels/telegram.md @@ -1,18 +1,18 @@ --- read_when: - - 处理 Telegram 功能或网络钩子 + - 开发 Telegram 功能或网络钩子 summary: Telegram 机器人支持状态、能力和配置 title: Telegram x-i18n: - generated_at: "2026-05-03T15:25:49Z" + generated_at: "2026-05-03T15:33:13Z" model: gpt-5.5 provider: openai - source_hash: c3b97d3dff3d3a91db568dc689f82c0b63ad8028fb716cc772e84d7afe071869 + source_hash: 5f234bc5f33eacbed3bfdc9d60285ea22ce4747f727cdb13863732238470a62d source_path: channels/telegram.md workflow: 16 --- -可投入生产环境,用于通过 grammY 支持机器人私信和群组。默认模式是长轮询;webhook 模式是可选的。 +可用于生产环境中的机器人私信和群组,基于 grammY。长轮询是默认模式;webhook 模式是可选的。 @@ -30,9 +30,9 @@ x-i18n: - 打开 Telegram 并与 **@BotFather** 聊天(确认用户名完全是 `@BotFather`)。 + 打开 Telegram 并与 **@BotFather** 聊天(确认句柄确实是 `@BotFather`)。 - 运行 `/newbot`,按提示操作,并保存令牌。 + 运行 `/newbot`,按照提示操作,并保存令牌。 @@ -52,7 +52,7 @@ x-i18n: ``` 环境变量回退:`TELEGRAM_BOT_TOKEN=...`(仅默认账号)。 - Telegram **不**使用 `openclaw channels login telegram`;请在配置/环境变量中配置令牌,然后启动 Gateway 网关。 + Telegram **不会**使用 `openclaw channels login telegram`;请在配置/环境变量中配置令牌,然后启动 Gateway 网关。 @@ -69,26 +69,26 @@ openclaw pairing approve telegram - 将机器人添加到你的群组,然后设置 `channels.telegram.groups` 和 `groupPolicy`,使其与你的访问模型匹配。 + 将机器人添加到你的群组,然后设置 `channels.telegram.groups` 和 `groupPolicy` 以匹配你的访问模型。 -令牌解析顺序支持账号感知。实际使用中,配置值优先于环境变量回退,且 `TELEGRAM_BOT_TOKEN` 只适用于默认账号。 +令牌解析顺序是账号感知的。实际使用中,配置值优先于环境变量回退,且 `TELEGRAM_BOT_TOKEN` 仅适用于默认账号。 -## Telegram 侧设置 +## Telegram 端设置 - Telegram 机器人默认使用**隐私模式**,这会限制它们能接收哪些群组消息。 + Telegram 机器人默认启用**隐私模式**,这会限制它们能接收哪些群组消息。 - 如果机器人必须看到所有群组消息,可以: + 如果机器人必须查看所有群组消息,可以: - 通过 `/setprivacy` 禁用隐私模式,或 - 将机器人设为群组管理员。 - 切换隐私模式时,请在每个群组中移除并重新添加机器人,以便 Telegram 应用该变更。 + 切换隐私模式时,请在每个群组中移除并重新添加机器人,以便 Telegram 应用更改。 @@ -102,7 +102,7 @@ openclaw pairing approve telegram - `/setjoingroups` 用于允许/拒绝添加到群组 - - `/setprivacy` 用于群组可见性行为 + - `/setprivacy` 用于控制群组可见性行为 @@ -111,32 +111,32 @@ openclaw pairing approve telegram - `channels.telegram.dmPolicy` 控制私信访问: + `channels.telegram.dmPolicy` 控制直接消息访问: - `pairing`(默认) - `allowlist`(要求 `allowFrom` 中至少有一个发送者 ID) - `open`(要求 `allowFrom` 包含 `"*"`) - `disabled` - `dmPolicy: "open"` 搭配 `allowFrom: ["*"]` 会让任何找到或猜到机器人用户名的 Telegram 账号都能向机器人发出命令。仅应将它用于刻意公开、且工具受到严格限制的机器人;单所有者机器人应使用包含数字用户 ID 的 `allowlist`。 + `dmPolicy: "open"` 搭配 `allowFrom: ["*"]` 会让任何找到或猜到机器人用户名的 Telegram 账号都能指挥机器人。仅对有意公开且工具受到严格限制的机器人使用它;单所有者机器人应使用带数字用户 ID 的 `allowlist`。 `channels.telegram.allowFrom` 接受数字 Telegram 用户 ID。`telegram:` / `tg:` 前缀会被接受并规范化。 在多账号配置中,限制性的顶层 `channels.telegram.allowFrom` 会被视为安全边界:账号级 `allowFrom: ["*"]` 条目不会让该账号公开,除非合并后的有效账号允许列表仍包含显式通配符。 - `dmPolicy: "allowlist"` 搭配空的 `allowFrom` 会阻止所有私信,并会被配置校验拒绝。 - 设置只会要求数字用户 ID。 - 如果你已升级且配置包含 `@username` 允许列表条目,请运行 `openclaw doctor --fix` 解析它们(尽力而为;需要 Telegram 机器人令牌)。 - 如果你之前依赖配对存储允许列表文件,`openclaw doctor --fix` 可以在 allowlist 流程中将条目恢复到 `channels.telegram.allowFrom`(例如当 `dmPolicy: "allowlist"` 还没有显式 ID 时)。 + `dmPolicy: "allowlist"` 搭配空 `allowFrom` 会阻止所有私信,并会被配置校验拒绝。 + 设置只会询问数字用户 ID。 + 如果你已升级且配置中包含 `@username` 允许列表条目,请运行 `openclaw doctor --fix` 解析它们(尽力而为;需要 Telegram 机器人令牌)。 + 如果你之前依赖配对存储允许列表文件,`openclaw doctor --fix` 可以在允许列表流程中将条目恢复到 `channels.telegram.allowFrom`(例如当 `dmPolicy: "allowlist"` 还没有显式 ID 时)。 - 对于单所有者机器人,建议使用 `dmPolicy: "allowlist"` 并配合显式数字 `allowFrom` ID,以便将访问策略持久保存在配置中(而不是依赖先前的配对批准)。 + 对于单所有者机器人,优先使用带显式数字 `allowFrom` ID 的 `dmPolicy: "allowlist"`,以便访问策略持久保存在配置中(而不是依赖之前的配对批准)。 - 常见混淆:私信配对批准并不表示“此发送者在所有地方都已授权”。 - 配对授予私信访问权限。如果尚不存在命令所有者,第一次获批的配对也会设置 `commands.ownerAllowFrom`,让仅所有者命令和执行批准拥有一个显式操作账号。 + 常见困惑:私信配对批准并不意味着“此发送者在所有地方都已获授权”。 + 配对授予私信访问权限。如果尚不存在命令所有者,首次获批配对还会设置 `commands.ownerAllowFrom`,使仅所有者命令和执行批准拥有明确的操作员账号。 群组发送者授权仍来自显式配置允许列表。 - 如果你希望“我授权一次后,私信和群组命令都可用”,请把你的数字 Telegram 用户 ID 放入 `channels.telegram.allowFrom`;对于仅所有者命令,请确保 `commands.ownerAllowFrom` 包含 `telegram:`。 + 如果你想要“我授权一次后,私信和群组命令都可用”,请将你的数字 Telegram 用户 ID 放入 `channels.telegram.allowFrom`;对于仅所有者命令,请确保 `commands.ownerAllowFrom` 包含 `telegram:`。 ### 查找你的 Telegram 用户 ID - 更安全的方法(无第三方机器人): + 更安全(无需第三方机器人): 1. 私信你的机器人。 2. 运行 `openclaw logs --follow`。 @@ -153,13 +153,13 @@ curl "https://api.telegram.org/bot/getUpdates" - 两个控制项会共同生效: + 两项控制会一起生效: 1. **允许哪些群组**(`channels.telegram.groups`) - 没有 `groups` 配置: - 搭配 `groupPolicy: "open"`:任何群组都可以通过群组 ID 检查 - 搭配 `groupPolicy: "allowlist"`(默认):群组会被阻止,直到你添加 `groups` 条目(或 `"*"`) - - 已配置 `groups`:充当允许列表(显式 ID 或 `"*"`) + - 已配置 `groups`:作为允许列表(显式 ID 或 `"*"`) 2. **群组中允许哪些发送者**(`channels.telegram.groupPolicy`) - `open` @@ -168,15 +168,15 @@ curl "https://api.telegram.org/bot/getUpdates" `groupAllowFrom` 用于群组发送者过滤。如果未设置,Telegram 会回退到 `allowFrom`。 `groupAllowFrom` 条目应为数字 Telegram 用户 ID(`telegram:` / `tg:` 前缀会被规范化)。 - 不要将 Telegram 群组或超级群组聊天 ID 放入 `groupAllowFrom`。负数聊天 ID 属于 `channels.telegram.groups`。 + 不要将 Telegram 群组或超级群组聊天 ID 放入 `groupAllowFrom`。负数聊天 ID 应放在 `channels.telegram.groups` 下。 非数字条目会在发送者授权中被忽略。 安全边界(`2026.2.25+`):群组发送者认证**不会**继承私信配对存储批准。 - 配对仅适用于私信。对于群组,请设置 `groupAllowFrom` 或按群组/按话题设置 `allowFrom`。 + 配对仍仅限私信。对于群组,请设置 `groupAllowFrom` 或按群组/按话题设置 `allowFrom`。 如果未设置 `groupAllowFrom`,Telegram 会回退到配置中的 `allowFrom`,而不是配对存储。 单所有者机器人的实用模式:在 `channels.telegram.allowFrom` 中设置你的用户 ID,保持 `groupAllowFrom` 未设置,并在 `channels.telegram.groups` 下允许目标群组。 运行时注意事项:如果完全缺少 `channels.telegram`,运行时会默认故障关闭为 `groupPolicy="allowlist"`,除非显式设置了 `channels.defaults.groupPolicy`。 - 示例:允许一个特定群组中的任何成员: + 示例:允许某个特定群组中的任何成员: ```json5 { @@ -193,7 +193,7 @@ curl "https://api.telegram.org/bot/getUpdates" } ``` - 示例:仅允许一个特定群组内的特定用户: + 示例:仅允许某个特定群组中的特定用户: ```json5 { @@ -213,21 +213,21 @@ curl "https://api.telegram.org/bot/getUpdates" 常见错误:`groupAllowFrom` 不是 Telegram 群组允许列表。 - - 将类似 `-1001234567890` 的负数 Telegram 群组或超级群组聊天 ID 放在 `channels.telegram.groups` 下。 - - 当你想限制允许群组内哪些人可以触发机器人时,将类似 `8734062810` 的 Telegram 用户 ID 放在 `groupAllowFrom` 下。 - - 仅当你希望允许群组的任何成员都能与机器人对话时,才使用 `groupAllowFrom: ["*"]`。 + - 将像 `-1001234567890` 这样的负数 Telegram 群组或超级群组聊天 ID 放在 `channels.telegram.groups` 下。 + - 当你想限制已允许群组内哪些人可以触发机器人时,将像 `8734062810` 这样的 Telegram 用户 ID 放在 `groupAllowFrom` 下。 + - 仅当你希望已允许群组中的任何成员都能与机器人对话时,才使用 `groupAllowFrom: ["*"]`。 - 群组回复默认要求提及。 + 群组回复默认需要提及。 提及可以来自: - 原生 `@botusername` 提及,或 - - 以下位置的提及模式: + - 以下位置中的提及模式: - `agents.list[].groupChat.mentionPatterns` - `messages.groupChat.mentionPatterns` @@ -236,9 +236,9 @@ curl "https://api.telegram.org/bot/getUpdates" - `/activation always` - `/activation mention` - 这些只会更新会话状态。使用配置实现持久化。 + 这些只会更新会话状态。使用配置来持久化。 - 持久配置示例: + 持久化配置示例: ```json5 { @@ -264,19 +264,19 @@ curl "https://api.telegram.org/bot/getUpdates" ## 运行时行为 - Telegram 由 Gateway 网关进程拥有。 -- 路由是确定性的:Telegram 入站消息会回复到 Telegram(模型不会选择渠道)。 -- 入站消息会规范化为共享渠道信封,并带有回复元数据和媒体占位符。 +- 路由是确定性的:Telegram 入站会回复到 Telegram(模型不会选择渠道)。 +- 入站消息会规范化为共享渠道信封,并包含回复元数据和媒体占位符。 - 群组会话按群组 ID 隔离。论坛话题会追加 `:topic:` 以保持话题隔离。 -- 私信消息可以携带 `message_thread_id`;OpenClaw 会保留线程 ID 用于回复,但默认让私信保持在扁平会话上。当你确实需要私信话题会话隔离时,请配置 `channels.telegram.dm.threadReplies: "inbound"`、`channels.telegram.direct..threadReplies: "inbound"`、`requireTopic: true`,或匹配的话题配置。 +- 私信消息可以携带 `message_thread_id`;OpenClaw 会保留线程 ID 用于回复,但默认将私信保持在扁平会话中。当你有意需要私信话题会话隔离时,请配置 `channels.telegram.dm.threadReplies: "inbound"`、`channels.telegram.direct..threadReplies: "inbound"`、`requireTopic: true`,或匹配的话题配置。 - 长轮询使用 grammY runner,并按聊天/按线程排序。整体 runner sink 并发使用 `agents.defaults.maxConcurrent`。 -- 每个 Gateway 网关进程内部都会保护长轮询,因此一次只有一个活跃轮询器可以使用一个机器人令牌。如果你仍看到 `getUpdates` 409 冲突,很可能是另一个 OpenClaw Gateway 网关、脚本或外部轮询器正在使用同一个令牌。 -- 默认情况下,如果 120 秒内没有完成的 `getUpdates` 活性信号,就会触发长轮询 watchdog 重启。仅当你的部署在长时间运行工作期间仍出现误判的轮询停滞重启时,才增大 `channels.telegram.pollingStallThresholdMs`。该值以毫秒为单位,允许范围为 `30000` 到 `600000`;支持按账号覆盖。 +- 长轮询在每个 Gateway 网关进程内受到保护,因此一次只有一个活跃轮询器可以使用某个机器人令牌。如果你仍看到 `getUpdates` 409 冲突,很可能另一个 OpenClaw Gateway 网关、脚本或外部轮询器正在使用同一个令牌。 +- 长轮询 watchdog 重启默认会在 120 秒内没有完成的 `getUpdates` 存活信号后触发。仅当你的部署在长时间运行工作期间仍出现误判的轮询停滞重启时,才增大 `channels.telegram.pollingStallThresholdMs`。该值以毫秒为单位,允许范围为 `30000` 到 `600000`;支持按账号覆盖。 - Telegram Bot API 不支持已读回执(`sendReadReceipts` 不适用)。 ## 功能参考 - + OpenClaw 可以实时流式传输部分回复: - 直接聊天:预览消息 + `editMessageText` @@ -286,10 +286,10 @@ curl "https://api.telegram.org/bot/getUpdates" - `channels.telegram.streaming` 为 `off | partial | block | progress`(默认:`partial`) - `progress` 在 Telegram 上映射为 `partial`(兼容跨渠道命名) - - `streaming.preview.toolProgress` 控制工具/进度更新是否复用同一条已编辑预览消息(默认:预览流式传输处于活跃状态时为 `true`) - - 会检测旧版 `channels.telegram.streamMode` 和布尔 `streaming` 值;运行 `openclaw doctor --fix` 将它们迁移到 `channels.telegram.streaming.mode` + - `streaming.preview.toolProgress` 控制工具/进度更新是否复用同一条已编辑的预览消息(默认:预览流式传输启用时为 `true`) + - 会检测旧版 `channels.telegram.streamMode` 和布尔型 `streaming` 值;运行 `openclaw doctor --fix` 将它们迁移到 `channels.telegram.streaming.mode` - 工具进度预览更新是在工具运行时显示的短 “Working...” 行,例如命令执行、文件读取、计划更新或补丁摘要。Telegram 默认保持这些更新启用,以匹配 `v2026.4.22` 及更高版本发布的 OpenClaw 行为。若要保留用于答案文本的已编辑预览,但隐藏工具进度行,请设置: + 工具进度预览更新是在工具运行时显示的简短“正在工作...”行,例如命令执行、文件读取、规划更新或补丁摘要。Telegram 默认保持这些更新启用,以匹配 `v2026.4.22` 及之后版本发布的 OpenClaw 行为。若要为回答文本保留已编辑预览,但隐藏工具进度行,请设置: ```json { @@ -306,20 +306,24 @@ curl "https://api.telegram.org/bot/getUpdates" } ``` - Use `streaming.mode: "off"` 仅在你需要只交付最终回复时使用:Telegram 预览编辑会被禁用,通用工具/进度提示会被抑制,而不是作为独立的 “Working...” 消息发送。审批提示、媒体载荷和错误仍然通过正常的最终交付路径发送。仅想保留答案预览编辑、同时隐藏工具进度状态行时,使用 `streaming.preview.toolProgress: false`。 + 仅在你想要只交付最终结果时使用 `streaming.mode: "off"`:Telegram 预览编辑会被禁用,通用的工具/进度闲聊会被抑制,而不是作为独立的 “Working...” 消息发送。审批提示、媒体载荷和错误仍会通过正常的最终交付路径发送。仅当你只想保留答案预览编辑,同时隐藏工具进度状态行时,使用 `streaming.preview.toolProgress: false`。 + + + Telegram 选中文本引用回复是例外。当 `replyToMode` 为 `"first"`、`"all"` 或 `"batched"`,并且入站消息包含选中的引用文本时,OpenClaw 会通过 Telegram 原生引用回复路径发送最终答案,而不是编辑答案预览,因此 `streaming.preview.toolProgress` 无法为该轮显示简短的 “Working...” 行。没有选中引用文本的当前消息回复仍会保留预览流式传输。当工具进度可见性比原生引用回复更重要时,设置 `replyToMode: "off"`;或设置 `streaming.preview.toolProgress: false` 来确认这一权衡。 + 对于纯文本回复: - - 简短的私信/群组/话题预览:OpenClaw 保留同一条预览消息,并原地执行最终编辑 - - 超过约一分钟的预览:OpenClaw 将完成的回复作为新的最终消息发送,然后清理预览,这样 Telegram 可见的时间戳会反映完成时间,而不是预览创建时间 + - 短私信/群组/话题预览:OpenClaw 会保留同一条预览消息,并在原位置执行最终编辑 + - 超过大约一分钟的预览:OpenClaw 会将完成的回复作为新的最终消息发送,然后清理预览,因此 Telegram 可见的时间戳会反映完成时间,而不是预览创建时间 - 对于复杂回复(例如媒体载荷),OpenClaw 会回退到正常的最终交付,然后清理预览消息。 + 对于复杂回复(例如媒体载荷),OpenClaw 会回退到正常最终交付,然后清理预览消息。 - 预览流式传输独立于分块流式传输。当 Telegram 明确启用分块流式传输时,OpenClaw 会跳过预览流,以避免重复流式传输。 + 预览流式传输独立于分块流式传输。当为 Telegram 显式启用分块流式传输时,OpenClaw 会跳过预览流,以避免双重流式传输。 - 仅 Telegram 的推理流: + 仅限 Telegram 的推理流: - - `/reasoning stream` 会在生成过程中把推理发送到实时预览 + - `/reasoning stream` 会在生成期间将推理发送到实时预览 - 最终答案发送时不包含推理文本 @@ -340,9 +344,9 @@ curl "https://api.telegram.org/bot/getUpdates" 原生命令默认值: - - `commands.native: "auto"` 为 Telegram 启用原生命令 + - `commands.native: "auto"` 会为 Telegram 启用原生命令 - 添加自定义命令菜单项: + 添加自定义命令菜单条目: ```json5 { @@ -359,24 +363,24 @@ curl "https://api.telegram.org/bot/getUpdates" 规则: - - 名称会规范化(去掉开头的 `/`,转为小写) + - 名称会规范化(去掉开头的 `/`,转换为小写) - 有效模式:`a-z`、`0-9`、`_`,长度 `1..32` - 自定义命令不能覆盖原生命令 - 冲突/重复项会被跳过并记录日志 - 注意事项: + 说明: - - 自定义命令只是菜单项;它们不会自动实现行为 - - 插件/skill 命令即使未显示在 Telegram 菜单中,输入时仍可工作 + - 自定义命令只是菜单条目;它们不会自动实现行为 + - 插件/Skills 命令即使未显示在 Telegram 菜单中,输入时仍可工作 - 如果禁用原生命令,内置命令会被移除。自定义/插件命令在已配置时仍可注册。 + 如果禁用原生命令,内置命令会被移除。自定义/插件命令在配置后仍可注册。 常见设置失败: - - `setMyCommands failed` 搭配 `BOT_COMMANDS_TOO_MUCH` 表示 Telegram 菜单在裁剪后仍然超出上限;减少插件/skill/自定义命令,或禁用 `channels.telegram.commands.native`。 - - `deleteWebhook`、`deleteMyCommands` 或 `setMyCommands` 失败并显示 `404: Not Found`,但直接的 Bot API curl 命令可用,可能表示 `channels.telegram.apiRoot` 被设置成了完整的 `/bot` 端点。`apiRoot` 必须只是 Bot API 根地址,`openclaw doctor --fix` 会移除意外尾随的 `/bot`。 - - `getMe returned 401` 表示 Telegram 拒绝了配置的 bot token。使用当前 BotFather token 更新 `botToken`、`tokenFile` 或 `TELEGRAM_BOT_TOKEN`;OpenClaw 会在轮询前停止,因此这不会被报告为 webhook 清理失败。 - - `setMyCommands failed` 搭配网络/fetch 错误通常表示到 `api.telegram.org` 的出站 DNS/HTTPS 被阻止。 + - `setMyCommands failed` 并带有 `BOT_COMMANDS_TOO_MUCH`,表示 Telegram 菜单在裁剪后仍然溢出;减少插件/Skills/自定义命令,或禁用 `channels.telegram.commands.native`。 + - 当直接使用 Bot API curl 命令可以工作,但 `deleteWebhook`、`deleteMyCommands` 或 `setMyCommands` 失败并带有 `404: Not Found` 时,可能表示 `channels.telegram.apiRoot` 被设置成了完整的 `/bot` 端点。`apiRoot` 必须只是 Bot API 根地址,`openclaw doctor --fix` 会移除意外结尾的 `/bot`。 + - `getMe returned 401` 表示 Telegram 拒绝了配置的机器人令牌。使用当前 BotFather 令牌更新 `botToken`、`tokenFile` 或 `TELEGRAM_BOT_TOKEN`;OpenClaw 会在轮询前停止,因此这不会被报告为 webhook 清理失败。 + - `setMyCommands failed` 并带有网络/fetch 错误,通常表示到 `api.telegram.org` 的出站 DNS/HTTPS 被阻止。 ### 设备配对命令(`device-pair` 插件) @@ -384,22 +388,22 @@ curl "https://api.telegram.org/bot/getUpdates" 1. `/pair` 生成设置代码 2. 在 iOS 应用中粘贴代码 - 3. `/pair pending` 列出待处理请求(包括角色/范围) + 3. `/pair pending` 列出待处理请求(包括角色/作用域) 4. 批准请求: - `/pair approve ` 用于显式批准 - - 只有一个待处理请求时使用 `/pair approve` - - `/pair approve latest` 用于最近的请求 + - 当只有一个待处理请求时使用 `/pair approve` + - `/pair approve latest` 用于最新请求 - 设置代码携带一个短期有效的引导 token。内置引导交接会将主节点 token 保持在 `scopes: []`;任何交接的操作员 token 都会限制在 `operator.approvals`、`operator.read`、`operator.talk.secrets` 和 `operator.write` 内。引导范围检查带有角色前缀,因此该操作员 allowlist 只满足操作员请求;非操作员角色仍需要自己角色前缀下的范围。 + 设置代码携带一个短期有效的引导令牌。内置引导交接会把主节点令牌保持在 `scopes: []`;任何交接出去的操作员令牌都会被限制在 `operator.approvals`、`operator.read`、`operator.talk.secrets` 和 `operator.write`。引导作用域检查带有角色前缀,因此该操作员允许列表只满足操作员请求;非操作员角色仍需要其自身角色前缀下的作用域。 - 如果设备使用已更改的认证详情(例如角色/范围/公钥)重试,先前的待处理请求会被取代,新请求会使用不同的 `requestId`。批准前请重新运行 `/pair pending`。 + 如果设备使用变更后的认证详情重试(例如角色/作用域/公钥),先前的待处理请求会被取代,新请求会使用不同的 `requestId`。批准前请重新运行 `/pair pending`。 更多详情:[配对](/zh-CN/channels/pairing#pair-via-telegram-recommended-for-ios)。 - 配置内联键盘范围: + 配置内联键盘作用域: ```json5 { @@ -413,7 +417,7 @@ curl "https://api.telegram.org/bot/getUpdates" } ``` - 按账户覆盖: + 按账号覆盖: ```json5 { @@ -431,7 +435,7 @@ curl "https://api.telegram.org/bot/getUpdates" } ``` - 范围: + 作用域: - `off` - `dm` @@ -439,7 +443,7 @@ curl "https://api.telegram.org/bot/getUpdates" - `all` - `allowlist`(默认) - 旧版 `capabilities: ["inlineButtons"]` 映射到 `inlineButtons: "all"`。 + 旧版 `capabilities: ["inlineButtons"]` 会映射到 `inlineButtons: "all"`。 消息操作示例: @@ -464,7 +468,7 @@ curl "https://api.telegram.org/bot/getUpdates" - + Telegram 工具操作包括: - `sendMessage`(`to`、`content`、可选 `mediaUrl`、`replyToMessageId`、`messageThreadId`) @@ -473,19 +477,19 @@ curl "https://api.telegram.org/bot/getUpdates" - `editMessage`(`chatId`、`messageId`、`content`) - `createForumTopic`(`chatId`、`name`、可选 `iconColor`、`iconCustomEmojiId`) - 渠道消息操作公开了易用别名(`send`、`react`、`delete`、`edit`、`sticker`、`sticker-search`、`topic-create`)。 + 渠道消息操作会公开便捷别名(`send`、`react`、`delete`、`edit`、`sticker`、`sticker-search`、`topic-create`)。 - 门控控制: + 门控控制项: - `channels.telegram.actions.sendMessage` - `channels.telegram.actions.deleteMessage` - `channels.telegram.actions.reactions` - `channels.telegram.actions.sticker`(默认:禁用) - 注意:`edit` 和 `topic-create` 当前默认启用,并且没有单独的 `channels.telegram.actions.*` 开关。 - 运行时发送使用活动的配置/密钥快照(启动/重新加载),因此操作路径不会在每次发送时执行临时 SecretRef 重新解析。 + 注意:`edit` 和 `topic-create` 目前默认启用,并且没有单独的 `channels.telegram.actions.*` 开关。 + 运行时发送使用活动配置/密钥快照(启动/重载),因此操作路径不会在每次发送时执行临时 SecretRef 重新解析。 - 表情反应移除语义:[/tools/reactions](/zh-CN/tools/reactions) + 移除反应语义:[/tools/reactions](/zh-CN/tools/reactions) @@ -501,9 +505,9 @@ curl "https://api.telegram.org/bot/getUpdates" - `first` - `all` - 启用回复线程,并且原始 Telegram 文本或说明文字可用时,OpenClaw 会自动包含原生 Telegram 引用摘录。Telegram 将原生引用文本限制为 1024 个 UTF-16 代码单元,因此更长的消息会从开头引用;如果 Telegram 拒绝引用,则回退到普通回复。 + 当启用回复线程,并且原始 Telegram 文本或标题可用时,OpenClaw 会自动包含原生 Telegram 引用摘录。Telegram 将原生引用文本限制为 1024 个 UTF-16 码元,因此更长的消息会从开头引用;如果 Telegram 拒绝该引用,则回退为普通回复。 - 注意:`off` 会禁用隐式回复线程。显式 `[[reply_to_*]]` 标签仍会生效。 + 注意:`off` 会禁用隐式回复线程。显式 `[[reply_to_*]]` 标签仍会被遵循。 @@ -511,19 +515,19 @@ curl "https://api.telegram.org/bot/getUpdates" 论坛超级群组: - 话题会话键追加 `:topic:` - - 回复和输入状态会指向话题线程 + - 回复和正在输入状态会指向话题线程 - 话题配置路径: `channels.telegram.groups..topics.` - 常规话题(`threadId=1`)特殊情况: + 常规话题(`threadId=1`)特殊处理: - 消息发送会省略 `message_thread_id`(Telegram 会拒绝 `sendMessage(...thread_id=1)`) - - 输入状态操作仍包含 `message_thread_id` + - 正在输入操作仍包含 `message_thread_id` - 话题继承:除非覆盖,话题条目会继承群组设置(`requireMention`、`allowFrom`、`skills`、`systemPrompt`、`enabled`、`groupPolicy`)。 + 话题继承:话题条目会继承群组设置,除非被覆盖(`requireMention`、`allowFrom`、`skills`、`systemPrompt`、`enabled`、`groupPolicy`)。 `agentId` 仅适用于话题,不会从群组默认值继承。 - **按话题的智能体路由**:每个话题都可以通过在话题配置中设置 `agentId` 路由到不同的智能体。这让每个话题都有自己的隔离工作区、记忆和会话。示例: + **按话题进行智能体路由**:每个话题都可以通过在话题配置中设置 `agentId` 路由到不同的智能体。这会让每个话题拥有自己的隔离工作区、记忆和会话。示例: ```json5 { @@ -543,26 +547,26 @@ curl "https://api.telegram.org/bot/getUpdates" } ``` - 然后每个话题都有自己的会话键:`agent:zu:telegram:group:-1001234567890:topic:3` + 然后,每个话题都有自己的会话键:`agent:zu:telegram:group:-1001234567890:topic:3` - **持久 ACP 话题绑定**:论坛话题可以通过顶层类型化 ACP 绑定(`bindings[]`,其中 `type: "acp"`、`match.channel: "telegram"`、`peer.kind: "group"`,以及类似 `-1001234567890:topic:42` 的带话题限定 ID)固定 ACP harness 会话。当前范围限于群组/超级群组中的论坛话题。参见 [ACP 智能体](/zh-CN/tools/acp-agents)。 + **持久 ACP 话题绑定**:论坛话题可以通过顶层类型化 ACP 绑定固定 ACP harness 会话(`bindings[]`,其中 `type: "acp"` 且 `match.channel: "telegram"`、`peer.kind: "group"`,并使用类似 `-1001234567890:topic:42` 的话题限定 ID)。目前范围限定在群组/超级群组中的论坛话题。参见 [ACP 智能体](/zh-CN/tools/acp-agents)。 - **从聊天生成线程绑定的 ACP**:`/acp spawn --thread here|auto` 会将当前话题绑定到新的 ACP 会话;后续消息会直接路由到那里。OpenClaw 会在话题内固定生成确认。需要 `channels.telegram.threadBindings.spawnSessions` 保持启用(默认:`true`)。 + **从聊天生成线程绑定 ACP**:`/acp spawn --thread here|auto` 会将当前话题绑定到新的 ACP 会话;后续消息会直接路由到那里。OpenClaw 会在话题内固定生成确认。需要保持 `channels.telegram.threadBindings.spawnSessions` 启用(默认:`true`)。 - 模板上下文公开 `MessageThreadId` 和 `IsForum`。带有 `message_thread_id` 的私信聊天默认会保留私信路由,并在扁平会话上保留回复元数据;只有在配置了 `threadReplies: "inbound"`、`threadReplies: "always"`、`requireTopic: true` 或匹配的话题配置时,才会使用线程感知会话键。使用顶层 `channels.telegram.dm.threadReplies` 设置账户默认值,或为单个私信使用 `direct..threadReplies`。 + 模板上下文会公开 `MessageThreadId` 和 `IsForum`。带有 `message_thread_id` 的私信聊天默认会在扁平会话上保留私信路由和回复元数据;只有在配置了 `threadReplies: "inbound"`、`threadReplies: "always"`、`requireTopic: true` 或匹配的话题配置时,才会使用线程感知的会话键。使用顶层 `channels.telegram.dm.threadReplies` 设置账号默认值,或使用 `direct..threadReplies` 设置单个私信。 ### 音频消息 - Telegram 区分语音消息和音频文件。 + Telegram 会区分语音便签和音频文件。 - 默认:音频文件行为 - - 在智能体回复中使用标签 `[[audio_as_voice]]` 强制发送语音消息 - - 入站语音消息转写会在智能体上下文中被框定为机器生成的、 - 不可信文本;提及检测仍使用原始 - 转写,因此提及门控的语音消息仍能工作。 + - 在智能体回复中使用标签 `[[audio_as_voice]]` 强制以语音便签发送 + - 入站语音便签转录会在智能体上下文中被框定为机器生成、 + 不可信文本;提及检测仍会使用原始 + 转录,因此受提及门控的语音消息会继续工作。 消息操作示例: @@ -578,7 +582,7 @@ curl "https://api.telegram.org/bot/getUpdates" ### 视频消息 - Telegram 区分视频文件和视频消息。 + Telegram 会区分视频文件和视频便签。 消息操作示例: @@ -592,7 +596,7 @@ curl "https://api.telegram.org/bot/getUpdates" } ``` - 视频消息不支持说明文字;提供的消息文本会单独发送。 + 视频备注不支持字幕;提供的消息文本会单独发送。 ### 贴纸 @@ -614,7 +618,7 @@ curl "https://api.telegram.org/bot/getUpdates" - `~/.openclaw/telegram/sticker-cache.json` - 贴纸会被描述一次(如果可能),并缓存以减少重复的视觉调用。 + 贴纸会在可行时描述一次并缓存,以减少重复的视觉调用。 启用贴纸操作: @@ -641,7 +645,7 @@ curl "https://api.telegram.org/bot/getUpdates" } ``` - 搜索缓存的贴纸: + 搜索已缓存的贴纸: ```json5 { @@ -654,8 +658,8 @@ curl "https://api.telegram.org/bot/getUpdates" - - Telegram 回应会作为 `message_reaction` 更新到达(与消息载荷分离)。 + + Telegram 表情回应会作为 `message_reaction` 更新到达(独立于消息负载)。 启用后,OpenClaw 会将如下系统事件加入队列: @@ -666,19 +670,19 @@ curl "https://api.telegram.org/bot/getUpdates" - `channels.telegram.reactionNotifications`:`off | own | all`(默认:`own`) - `channels.telegram.reactionLevel`:`off | ack | minimal | extensive`(默认:`minimal`) - 说明: + 注意事项: - - `own` 表示仅限用户对机器人发送消息的回应(通过已发送消息缓存尽力判断)。 - - 回应事件仍会遵循 Telegram 访问控制(`dmPolicy`、`allowFrom`、`groupPolicy`、`groupAllowFrom`);未授权的发送者会被丢弃。 - - Telegram 不会在回应更新中提供话题 ID。 - - 非论坛群组路由到群聊会话 - - 论坛群组路由到群组通用话题会话(`:topic:1`),而不是精确的原始话题 + - `own` 表示仅限用户对机器人发送消息的表情回应(通过已发送消息缓存尽力判断)。 + - 表情回应事件仍会遵循 Telegram 访问控制(`dmPolicy`、`allowFrom`、`groupPolicy`、`groupAllowFrom`);未授权发送者会被丢弃。 + - Telegram 不会在表情回应更新中提供话题 ID。 + - 非论坛群组会路由到群聊会话 + - 论坛群组会路由到群组通用话题会话(`:topic:1`),而不是精确的原始话题 用于轮询/webhook 的 `allowed_updates` 会自动包含 `message_reaction`。 - + `ackReaction` 会在 OpenClaw 处理入站消息时发送一个确认 emoji。 解析顺序: @@ -688,10 +692,10 @@ curl "https://api.telegram.org/bot/getUpdates" - `messages.ackReaction` - 智能体身份 emoji 兜底(`agents.list[].identity.emoji`,否则为 "👀") - 说明: + 注意事项: - - Telegram 需要 unicode emoji(例如 "👀")。 - - 使用 `""` 可禁用某个渠道或账号的回应。 + - Telegram 期望使用 unicode emoji(例如 "👀")。 + - 使用 `""` 可为某个渠道或账户禁用该表情回应。 @@ -718,28 +722,28 @@ curl "https://api.telegram.org/bot/getUpdates" - 默认是长轮询。对于 webhook 模式,设置 `channels.telegram.webhookUrl` 和 `channels.telegram.webhookSecret`;可选 `webhookPath`、`webhookHost`、`webhookPort`(默认值为 `/telegram-webhook`、`127.0.0.1`、`8787`)。 + 默认使用长轮询。对于 webhook 模式,请设置 `channels.telegram.webhookUrl` 和 `channels.telegram.webhookSecret`;可选设置 `webhookPath`、`webhookHost`、`webhookPort`(默认值为 `/telegram-webhook`、`127.0.0.1`、`8787`)。 本地监听器绑定到 `127.0.0.1:8787`。对于公网入口,可以在本地端口前放置反向代理,或有意设置 `webhookHost: "0.0.0.0"`。 - webhook 模式会先验证请求保护、Telegram secret token 和 JSON 正文,然后再向 Telegram 返回 `200`。 - 随后 OpenClaw 会通过与长轮询相同的按聊天/按话题机器人通道异步处理该更新,因此缓慢的智能体轮次不会阻塞 Telegram 的投递 ACK。 + Webhook 模式会在向 Telegram 返回 `200` 之前验证请求保护、Telegram secret token 和 JSON body。 + 随后,OpenClaw 会通过与长轮询相同的按聊天/按话题机器人通道异步处理更新,因此较慢的智能体轮次不会阻塞 Telegram 的投递 ACK。 - - `channels.telegram.textChunkLimit` 默认是 4000。 - - `channels.telegram.chunkMode="newline"` 在按长度拆分前优先使用段落边界(空行)。 + - `channels.telegram.textChunkLimit` 默认值为 4000。 + - `channels.telegram.chunkMode="newline"` 会在按长度拆分前优先使用段落边界(空行)。 - `channels.telegram.mediaMaxMb`(默认 100)限制入站和出站 Telegram 媒体大小。 - - `channels.telegram.timeoutSeconds` 会覆盖 Telegram API 客户端超时(如果未设置,则使用 grammY 默认值)。机器人客户端会将配置值限制在 60 秒出站文本/输入中请求保护以下,避免 grammY 在 OpenClaw 的传输保护和兜底能够运行之前中止可见回复投递。长轮询仍使用 45 秒 `getUpdates` 请求保护,因此空闲轮询不会被无限期放弃。 - - `channels.telegram.pollingStallThresholdMs` 默认是 `120000`;仅在误报轮询停滞重启时,在 `30000` 到 `600000` 之间调整。 + - `channels.telegram.timeoutSeconds` 会覆盖 Telegram API 客户端超时(如果未设置,则使用 grammY 默认值)。机器人客户端会将配置值限制在 60 秒出站文本/输入状态请求保护以下,避免 grammY 在 OpenClaw 的传输保护和兜底逻辑运行前中止可见回复投递。长轮询仍使用 45 秒 `getUpdates` 请求保护,因此空闲轮询不会无限期挂起。 + - `channels.telegram.pollingStallThresholdMs` 默认值为 `120000`;仅在轮询停滞重启出现误报时,在 `30000` 到 `600000` 之间调整。 - 群组上下文历史使用 `channels.telegram.historyLimit` 或 `messages.groupChat.historyLimit`(默认 50);`0` 表示禁用。 - - 回复/引用/转发的补充上下文目前按接收原样传递。 - - Telegram 允许列表主要限制谁可以触发智能体,并不是完整的补充上下文删改边界。 + - 回复/引用/转发的补充上下文目前会按收到的内容传递。 + - Telegram allowlist 主要控制谁可以触发智能体,而不是完整的补充上下文脱敏边界。 - 私信历史控制: - `channels.telegram.dmHistoryLimit` - `channels.telegram.dms[""].historyLimit` - - `channels.telegram.retry` 配置适用于 Telegram 发送辅助能力(CLI/工具/操作)中的可恢复出站 API 错误。入站最终回复投递也会对 Telegram 预连接失败使用有界安全发送重试,但不会重试可能重复可见消息的发送后网络信封不明确情况。 + - `channels.telegram.retry` 配置适用于 Telegram 发送辅助函数(CLI/工具/操作)中的可恢复出站 API 错误。入站最终回复投递也会对 Telegram 预连接失败使用有界的安全发送重试,但不会重试可能重复可见消息的模糊发送后网络信封。 CLI 发送目标可以是数字聊天 ID 或用户名: @@ -758,57 +762,57 @@ openclaw message poll --channel telegram --target -1001234567890:topic:42 \ --poll-duration-seconds 300 --poll-public ``` - 仅 Telegram 支持的投票标志: + 仅限 Telegram 的投票标志: - `--poll-duration-seconds`(5-600) - `--poll-anonymous` - `--poll-public` - - 用于论坛话题的 `--thread-id`(或使用 `:topic:` 目标) + - `--thread-id` 用于论坛话题(也可使用 `:topic:` 目标) Telegram 发送还支持: - - 当 `channels.telegram.capabilities.inlineButtons` 允许时,使用带有 `buttons` 块的 `--presentation` 发送内联键盘 - - 当机器人可在该聊天中置顶时,使用 `--pin` 或 `--delivery '{"pin":true}'` 请求置顶投递 + - 当 `channels.telegram.capabilities.inlineButtons` 允许时,使用带有 `buttons` 块的 `--presentation` 创建内联键盘 + - 使用 `--pin` 或 `--delivery '{"pin":true}'` 在机器人可在该聊天中置顶时请求置顶投递 - 使用 `--force-document` 将出站图片和 GIF 作为文档发送,而不是压缩照片或动画媒体上传 - 操作门控: + 操作控制: - `channels.telegram.actions.sendMessage=false` 会禁用出站 Telegram 消息,包括投票 - - `channels.telegram.actions.poll=false` 会禁用 Telegram 投票创建,同时保留常规发送启用 + - `channels.telegram.actions.poll=false` 会禁用 Telegram 投票创建,同时保留常规发送功能 - - Telegram 支持在审批者私信中进行 exec 审批,并可选地在原始聊天或话题中发布提示。审批者必须是数字 Telegram 用户 ID。 + + Telegram 支持在审批者私信中进行执行审批,也可以选择在原始聊天或话题中发布提示。审批者必须是数字 Telegram 用户 ID。 配置路径: - - `channels.telegram.execApprovals.enabled`(当至少有一个审批者可解析时自动启用) - - `channels.telegram.execApprovals.approvers`(回退到来自 `commands.ownerAllowFrom` 的数字所有者 ID) + - `channels.telegram.execApprovals.enabled`(当至少一个审批者可解析时自动启用) + - `channels.telegram.execApprovals.approvers`(回退到 `commands.ownerAllowFrom` 中的数字 owner ID) - `channels.telegram.execApprovals.target`:`dm`(默认)| `channel` | `both` - `agentFilter`、`sessionFilter` - `channels.telegram.allowFrom`、`groupAllowFrom` 和 `defaultTo` 控制谁可以与机器人交谈,以及它向哪里发送普通回复。它们不会让某人成为 exec 审批者。当尚不存在命令所有者时,首次获批的私信配对会引导写入 `commands.ownerAllowFrom`,因此单所有者设置无需在 `execApprovals.approvers` 下重复 ID 也能正常工作。 + `channels.telegram.allowFrom`、`groupAllowFrom` 和 `defaultTo` 控制谁可以与机器人对话以及正常回复发送到哪里。它们不会让某人成为执行审批者。当尚不存在命令 owner 时,第一次获批的私信配对会引导生成 `commands.ownerAllowFrom`,因此单 owner 设置仍可工作,而无需在 `execApprovals.approvers` 下重复 ID。 - 渠道投递会在聊天中显示命令文本;仅在可信群组/话题中启用 `channel` 或 `both`。当提示落在论坛话题中时,OpenClaw 会为审批提示和后续消息保留该话题。exec 审批默认在 30 分钟后过期。 + 渠道投递会在聊天中显示命令文本;仅在可信群组/话题中启用 `channel` 或 `both`。当提示落在论坛话题中时,OpenClaw 会为审批提示和后续消息保留该话题。执行审批默认在 30 分钟后过期。 - 内联审批按钮还需要 `channels.telegram.capabilities.inlineButtons` 允许目标表面(`dm`、`group` 或 `all`)。以 `plugin:` 为前缀的审批 ID 会通过插件审批解析;其他 ID 会先通过 exec 审批解析。 + 内联审批按钮还需要 `channels.telegram.capabilities.inlineButtons` 允许目标表面(`dm`、`group` 或 `all`)。以 `plugin:` 为前缀的审批 ID 会通过插件审批解析;其他 ID 会先通过执行审批解析。 - 参见 [Exec 审批](/zh-CN/tools/exec-approvals)。 + 参见 [执行审批](/zh-CN/tools/exec-approvals)。 ## 错误回复控制 -当智能体遇到投递或提供商错误时,Telegram 可以回复错误文本,也可以抑制该错误。两个配置键控制此行为: +当智能体遇到投递或提供商错误时,Telegram 可以回复错误文本,也可以抑制错误回复。两个配置键控制此行为: -| 键 | 值 | 默认值 | 描述 | -| ----------------------------------- | ----------------- | ------- | ------------------------------------------------------------------------------------------------ | -| `channels.telegram.errorPolicy` | `reply`, `silent` | `reply` | `reply` 会向聊天发送友好的错误消息。`silent` 会完全抑制错误回复。 | -| `channels.telegram.errorCooldownMs` | number (ms) | `60000` | 向同一聊天发送错误回复之间的最短时间。防止故障期间出现错误刷屏。 | +| 键 | 值 | 默认值 | 描述 | +| ----------------------------------- | ----------------- | ------- | ------------------------------------------------------------------------------------------ | +| `channels.telegram.errorPolicy` | `reply`, `silent` | `reply` | `reply` 会向聊天发送友好的错误消息。`silent` 会完全抑制错误回复。 | +| `channels.telegram.errorCooldownMs` | number (ms) | `60000` | 同一聊天两次错误回复之间的最短时间。防止故障期间出现错误刷屏。 | -支持按账号、按群组和按话题覆盖(继承方式与其他 Telegram 配置键相同)。 +支持按账户、按群组和按话题覆盖(继承方式与其他 Telegram 配置键相同)。 ```json5 { @@ -829,56 +833,56 @@ openclaw message poll --channel telegram --target -1001234567890:topic:42 \ ## 故障排除 - + - 如果 `requireMention=false`,Telegram 隐私模式必须允许完整可见性。 - BotFather:`/setprivacy` -> Disable - - 然后移除机器人并重新加入群组 - - 当配置预期接收未提及机器人的群组消息时,`openclaw channels status` 会发出警告。 - - `openclaw channels status --probe` 可以检查明确的数字群组 ID;通配符 `"*"` 无法探测成员资格。 + - 然后将机器人从群组中移除并重新添加 + - 当配置期望未提及的群组消息时,`openclaw channels status` 会发出警告。 + - `openclaw channels status --probe` 可以检查显式数字群组 ID;通配符 `"*"` 无法进行成员资格探测。 - 快速会话测试:`/activation always`。 - - 当 `channels.telegram.groups` 存在时,群组必须列在其中(或包含 `"*"`) + - 当 `channels.telegram.groups` 存在时,群组必须被列出(或包含 `"*"`) - 验证机器人在群组中的成员资格 - - 查看日志:`openclaw logs --follow`,了解跳过原因 + - 查看日志:`openclaw logs --follow`,以了解跳过原因 - + - 授权你的发送者身份(配对和/或数字 `allowFrom`) - 即使群组策略为 `open`,命令授权仍然适用 - - `setMyCommands failed` 且包含 `BOT_COMMANDS_TOO_MUCH` 表示原生命令菜单条目过多;减少插件/skill/自定义命令,或禁用原生菜单 - - `deleteMyCommands` / `setMyCommands` 启动调用和 `sendChatAction` 输入中调用是有界的,并会在请求超时时通过 Telegram 的传输兜底重试一次。持续的网络/fetch 错误通常表示到 `api.telegram.org` 的 DNS/HTTPS 可达性存在问题 + - `setMyCommands failed` 携带 `BOT_COMMANDS_TOO_MUCH` 表示原生命令菜单条目过多;减少插件/skill/自定义命令,或禁用原生命令菜单 + - `deleteMyCommands` / `setMyCommands` 启动调用和 `sendChatAction` 输入状态调用都有边界,并会在请求超时时通过 Telegram 的传输兜底重试一次。持续的网络/fetch 错误通常表示到 `api.telegram.org` 的 DNS/HTTPS 可达性存在问题 - - `getMe returned 401` 是配置的机器人 token 发生 Telegram 认证失败。 - - 在 BotFather 中重新复制或重新生成机器人 token,然后更新默认账号的 `channels.telegram.botToken`、`channels.telegram.tokenFile`、`channels.telegram.accounts..botToken` 或 `TELEGRAM_BOT_TOKEN`。 - - 启动期间的 `deleteWebhook 401 Unauthorized` 也是认证失败;将其当作“没有 webhook 存在”只会把相同的错误 token 失败推迟到后续 API 调用。 + - `getMe returned 401` 是配置的机器人 token 发生 Telegram 身份验证失败。 + - 在 BotFather 中重新复制或重新生成机器人 token,然后更新默认账户的 `channels.telegram.botToken`、`channels.telegram.tokenFile`、`channels.telegram.accounts..botToken` 或 `TELEGRAM_BOT_TOKEN`。 + - 启动期间出现 `deleteWebhook 401 Unauthorized` 也是身份验证失败;将其视为“webhook 不存在”只会把同一个错误 token 失败推迟到后续 API 调用。 - - Node 22+ + 自定义 fetch/代理可能在 AbortSignal 类型不匹配时触发立即中止行为。 - - 一些主机会先把 `api.telegram.org` 解析到 IPv6;损坏的 IPv6 出站连接可能导致 Telegram API 间歇性失败。 - - 如果日志包含 `TypeError: fetch failed` 或 `Network request for 'getUpdates' failed!`,OpenClaw 现在会将这些作为可恢复的网络错误重试。 - - 在轮询启动期间,OpenClaw 会为 grammY 复用启动时成功的 `getMe` 探测,因此运行器不需要在第一次 `getUpdates` 前再执行第二次 `getMe`。 - - 如果 `deleteWebhook` 在轮询启动期间因暂时性网络错误失败,OpenClaw 会继续进入长轮询,而不是再发起一次预轮询控制平面调用。仍处于活动状态的网络钩子会表现为 `getUpdates` 冲突;随后 OpenClaw 会重建 Telegram 传输层并重试网络钩子清理。 - - 如果 Telegram 套接字按较短的固定周期回收,请检查 `channels.telegram.timeoutSeconds` 是否过低;bot 客户端会将低于出站和 `getUpdates` 请求保护值的配置值钳制到保护值以上,但旧版本在该值低于这些保护值时,可能每次轮询或回复都会中止。 - - 如果日志包含 `Polling stall detected`,默认情况下,OpenClaw 会在 120 秒内没有完成长轮询活性检查后重启轮询并重建 Telegram 传输层。 - - 当正在运行的轮询账号在启动宽限期后尚未完成 `getUpdates`、正在运行网络钩子的账号在启动宽限期后尚未完成 `setWebhook`,或最后一次成功的轮询传输活动已过期时,`openclaw channels status --probe` 和 `openclaw doctor` 会发出警告。 - - 仅当长时间运行的 `getUpdates` 调用是健康的,但你的主机仍报告误判的轮询停滞重启时,才增大 `channels.telegram.pollingStallThresholdMs`。持续停滞通常指向主机与 `api.telegram.org` 之间的代理、DNS、IPv6 或 TLS 出站连接问题。 - - Telegram 还会为 Bot API 传输遵循进程代理环境变量,包括 `HTTP_PROXY`、`HTTPS_PROXY`、`ALL_PROXY` 及其小写变体。`NO_PROXY` / `no_proxy` 仍可绕过 `api.telegram.org`。 - - 如果通过 `OPENCLAW_PROXY_URL` 为服务环境配置了 OpenClaw 托管代理,且不存在标准代理环境变量,Telegram 也会将该 URL 用于 Bot API 传输。 - - 在直接出站连接/TLS 不稳定的 VPS 主机上,通过 `channels.telegram.proxy` 路由 Telegram API 调用: + - Node 22+ + 自定义 fetch/proxy 可能会在 AbortSignal 类型不匹配时触发立即中止行为。 + - 某些主机会先把 `api.telegram.org` 解析到 IPv6;损坏的 IPv6 出站可能导致 Telegram API 间歇性失败。 + - 如果日志包含 `TypeError: fetch failed` 或 `Network request for 'getUpdates' failed!`,OpenClaw 现在会把这些作为可恢复的网络错误重试。 + - 在轮询启动期间,OpenClaw 会为 grammY 复用启动时成功的 `getMe` 探测,因此 runner 不需要在第一次 `getUpdates` 之前再执行第二次 `getMe`。 + - 如果 `deleteWebhook` 在轮询启动期间因瞬时网络错误失败,OpenClaw 会继续进入长轮询,而不是再发起一次预轮询控制平面调用。仍处于活动状态的 webhook 会表现为 `getUpdates` 冲突;随后 OpenClaw 会重建 Telegram 传输并重试 webhook 清理。 + - 如果 Telegram 套接字按较短的固定周期回收,请检查是否设置了较低的 `channels.telegram.timeoutSeconds`;bot 客户端会将低于出站和 `getUpdates` 请求保护阈值的配置值钳制到保护范围内,但旧版本在该值低于这些保护阈值时可能会中止每次轮询或回复。 + - 如果日志包含 `Polling stall detected`,OpenClaw 默认会在 120 秒内没有完成的长轮询活性信号后重启轮询并重建 Telegram 传输。 + - `openclaw channels status --probe` 和 `openclaw doctor` 会在运行中的轮询账号在启动宽限期后仍未完成 `getUpdates`、运行中的 webhook 账号在启动宽限期后仍未完成 `setWebhook`,或最后一次成功的轮询传输活动已过期时发出警告。 + - 仅当长时间运行的 `getUpdates` 调用健康,但你的主机仍报告误报的轮询停滞重启时,才增加 `channels.telegram.pollingStallThresholdMs`。持续停滞通常指向主机与 `api.telegram.org` 之间的 proxy、DNS、IPv6 或 TLS 出站问题。 + - Telegram 还会为 Bot API 传输遵循进程 proxy 环境变量,包括 `HTTP_PROXY`、`HTTPS_PROXY`、`ALL_PROXY` 及其小写变体。`NO_PROXY` / `no_proxy` 仍可绕过 `api.telegram.org`。 + - 如果服务环境通过 `OPENCLAW_PROXY_URL` 配置了 OpenClaw 托管 proxy,且不存在标准 proxy 环境变量,Telegram 也会将该 URL 用于 Bot API 传输。 + - 在直接出站/TLS 不稳定的 VPS 主机上,通过 `channels.telegram.proxy` 路由 Telegram API 调用: ```yaml channels: @@ -886,8 +890,8 @@ channels: proxy: socks5://:@proxy-host:1080 ``` - - Node 22+ 默认使用 `autoSelectFamily=true`(WSL2 除外)。Telegram DNS 结果顺序依次遵循 `OPENCLAW_TELEGRAM_DNS_RESULT_ORDER`、`channels.telegram.network.dnsResultOrder`,再到进程默认值,例如 `NODE_OPTIONS=--dns-result-order=ipv4first`;如果都不适用,Node 22+ 会回退到 `ipv4first`。 - - 如果你的主机是 WSL2,或明确在仅 IPv4 行为下表现更好,请强制地址族选择: + - Node 22+ 默认使用 `autoSelectFamily=true`(WSL2 除外)。Telegram DNS 结果顺序依次遵循 `OPENCLAW_TELEGRAM_DNS_RESULT_ORDER`、`channels.telegram.network.dnsResultOrder`,然后是进程默认值,例如 `NODE_OPTIONS=--dns-result-order=ipv4first`;如果都不适用,Node 22+ 会回退到 `ipv4first`。 + - 如果你的主机是 WSL2,或明确使用仅 IPv4 行为效果更好,请强制选择地址族: ```yaml channels: @@ -896,7 +900,7 @@ channels: autoSelectFamily: false ``` - - 默认情况下,Telegram 媒体下载已允许 RFC 2544 基准测试范围解析结果(`198.18.0.0/15`)。如果可信的假 IP 或透明代理在媒体下载期间将 `api.telegram.org` 重写到其他私有/内部/特殊用途地址,你可以选择启用仅限 Telegram 的绕过: + - 默认已允许 Telegram 媒体下载使用 RFC 2544 基准测试范围地址(`198.18.0.0/15`)。如果受信任的 fake-IP 或透明 proxy 在媒体下载期间把 `api.telegram.org` 重写到其他私有/内部/特殊用途地址,你可以选择启用仅限 Telegram 的绕过: ```yaml channels: @@ -905,20 +909,20 @@ channels: dangerouslyAllowPrivateNetwork: true ``` - - 同一选择性启用项也可按账号配置在 + - 同样的选择性启用也可按账号配置在 `channels.telegram.accounts..network.dangerouslyAllowPrivateNetwork`。 - - 如果你的代理将 Telegram 媒体主机解析到 `198.18.x.x`,请先保持危险标志关闭。Telegram 媒体默认已允许 RFC 2544 基准测试范围。 + - 如果你的 proxy 将 Telegram 媒体主机解析到 `198.18.x.x`,先保持危险标志关闭。Telegram 媒体默认已允许 RFC 2544 基准测试范围。 `channels.telegram.network.dangerouslyAllowPrivateNetwork` 会削弱 Telegram - 媒体 SSRF 防护。仅在可信、由运维方控制的代理环境中使用它,例如 Clash、Mihomo 或 Surge 假 IP 路由,并且它们会合成 RFC 2544 基准测试范围之外的私有或特殊用途解析结果。对于普通公共互联网 Telegram 访问,请保持关闭。 + 媒体 SSRF 防护。仅在受信任、由操作方控制的 proxy 环境中使用,例如 Clash、Mihomo 或 Surge fake-IP 路由,并且这些环境会合成 RFC 2544 基准测试范围之外的私有或特殊用途答案。对于正常公共互联网 Telegram 访问,请保持关闭。 - - 环境变量覆盖(临时): + - 环境覆盖(临时): - `OPENCLAW_TELEGRAM_DISABLE_AUTO_SELECT_FAMILY=1` - `OPENCLAW_TELEGRAM_ENABLE_AUTO_SELECT_FAMILY=1` - `OPENCLAW_TELEGRAM_DNS_RESULT_ORDER=ipv4first` - - 验证 DNS 解析结果: + - 验证 DNS 答案: ```bash dig +short api.telegram.org A @@ -934,34 +938,34 @@ dig +short api.telegram.org AAAA 主要参考:[配置参考 - Telegram](/zh-CN/gateway/config-channels#telegram)。 - + -- 启动/认证:`enabled`、`botToken`、`tokenFile`、`accounts.*`(`tokenFile` 必须指向常规文件;符号链接会被拒绝) +- 启动/身份验证:`enabled`、`botToken`、`tokenFile`、`accounts.*`(`tokenFile` 必须指向常规文件;符号链接会被拒绝) - 访问控制:`dmPolicy`、`allowFrom`、`groupPolicy`、`groupAllowFrom`、`groups`、`groups.*.topics.*`、顶层 `bindings[]`(`type: "acp"`) -- 执行审批:`execApprovals`、`accounts.*.execApprovals` +- exec 审批:`execApprovals`、`accounts.*.execApprovals` - 命令/菜单:`commands.native`、`commands.nativeSkills`、`customCommands` - 线程/回复:`replyToMode`、`dm.threadReplies`、`direct.*.threadReplies` - 流式传输:`streaming`(预览)、`streaming.preview.toolProgress`、`blockStreaming` - 格式化/投递:`textChunkLimit`、`chunkMode`、`linkPreview`、`responsePrefix` - 媒体/网络:`mediaMaxMb`、`timeoutSeconds`、`pollingStallThresholdMs`、`retry`、`network.autoSelectFamily`、`network.dangerouslyAllowPrivateNetwork`、`proxy` - 自定义 API 根地址:`apiRoot`(仅 Bot API 根地址;不要包含 `/bot`) -- 网络钩子:`webhookUrl`、`webhookSecret`、`webhookPath`、`webhookHost` +- webhook:`webhookUrl`、`webhookSecret`、`webhookPath`、`webhookHost` - 操作/能力:`capabilities.inlineButtons`、`actions.sendMessage|editMessage|deleteMessage|reactions|sticker` -- 表情回应:`reactionNotifications`、`reactionLevel` +- reactions:`reactionNotifications`、`reactionLevel` - 错误:`errorPolicy`、`errorCooldownMs` -- 写入/历史记录:`configWrites`、`historyLimit`、`dmHistoryLimit`、`dms.*.historyLimit` +- 写入/历史:`configWrites`、`historyLimit`、`dmHistoryLimit`、`dms.*.historyLimit` -多账号优先级:配置两个或更多账号 ID 时,请设置 `channels.telegram.defaultAccount`(或包含 `channels.telegram.accounts.default`),以明确默认路由。否则,OpenClaw 会回退到第一个规范化后的账号 ID,并且 `openclaw doctor` 会发出警告。命名账号会继承 `channels.telegram.allowFrom` / `groupAllowFrom`,但不会继承 `accounts.default.*` 值。 +多账号优先级:配置两个或更多账号 ID 时,设置 `channels.telegram.defaultAccount`(或包含 `channels.telegram.accounts.default`)以明确默认路由。否则 OpenClaw 会回退到第一个规范化账号 ID,并且 `openclaw doctor` 会发出警告。命名账号会继承 `channels.telegram.allowFrom` / `groupAllowFrom`,但不会继承 `accounts.default.*` 值。 -## 相关内容 +## 相关 - 将 Telegram 用户配对到 Gateway 网关。 + 将 Telegram 用户与 Gateway 网关配对。 群组和话题允许列表行为。 diff --git a/docs/zh-CN/concepts/streaming.md b/docs/zh-CN/concepts/streaming.md index c6ac4e82a..27db43a17 100644 --- a/docs/zh-CN/concepts/streaming.md +++ b/docs/zh-CN/concepts/streaming.md @@ -1,29 +1,29 @@ --- read_when: - - 解释流式传输或分块在渠道中的工作方式 + - 说明流式传输或分块在渠道上的工作方式 - 更改分块流式传输或渠道分块行为 - 调试重复/过早的分块回复或渠道预览流式传输 summary: 流式传输 + 分块行为(块回复、渠道预览流式传输、模式映射) title: 流式传输和分块 x-i18n: - generated_at: "2026-05-03T01:35:03Z" + generated_at: "2026-05-03T15:33:28Z" model: gpt-5.5 provider: openai - source_hash: 85f6cb33031a6c818bb709e0ed14d8dd0f8c30a3dd90468a40396b3a515b5e65 + source_hash: 4a62b333123d317cad9a8063a68c5c026fb91b23731a6ccdb97d995d9bb8bdba source_path: concepts/streaming.md workflow: 16 --- OpenClaw 有两个独立的流式传输层: -- **分块流式传输(渠道):** 在助手写入时发出已完成的**块**。这些是普通渠道消息(不是 token 增量)。 -- **预览流式传输(Telegram/Discord/Slack):** 在生成过程中更新临时的**预览消息**。 +- **分块流式传输(渠道):** 在 assistant 写入时发出已完成的 **blocks**。这些是普通渠道消息(不是 token 增量)。 +- **预览流式传输(Telegram/Discord/Slack):** 生成期间更新临时的 **预览消息**。 -目前渠道消息**没有真正的 token 增量流式传输**。预览流式传输基于消息(发送 + 编辑/追加)。 +目前渠道消息没有**真正的 token 增量流式传输**。预览流式传输基于消息(发送 + 编辑/追加)。 ## 分块流式传输(渠道消息) -分块流式传输会在助手输出可用时,以较粗粒度的分块发送。 +分块流式传输会在 assistant 输出可用时,以较粗粒度的分块发送输出。 ``` Model output @@ -44,67 +44,66 @@ Model output **控制项:** - `agents.defaults.blockStreamingDefault`:`"on"`/`"off"`(默认关闭)。 -- 渠道覆盖:`*.blockStreaming`(以及按账号的变体),用于按渠道强制 `"on"`/`"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`)。 +- 渠道硬上限:`*.textChunkLimit`(例如 `channels.whatsapp.textChunkLimit`)。 - 渠道分块模式:`*.chunkMode`(默认 `length`,`newline` 会先按空行(段落边界)拆分,再按长度分块)。 -- Discord 软性上限:`channels.discord.maxLinesPerMessage`(默认 17),用于拆分过高的回复,避免 UI 裁切。 +- Discord 软上限:`channels.discord.maxLinesPerMessage`(默认 17)会拆分过高的回复,避免 UI 裁切。 **边界语义:** -- `text_end`:只要 chunker 发出块就流式传输;在每个 `text_end` 刷新。 -- `message_end`:等待助手消息完成,然后刷新缓冲输出。 +- `text_end`:chunker 一发出就流式发送块;在每个 `text_end` 时刷新。 +- `message_end`:等到 assistant 消息完成后,再刷新缓冲的输出。 如果缓冲文本超过 `maxChars`,`message_end` 仍会使用 chunker,因此它可以在末尾发出多个分块。 ### 使用分块流式传输交付媒体 -`MEDIA:` 指令是普通交付元数据。当分块流式传输提前发送媒体块时,OpenClaw 会记住本轮的该次交付。如果最终助手载荷重复同一个媒体 URL,最终交付会移除重复媒体,而不是再次发送附件。 +`MEDIA:` 指令是普通交付元数据。当分块流式传输提前发送媒体块时,OpenClaw 会记住该回合的交付。如果最终 assistant payload 重复同一媒体 URL,最终交付会移除重复媒体,而不是再次发送附件。 -完全重复的最终载荷会被抑制。如果最终载荷在已流式传输的媒体周围添加了不同文本,OpenClaw 仍会发送新文本,同时保持媒体只交付一次。这可以避免在 Telegram 等渠道中,当智能体在流式传输期间发出 `MEDIA:`,且提供商也在完成回复中包含它时,产生重复语音消息或文件。 +完全重复的最终 payload 会被抑制。如果最终 payload 在已流式传输的媒体周围添加不同文本,OpenClaw 仍会发送新文本,同时保持媒体只交付一次。这可防止在 Telegram 等渠道上出现重复语音消息或文件,例如智能体在流式传输期间发出 `MEDIA:`,而提供商也在完成的回复中包含它时。 ## 分块算法(低/高边界) 分块由 `EmbeddedBlockChunker` 实现: -- **低边界:** 在缓冲区 >= `minChars` 之前不发出(除非强制)。 -- **高边界:** 优先在 `maxChars` 之前拆分;如果强制,则在 `maxChars` 处拆分。 +- **低边界:** 直到缓冲区 >= `minChars` 才发出(除非强制)。 +- **高边界:** 优先在 `maxChars` 前拆分;如果强制,则在 `maxChars` 处拆分。 - **断点偏好:** `paragraph` → `newline` → `sentence` → `whitespace` → 硬断点。 -- **代码围栏:** 绝不在围栏内部拆分;当在 `maxChars` 处强制拆分时,会关闭并重新打开围栏,以保持 Markdown 有效。 +- **代码围栏:** 绝不在围栏内拆分;在 `maxChars` 处强制拆分时,会关闭 + 重新打开围栏,以保持 Markdown 有效。 -`maxChars` 会被限制到渠道的 `textChunkLimit`,因此你无法超过每个渠道的上限。 +`maxChars` 会被限制到渠道的 `textChunkLimit`,因此你不能超过每个渠道的上限。 ## 合并(合并流式块) -启用分块流式传输后,OpenClaw 可以在发送前**合并连续的分块片段**。这可以减少“单行刷屏”,同时仍然提供渐进式输出。 +启用分块流式传输时,OpenClaw 可以在发送前**合并连续的块分片**。这会减少“单行刷屏”,同时仍然提供渐进式输出。 - 合并会等待**空闲间隔**(`idleMs`)后再刷新。 -- 缓冲区受 `maxChars` 限制,超过后会刷新。 -- `minChars` 会阻止很小的片段在积累足够文本前发送(最终刷新始终会发送剩余文本)。 -- 连接符由 `blockStreamingChunk.breakPreference` 推导 - (`paragraph` → `\n\n`,`newline` → `\n`,`sentence` → 空格)。 -- 可通过 `*.blockStreamingCoalesce` 提供渠道覆盖(包括按账号配置)。 -- 除非被覆盖,否则 Signal/Slack/Discord 的默认合并 `minChars` 会提升到 1500。 +- 缓冲区受 `maxChars` 限制,超过时会刷新。 +- `minChars` 会阻止过小片段发送,直到累积足够文本(最终刷新始终发送剩余文本)。 +- 连接符源自 `blockStreamingChunk.breakPreference`(`paragraph` → `\n\n`,`newline` → `\n`,`sentence` → 空格)。 +- 可通过 `*.blockStreamingCoalesce` 设置渠道覆盖(包括按账户配置)。 +- 除非覆盖,Signal/Slack/Discord 的默认合并 `minChars` 会提升到 1500。 ## 分块之间的拟人化节奏 -启用分块流式传输后,你可以在分块回复之间添加**随机暂停**(第一个分块之后)。这会让多气泡回复感觉更自然。 +启用分块流式传输时,你可以在分块回复之间(第一个块之后)添加**随机暂停**。这会让多气泡回复感觉更自然。 -- 配置:`agents.defaults.humanDelay`(可通过 `agents.list[].humanDelay` 按智能体覆盖)。 +- 配置:`agents.defaults.humanDelay`(通过 `agents.list[].humanDelay` 按智能体覆盖)。 - 模式:`off`(默认)、`natural`(800–2500ms)、`custom`(`minMs`/`maxMs`)。 -- 仅应用于**分块回复**,不应用于最终回复或工具摘要。 +- 仅适用于**分块回复**,不适用于最终回复或工具摘要。 ## “流式传输分块或全部内容” -这对应于: +这映射到: - **流式传输分块:** `blockStreamingDefault: "on"` + `blockStreamingBreak: "text_end"`(边生成边发出)。非 Telegram 渠道还需要 `*.blockStreaming: true`。 -- **在末尾流式传输全部内容:** `blockStreamingBreak: "message_end"`(刷新一次;如果很长,可能有多个分块)。 +- **在末尾流式传输全部内容:** `blockStreamingBreak: "message_end"`(刷新一次,如果很长可能有多个分块)。 - **无分块流式传输:** `blockStreamingDefault: "off"`(仅最终回复)。 -**渠道注意事项:** 除非显式将 `*.blockStreaming` 设置为 `true`,否则分块流式传输为**关闭**。渠道可以在没有分块回复的情况下流式传输实时预览(`channels..streaming`)。 +**渠道说明:** 除非显式将 `*.blockStreaming` 设置为 `true`,否则分块流式传输**关闭**。渠道可以流式传输实时预览(`channels..streaming`),而不发送分块回复。 配置位置提醒:`blockStreaming*` 默认值位于 `agents.defaults` 下,而不是根配置。 @@ -115,27 +114,27 @@ Model output 模式: - `off`:禁用预览流式传输。 -- `partial`:单个预览,会替换为最新文本。 +- `partial`:单个预览,会被最新文本替换。 - `block`:以分块/追加步骤更新预览。 - `progress`:生成期间显示进度/Status 预览,完成时给出最终答案。 ### 渠道映射 -| 渠道 | `off` | `partial` | `block` | `progress` | +| 渠道 | `off` | `partial` | `block` | `progress` | | ---------- | ----- | --------- | ------- | ----------------- | -| Telegram | ✅ | ✅ | ✅ | 映射到 `partial` | -| Discord | ✅ | ✅ | ✅ | 映射到 `partial` | -| Slack | ✅ | ✅ | ✅ | ✅ | -| Mattermost | ✅ | ✅ | ✅ | ✅ | +| Telegram | ✅ | ✅ | ✅ | 映射到 `partial` | +| Discord | ✅ | ✅ | ✅ | 映射到 `partial` | +| Slack | ✅ | ✅ | ✅ | ✅ | +| Mattermost | ✅ | ✅ | ✅ | ✅ | -Slack 专用: +仅 Slack: - 当 `channels.slack.streaming.mode="partial"` 时,`channels.slack.streaming.nativeTransport` 会切换 Slack 原生流式传输 API 调用(默认:`true`)。 -- Slack 原生流式传输和 Slack 助手线程 Status 需要一个回复线程目标。顶级私信不会显示那种线程样式预览,但仍可以使用 Slack 草稿预览帖子和编辑。 +- Slack 原生流式传输和 Slack assistant 线程 Status 需要回复线程目标。顶层私信不会显示这种线程样式预览,但它们仍可使用 Slack 草稿预览帖子和编辑。 旧键迁移: -- Telegram:旧版 `streamMode` 以及标量/布尔 `streaming` 值会被检测到,并由 Doctor/配置兼容路径迁移到 `streaming.mode`。 +- Telegram:旧版 `streamMode` 和标量/布尔 `streaming` 值会被 Doctor/配置兼容路径检测并迁移到 `streaming.mode`。 - Discord:`streamMode` + 布尔 `streaming` 会自动迁移到 `streaming` 枚举。 - Slack:`streamMode` 会自动迁移到 `streaming.mode`;布尔 `streaming` 会自动迁移到 `streaming.mode` 加 `streaming.nativeTransport`;旧版 `nativeStreaming` 会自动迁移到 `streaming.nativeTransport`。 @@ -143,8 +142,8 @@ Slack 专用: Telegram: -- 在私信和群组/话题中使用 `sendMessage` + `editMessageText` 进行预览更新。 -- 当预览已可见约一分钟时,会发送一条新的最终消息,而不是原地编辑,然后清理预览,使 Telegram 的时间戳反映回复完成时间。 +- 在私信和群组/话题中使用 `sendMessage` + `editMessageText` 预览更新。 +- 当预览已可见约一分钟时,会发送一条新的最终消息,而不是就地编辑,然后清理预览,使 Telegram 的时间戳反映回复完成时间。 - 当 Telegram 分块流式传输被显式启用时,会跳过预览流式传输(避免双重流式传输)。 - `/reasoning stream` 可以将推理写入预览。 @@ -153,39 +152,40 @@ Discord: - 使用发送 + 编辑预览消息。 - `block` 模式使用草稿分块(`draftChunk`)。 - 当 Discord 分块流式传输被显式启用时,会跳过预览流式传输。 -- 最终媒体、错误和显式回复载荷会取消待处理预览,而不刷新新的草稿,然后使用正常交付。 +- 最终媒体、错误和显式回复 payload 会取消待处理预览,而不刷新新的草稿,然后使用正常交付。 Slack: - 可用时,`partial` 可以使用 Slack 原生流式传输(`chat.startStream`/`append`/`stop`)。 -- `block` 使用追加式草稿预览。 +- `block` 使用追加样式的草稿预览。 - `progress` 使用 Status 预览文本,然后给出最终答案。 -- 没有回复线程的顶级私信会使用草稿预览帖子和编辑,而不是 Slack 原生流式传输。 -- 原生和草稿预览流式传输会抑制本轮的分块回复,因此 Slack 回复只通过一条交付路径进行流式传输。 -- 最终媒体/错误载荷和进度最终消息不会创建一次性草稿消息;只有可以编辑预览的文本/块最终消息会刷新待处理草稿文本。 +- 没有回复线程的顶层私信会使用草稿预览帖子和编辑,而不是 Slack 原生流式传输。 +- 原生和草稿预览流式传输会抑制该回合的分块回复,因此 Slack 回复只通过一条交付路径流式传输。 +- 最终媒体/错误 payload 和进度最终内容不会创建一次性草稿消息;只有能编辑预览的文本/块最终内容才会刷新待处理草稿文本。 Mattermost: -- 将思考、工具活动和部分回复文本流式传输到单个草稿预览帖子中,并在最终答案可安全发送时原地最终化。 -- 如果预览帖子已删除或在最终化时不可用,则回退为发送新的最终帖子。 -- 最终媒体/错误载荷会在正常交付前取消待处理预览更新,而不是刷新临时预览帖子。 +- 将思考、工具活动和部分回复文本流式传输到单个草稿预览帖子中,并在最终答案可安全发送时就地完成。 +- 如果预览帖子在完成时已被删除或无法使用,则回退为发送新的最终帖子。 +- 最终媒体/错误 payload 会先取消待处理预览更新,再正常交付,而不是刷新临时预览帖子。 Matrix: -- 当最终文本可以复用预览事件时,草稿预览会原地最终化。 -- 仅媒体、错误和回复目标不匹配的最终消息会在正常交付前取消待处理预览更新;已可见的过期预览会被撤回。 +- 当最终文本可以复用预览事件时,草稿预览会就地完成。 +- 仅媒体、错误和回复目标不匹配的最终内容会先取消待处理预览更新,再正常交付;已可见的过时预览会被撤回。 ### 工具进度预览更新 -预览流式传输还可以包含**工具进度**更新,即像“搜索网页”“读取文件”或“调用工具”这样的短 Status 行;它们会在工具运行期间、最终回复之前出现在同一条预览消息中。这让多步骤工具轮次在第一条思考预览和最终答案之间保持视觉上的活跃,而不是沉默。 +预览流式传输还可以包含**工具进度**更新,即“正在搜索网络”、“正在读取文件”或“正在调用工具”这类短 Status 行。工具运行时,它们会显示在同一条预览消息中,早于最终回复。这能让多步骤工具回合在第一个思考预览和最终答案之间保持视觉上的进行状态,而不是沉默。 支持的表面: -- 当预览流式传输处于活动状态时,**Discord**、**Slack**、**Telegram** 和 **Matrix** 默认会将工具进度流式传输到实时预览编辑中。 +- **Discord**、**Slack**、**Telegram** 和 **Matrix** 在预览流式传输处于活动状态时,默认会将工具进度流式传输到实时预览编辑中。 - Telegram 自 `v2026.4.22` 起已发布启用工具进度预览更新的行为;保持启用可保留该已发布行为。 -- **Mattermost** 已经将工具活动折叠进它的单个草稿预览帖子(见上文)。 -- 工具进度编辑遵循活动的预览流式传输模式;当预览流式传输为 `off`,或分块流式传输已接管消息时,会跳过它们。在 Telegram 上,`streaming.mode: "off"` 表示仅最终回复:通用进度闲聊也会被抑制,而不是作为独立的“Working...”消息交付,但审批提示、媒体载荷和错误仍会正常路由。 -- 若要保留预览流式传输但隐藏工具进度行,请将该渠道的 `streaming.preview.toolProgress` 设置为 `false`。若要完全禁用预览编辑,请将 `streaming.mode` 设置为 `off`。 +- **Mattermost** 已将工具活动合并到它的单个草稿预览帖子中(见上文)。 +- 工具进度编辑遵循活动的预览流式传输模式;当预览流式传输为 `off`,或分块流式传输已接管消息时会跳过。在 Telegram 上,`streaming.mode: "off"` 表示仅最终回复:通用进度闲聊也会被抑制,而不是作为独立的“Working...”消息交付;同时审批提示、媒体 payload 和错误仍会正常路由。 +- 要保留预览流式传输但隐藏工具进度行,请为该渠道将 `streaming.preview.toolProgress` 设置为 `false`。要完全禁用预览编辑,请将 `streaming.mode` 设置为 `off`。 +- Telegram 所选引用回复是一个例外:当 `replyToMode` 不是 `"off"` 且存在所选引用文本时,OpenClaw 会跳过该回合的答案预览流,因此工具进度预览行无法渲染。没有所选引用文本的当前消息回复仍会保留预览流式传输。详见 [Telegram 渠道文档](/zh-CN/channels/telegram)。 示例: @@ -204,8 +204,8 @@ Matrix: } ``` -## 相关 +## 相关内容 - [消息](/zh-CN/concepts/messages) — 消息生命周期和交付 - [重试](/zh-CN/concepts/retry) — 交付失败时的重试行为 -- [渠道](/zh-CN/channels) — 按渠道的流式传输支持 +- [渠道](/zh-CN/channels) — 各渠道流式传输支持