Telegram (Bot API)
状态:生产就绪,通过 grammY 支持 Bot 私信和群组。默认使用长轮询模式;也可选用 webhook 模式。
- 配对 — Telegram 的默认私信策略为配对模式。
- 频道故障排查 — 跨频道诊断与修复指南。
- Gateway 配置 — 完整的频道配置模式与示例。
快速设置
步骤 1:在 BotFather 中创建 Bot Token
打开 Telegram 并与 **@BotFather** 对话(确认用户名正好是 `@BotFather`)。
运行 `/newbot`,按提示操作并保存 Token。
步骤 2:配置 Token 和私信策略
{
channels: {
telegram: {
enabled: true,
botToken: "123:abc",
dmPolicy: "pairing",
groups: { "*": { requireMention: true } },
},
},
}
环境变量备选:`TELEGRAM_BOT_TOKEN=...`(仅默认账户)。
Telegram **不**使用 `openclaw channels login telegram`;在配置/环境变量中设置 Token,然后启动 Gateway。
步骤 3:启动 Gateway 并批准首次私信
openclaw gateway
openclaw pairing list telegram
openclaw pairing approve telegram <CODE>
配对码在 1 小时后过期。
步骤 4:将 Bot 添加到群组
将 Bot 添加到你的群组,然后设置 `channels.telegram.groups` 和 `groupPolicy` 以匹配你的访问模型。
注意: Token 解析顺序具有账户感知能力。实际上配置值优先于环境变量备选,且
TELEGRAM_BOT_TOKEN仅适用于默认账户。
Telegram 端设置
隐私模式与群组可见性
Telegram Bot 默认启用 **Privacy Mode**,限制它们能接收的群组消息。
如果 Bot 需要看到所有群组消息,可以:
- 通过 `/setprivacy` 禁用隐私模式,或
- 将 Bot 设为群组管理员。
切换隐私模式后,需在每个群组中移除并重新添加 Bot,Telegram 才会应用更改。
群组权限
管理员状态在 Telegram 群组设置中控制。
管理员 Bot 接收所有群组消息,适用于始终在线的群组行为。
BotFather 实用开关
- `/setjoingroups` 控制是否允许被添加到群组
- `/setprivacy` 控制群组可见性行为
访问控制与激活
私信策略
`channels.telegram.dmPolicy` 控制私信访问:
- `pairing`(默认)
- `allowlist`(需要 `allowFrom` 中至少有一个发送者 ID)
- `open`(需要 `allowFrom` 包含 `"*"`)
- `disabled`
`channels.telegram.allowFrom` 接受数字 Telegram 用户 ID。`telegram:` / `tg:` 前缀会被接受并规范化。
`dmPolicy: "allowlist"` 且 `allowFrom` 为空时会阻止所有私信,并被配置验证拒绝。
引导向导接受 `@username` 输入并将其解析为数字 ID。
如果你升级后配置中包含 `@username` 白名单条目,运行 `openclaw doctor --fix` 来解析(尽力而为;需要 Telegram Bot Token)。
如果你之前依赖配对存储白名单文件,`openclaw doctor --fix` 可以在白名单流程中恢复条目到 `channels.telegram.allowFrom`(例如当 `dmPolicy: "allowlist"` 没有显式 ID 时)。
对于单用户 Bot,建议使用 `dmPolicy: "allowlist"` 并在 `allowFrom` 中明确填入数字 ID,使访问策略持久保存在配置中(而非依赖之前的配对审批)。
### 查找你的 Telegram 用户 ID
更安全的方式(无需第三方 Bot):
1. 向你的 Bot 发私信。
2. 运行 `openclaw logs --follow`。
3. 读取 `from.id`。
官方 Bot API 方法:
curl "https://api.telegram.org/bot<bot_token>/getUpdates"
第三方方法(隐私性较低):`@userinfobot` 或 `@getidsbot`。
群组策略和白名单
两个控制共同生效:
1. **允许哪些群组**(`channels.telegram.groups`)
- 无 `groups` 配置时:
- `groupPolicy: "open"`:任何群组都可通过群组 ID 检查
- `groupPolicy: "allowlist"`(默认):群组被阻止直到你添加 `groups` 条目(或 `"*"`)
- 已配置 `groups`:作为白名单(显式 ID 或 `"*"`)
2. **群组中允许哪些发送者**(`channels.telegram.groupPolicy`)
- `open`
- `allowlist`(默认)
- `disabled`
`groupAllowFrom` 用于群组发送者过滤。如果未设置,Telegram 会回退到 `allowFrom`。
`groupAllowFrom` 条目应为数字 Telegram 用户 ID(`telegram:` / `tg:` 前缀会被规范化)。
不要将 Telegram 群组或超级群组聊天 ID 放入 `groupAllowFrom`。负数聊天 ID 属于 `channels.telegram.groups`。
非数字条目在发送者授权时会被忽略。
安全边界(`2026.2.25+`):群组发送者认证**不**继承私信配对存储审批。
配对仅限私信。对于群组,请设置 `groupAllowFrom` 或按群组/按话题的 `allowFrom`。
运行时注意:如果 `channels.telegram` 完全缺失,运行时默认为安全关闭的 `groupPolicy="allowlist"`,除非 `channels.defaults.groupPolicy` 已显式设置。
示例:允许特定群组中的任何成员:
{
channels: {
telegram: {
groups: {
"-1001234567890": {
groupPolicy: "open",
requireMention: false,
},
},
},
},
}
示例:仅允许特定群组中的特定用户:
{
channels: {
telegram: {
groups: {
"-1001234567890": {
requireMention: true,
allowFrom: ["8734062810", "745123456"],
},
},
},
},
}
> **警告:**
常见错误:
groupAllowFrom不是 Telegram 群组白名单。- 将负数 Telegram 群组或超级群组聊天 ID(如 `-1001234567890`)放入 `channels.telegram.groups`。 - 将 Telegram 用户 ID(如 `8734062810`)放入 `groupAllowFrom`,用于限制允许的群组中谁可以触发 Bot。 - 仅当你希望允许的群组中任何成员都能与 Bot 对话时才使用 `groupAllowFrom: ["*"]`。
提及行为
群组回复默认需要提及。
提及可来自:
- 原生 `@botusername` 提及,或
- 提及模式:
- `agents.list[].groupChat.mentionPatterns`
- `messages.groupChat.mentionPatterns`
会话级命令开关:
- `/activation always`
- `/activation mention`
这些仅更新会话状态,如需持久化请使用配置。
持久化配置示例:
{
channels: {
telegram: {
groups: {
"*": { requireMention: false },
},
},
},
}
获取群组聊天 ID:
- 将群组消息转发给 `@userinfobot` / `@getidsbot`
- 或从 `openclaw logs --follow` 中读取 `chat.id`
- 或检查 Bot API `getUpdates`
运行时行为
- Telegram 由 Gateway 进程拥有。
- 路由是确定性的:Telegram 入站消息回复到 Telegram(模型不选择频道)。
- 入站消息规范化为共享频道信封,带回复元数据和媒体占位符。
- 群组会话按群组 ID 隔离。论坛话题追加
:topic:<threadId>以保持话题隔离。 - 私信消息可以携带
message_thread_id;OpenClaw 使用线程感知的会话键路由它们,并在回复中保留线程 ID。 - 长轮询使用 grammY runner,按聊天/线程顺序处理。总体 runner sink 并发使用
agents.defaults.maxConcurrent。 - Telegram Bot API 不支持已读回执(
sendReadReceipts不适用)。
功能参考
实时流式预览(消息编辑)
OpenClaw 可以实时流式传输部分回复:
- 私信:预览消息 + `editMessageText`
- 群组/话题:预览消息 + `editMessageText`
要求:
- `channels.telegram.streaming` 为 `off | partial | block | progress`(默认:`partial`)
- `progress` 在 Telegram 上映射为 `partial`(与跨频道命名兼容)
- 旧版 `channels.telegram.streamMode` 和布尔值 `streaming` 会自动映射
纯文本回复:
- 私信:OpenClaw 保持同一预览消息并就地执行最终编辑(不发送第二条消息)
- 群组/话题:OpenClaw 保持同一预览消息并就地执行最终编辑(不发送第二条消息)
复杂回复(例如媒体 payload)时,OpenClaw 回退到正常最终投递,然后清理预览消息。
预览流式传输与分块流式传输独立。当 Telegram 显式启用分块流式传输时,OpenClaw 跳过预览流式传输以避免重复。
如果原生草稿传输不可用/被拒绝,OpenClaw 自动回退到 `sendMessage` + `editMessageText`。
Telegram 专属推理流:
- `/reasoning stream` 在生成时将推理发送到实时预览
- 最终答案不含推理文本
格式与 HTML 回退
出站文本使用 Telegram `parse_mode: "HTML"`。
- Markdown 风格的文本渲染为 Telegram 安全的 HTML。
- 原始模型 HTML 会被转义以减少 Telegram 解析失败。
- 如果 Telegram 拒绝解析后的 HTML,OpenClaw 以纯文本重试。
链接预览默认启用,可通过 `channels.telegram.linkPreview: false` 禁用。
原生命令和自定义命令
Telegram 命令菜单注册在启动时通过 `setMyCommands` 处理。
原生命令默认值:
- `commands.native: "auto"` 为 Telegram 启用原生命令
添加自定义命令菜单条目:
{
channels: {
telegram: {
customCommands: [
{ command: "backup", description: "Git backup" },
{ command: "generate", description: "Create an image" },
],
},
},
}
规则:
- 名称被规范化(去除前导 `/`,转为小写)
- 有效模式:`a-z`、`0-9`、`_`,长度 `1..32`
- 自定义命令不能覆盖原生命令
- 冲突/重复会被跳过并记录
说明:
- 自定义命令仅是菜单条目;它们不会自动实现行为
- 插件/技能命令即使未在 Telegram 菜单中显示也可以工作
如果禁用原生命令,内置命令会被移除。自定义/插件命令如已配置仍可能注册。
常见设置失败:
- `setMyCommands failed` 加 `BOT_COMMANDS_TOO_MUCH` 表示 Telegram 菜单在精简后仍溢出;减少插件/技能/自定义命令或禁用 `channels.telegram.commands.native`。
- `setMyCommands failed` 加网络/fetch 错误通常表示到 `api.telegram.org` 的出站 DNS/HTTPS 被阻止。
内联按钮
配置内联键盘范围:
{
channels: {
telegram: {
capabilities: {
inlineButtons: "allowlist",
},
},
},
}
范围:
- `off`
- `dm`
- `group`
- `all`
- `allowlist`(默认)
旧版 `capabilities: ["inlineButtons"]` 映射为 `inlineButtons: "all"`。
回复线程标签
Telegram 支持生成输出中的显式回复线程标签:
- `[[reply_to_current]]` 回复触发消息
- `[[reply_to:<id>]]` 回复特定 Telegram 消息 ID
`channels.telegram.replyToMode` 控制处理:
- `off`(默认)
- `first`
- `all`
注意:`off` 禁用隐式回复线程。显式的 `[[reply_to_*]]` 标签仍然有效。
论坛话题和线程行为
论坛超级群组:
- 话题会话键追加 `:topic:<threadId>`
- 回复和输入指示定位话题线程
**按话题的 Agent 路由**:每个话题可通过在话题配置中设置 `agentId` 路由到不同的 Agent。
**持久化 ACP 话题绑定**:论坛话题可以通过顶层类型化 ACP 绑定固定 ACP harness 会话。
音频、视频和贴纸
Telegram 区分语音备忘录和音频文件、视频文件和视频备忘录。
启用贴纸操作:
{
channels: {
telegram: {
actions: {
sticker: true,
},
},
},
}
表情回应通知
配置:
- `channels.telegram.reactionNotifications`:`off | own | all`(默认:`own`)
- `channels.telegram.reactionLevel`:`off | ack | minimal | extensive`(默认:`minimal`)
长轮询 vs webhook
默认:长轮询。
Webhook 模式:
- 设置 `channels.telegram.webhookUrl`
- 设置 `channels.telegram.webhookSecret`(设置 webhook URL 时必需)
- 可选 `channels.telegram.webhookPath`(默认 `/telegram-webhook`)
- 可选 `channels.telegram.webhookHost`(默认 `127.0.0.1`)
- 可选 `channels.telegram.webhookPort`(默认 `8787`)
故障排查
Bot 不回复非提及的群组消息
- 如果 `requireMention=false`,Telegram 隐私模式必须允许完全可见性。
- BotFather:`/setprivacy` -> Disable
- 然后移除并重新添加 Bot 到群组
Bot 完全看不到群组消息
- 当 `channels.telegram.groups` 存在时,群组必须被列出(或包含 `"*"`)
- 验证 Bot 在群组中的成员身份
- 查看日志:`openclaw logs --follow` 了解跳过原因
轮询或网络不稳定
- 在 VPS 主机上如果直接出站/TLS 不稳定,通过 `channels.telegram.proxy` 路由 Telegram API 调用:
channels:
telegram:
proxy: socks5://<user>:<password>@proxy-host:1080
更多帮助:频道故障排查。
Telegram 配置参考指引
主要参考:
-
channels.telegram.enabled:启用/禁用频道启动。 -
channels.telegram.botToken:Bot Token(BotFather)。 -
channels.telegram.dmPolicy:pairing | allowlist | open | disabled(默认:pairing)。 -
channels.telegram.allowFrom:私信白名单(数字 Telegram 用户 ID)。 -
channels.telegram.groupPolicy:open | allowlist | disabled(默认:allowlist)。 -
channels.telegram.groupAllowFrom:群组发送者白名单(数字 Telegram 用户 ID)。 -
channels.telegram.groups:按群组默认值 + 白名单(使用"*"作为全局默认值)。