跳转到内容

Telegram

状态:生产就绪,支持机器人私信(DM)+ 群组(通过 grammY)。默认使用长轮询(Long-polling);可选 Webhook。

  1. 使用 @BotFather 创建一个机器人并复制令牌(token)。
  2. 设置令牌:
    • 环境变量:TELEGRAM_BOT_TOKEN=...
    • 或配置:channels.telegram.botToken: "..."
    • 如果两者都设置了,配置优先(环境变量回退仅适用于默认账户)。
  3. 启动网关。
  4. 私信访问默认为配对模式;在首次联系时批准配对代码。

最小配置:

{
channels: {
telegram: {
enabled: true,
botToken: "123:abc",
dmPolicy: "pairing"
}
}
}
  • 一个由网关拥有的 Telegram Bot API 频道。
  • 确定性路由:回复会返回到 Telegram;模型从不选择频道。
  • 私信共享智能体的主会话;群组保持隔离 (agent:<agentId>:telegram:group:<chatId>)。
  1. 打开 Telegram 并与 @BotFather 聊天。
  2. 运行 /newbot,然后按照提示操作(名称 + 以 bot 结尾的用户名)。
  3. 复制令牌并妥善保存。

可选的 BotFather 设置:

  • /setjoingroups — 允许/拒绝将机器人添加到群组。
  • /setprivacy — 控制机器人是否可以看到所有群组消息。

2) 配置令牌(环境变量或配置)

Section titled “2) 配置令牌(环境变量或配置)”

示例:

{
channels: {
telegram: {
enabled: true,
botToken: "123:abc",
dmPolicy: "pairing",
groups: { "*": { requireMention: true } }
}
}
}

环境变量选项:TELEGRAM_BOT_TOKEN=...(适用于默认账户)。 如果同时设置了环境变量和配置,配置优先。

多账户支持:使用 channels.telegram.accounts,配置每个账户的令牌和可选的 name。参见 gateway/configuration 了解共享模式。

  1. 启动网关。当令牌解析后(配置优先,环境变量回退),Telegram 启动。
  2. 私信访问默认为配对。当首次联系机器人时批准代码。
  3. 对于群组:添加机器人,决定隐私/管理员行为(见下文),然后设置 channels.telegram.groups 来控制提及门槛 + 白名单。

令牌 + 隐私 + 权限(Telegram 端)

Section titled “令牌 + 隐私 + 权限(Telegram 端)”
  • /newbot 创建机器人并返回令牌(保密)。
  • 如果令牌泄露,通过 @BotFather 撤销/重新生成它并更新你的配置。

Telegram 机器人默认为 隐私模式 (Privacy Mode),这限制了它们接收哪些群组消息。 如果你的机器人必须查看 所有 群组消息,你有两个选择:

  • 使用 /setprivacy 禁用隐私模式
  • 将机器人添加为群组 管理员(管理员机器人接收所有消息)。

注意: 当你切换隐私模式时,Telegram 要求将机器人从每个群组移除并重新添加,更改才会生效。

管理员状态在群组内设置(Telegram UI)。管理员机器人总是接收所有群组消息,所以如果你需要完全可见性,请使用管理员。

  • 入站消息被标准化为带有回复上下文和媒体占位符的共享频道信封。
  • 群组回复默认需要提及(原生 @mention 或 agents.list[].groupChat.mentionPatterns / messages.groupChat.mentionPatterns)。
  • 多智能体覆盖:在 agents.list[].groupChat.mentionPatterns 上设置每个智能体的模式。
  • 回复总是路由回同一个 Telegram 聊天。
  • 长轮询使用带有每个聊天排序的 grammY runner;总并发数由 agents.defaults.maxConcurrent 限制。
  • Telegram Bot API 不支持已读回执;没有 sendReadReceipts 选项。
  • 出站 Telegram 文本使用 parse_mode: "HTML"(Telegram 支持的标签子集)。
  • Markdown 风格的输入被渲染为 Telegram 安全的 HTML(粗体/斜体/删除线/代码/链接);块元素被扁平化为带有换行符/项目符号的文本。
  • 来自模型的原始 HTML 被转义以避免 Telegram 解析错误。
  • 如果 Telegram 拒绝 HTML 有效负载,OpenClaw 会作为纯文本重试相同的消息。

OpenClaw 在启动时向 Telegram 的机器人菜单注册原生命令(如 /status, /reset, /model)。 你可以通过配置向菜单添加自定义命令:

{
channels: {
telegram: {
customCommands: [
{ command: "backup", description: "Git backup" },
{ command: "generate", description: "Create an image" }
]
}
}
}
  • 日志中的 setMyCommands failed 通常意味着到 api.telegram.org 的出站 HTTPS/DNS 被阻止。
  • 如果你看到 sendMessagesendChatAction 失败,请检查 IPv6 路由和 DNS。

更多帮助:频道故障排除

注意:

  • 自定义命令 仅是菜单条目;OpenClaw 不会实现它们,除非你在其他地方处理它们。
  • 命令名称被标准化(去除前导 /,小写)并且必须匹配 a-z, 0-9, _(1–32 个字符)。
  • 自定义命令 不能覆盖原生命令。冲突会被忽略并记录。
  • 如果禁用了 commands.native,则仅注册自定义命令(如果无则清除)。
  • 出站文本分块限制为 channels.telegram.textChunkLimit(默认 4000)。
  • 可选换行符分块:设置 channels.telegram.chunkMode="newline" 以在长度分块之前按空行(段落边界)拆分。
  • 媒体下载/上传限制为 channels.telegram.mediaMaxMb(默认 5)。
  • Telegram Bot API 请求在 channels.telegram.timeoutSeconds 后超时(默认通过 grammY 为 500)。设置较低的值以避免长时间挂起。
  • 群组历史上下文使用 channels.telegram.historyLimit(或 channels.telegram.accounts.*.historyLimit),回退到 messages.groupChat.historyLimit。设置为 0 以禁用(默认 50)。
  • 私信历史可以通过 channels.telegram.dmHistoryLimit(用户轮次)进行限制。每个用户的覆盖:channels.telegram.dms["<user_id>"].historyLimit

默认情况下,机器人仅响应群组中的提及(@botnameagents.list[].groupChat.mentionPatterns 中的模式)。要更改此行为:

{
channels: {
telegram: {
groups: {
"-1001234567890": { requireMention: false } // 在此群组中总是响应
}
}
}
}

重要: 设置 channels.telegram.groups 会创建一个 白名单 - 只有列出的群组(或 "*")会被接受。 论坛主题继承其父群组配置(allowFrom, requireMention, skills, prompts),除非你在 channels.telegram.groups.<groupId>.topics.<topicId> 下添加每个主题的覆盖。

允许所有群组总是响应:

{
channels: {
telegram: {
groups: {
"*": { requireMention: false } // 所有群组,总是响应
}
}
}
}

保持所有群组仅提及(默认行为):

{
channels: {
telegram: {
groups: {
"*": { requireMention: true } // 或者完全省略 groups
}
}
}
}

在群组中发送:

  • /activation always - 响应所有消息
  • /activation mention - 需要提及(默认)

注意: 命令仅更新会话状态。要在重启后保持持久行为,请使用配置。

将群组中的任何消息转发给 Telegram 上的 @userinfobot@getidsbot 以查看聊天 ID(类似 -1001234567890 的负数)。

提示: 对于你自己的用户 ID,私信机器人,它将回复你的用户 ID(配对消息),或者一旦启用命令,使用 /whoami

隐私说明: @userinfobot 是第三方机器人。如果你更喜欢,将机器人添加到群组,发送消息,并使用 openclaw logs --follow 读取 chat.id,或使用 Bot API getUpdates

默认情况下,Telegram 允许写入由频道事件或 /config set|unset 触发的配置更新。

这发生在:

  • 群组升级为超级群组且 Telegram 发出 migrate_to_chat_id(聊天 ID 更改)时。OpenClaw 可以自动迁移 channels.telegram.groups
  • 你在 Telegram 聊天中运行 /config set/config unset(需要 commands.config: true)。

禁用方法:

{
channels: { telegram: { configWrites: false } }
}

Telegram 论坛主题在每条消息中包含一个 message_thread_id。OpenClaw:

  • :topic:<threadId> 附加到 Telegram 群组会话键,以便每个主题都是隔离的。
  • 发送带有 message_thread_id 的输入指示和回复,以便响应保留在主题中。
  • 常规主题(线程 ID 1)很特殊:消息发送省略 message_thread_id(Telegram 拒绝它),但输入指示仍包含它。
  • 在模板上下文中公开 MessageThreadId + IsForum 以用于路由/模板化。
  • 主题特定配置可在 channels.telegram.groups.<chatId>.topics.<threadId> 下获得(skills, allowlists, auto-reply, system prompts, disable)。
  • 主题配置继承群组设置(requireMention, allowlists, skills, prompts, enabled),除非每个主题被覆盖。

私聊在某些边缘情况下可能包含 message_thread_id。OpenClaw 保持 DM 会话键不变,但在存在时仍使用线程 ID 进行回复/草稿流式传输。

Telegram 支持带有回调按钮的内联键盘。

{
"channels": {
"telegram": {
"capabilities": {
"inlineButtons": "allowlist"
}
}
}
}

对于每个账户的配置:

{
"channels": {
"telegram": {
"accounts": {
"main": {
"capabilities": {
"inlineButtons": "allowlist"
}
}
}
}
}
}

范围:

  • off — 禁用内联按钮
  • dm — 仅私信(群组目标被阻止)
  • group — 仅群组(私信目标被阻止)
  • all — 私信 + 群组
  • allowlist — 私信 + 群组,但仅限 allowFrom/groupAllowFrom 允许的发送者(与控制命令规则相同)

默认值:allowlist。 旧版:capabilities: ["inlineButtons"] = inlineButtons: "all"

使用带有 buttons 参数的 message 工具:

{
"action": "send",
"channel": "telegram",
"to": "123456789",
"message": "Choose an option:",
"buttons": [
[
{"text": "Yes", "callback_data": "yes"},
{"text": "No", "callback_data": "no"}
],
[
{"text": "Cancel", "callback_data": "cancel"}
]
]
}

当用户点击按钮时,回调数据作为具有以下格式的消息发送回智能体: callback_data: value

Telegram 功能可以在两个级别配置(如上所示的对象形式;仍支持旧版字符串数组):

  • channels.telegram.capabilities:除非被覆盖,否则应用于所有 Telegram 账户的全局默认功能配置。
  • channels.telegram.accounts.<account>.capabilities:每个账户的功能,覆盖该特定账户的全局默认值。

当所有 Telegram 机器人/账户应表现相同时,使用全局设置。当不同的机器人需要不同的行为时(例如,一个账户仅处理私信,而另一个允许在群组中),使用每个账户的配置。

  • 默认:channels.telegram.dmPolicy = "pairing"。未知发送者会收到一个配对代码;消息会被忽略,直到获得批准(代码在 1 小时后过期)。
  • 批准方式:
    • openclaw pairing list telegram
    • openclaw pairing approve telegram <CODE>
  • 配对是用于 Telegram 私信的默认令牌交换。详情:配对
  • channels.telegram.allowFrom 接受数字用户 ID(推荐)或 @username 条目。它 不是 机器人用户名;使用人类发送者的 ID。向导接受 @username 并在可能时将其解析为数字 ID。

更安全(无第三方机器人):

  1. 启动网关并私信你的机器人。
  2. 运行 openclaw logs --follow 并查找 from.id

替代方案(官方 Bot API):

  1. 私信你的机器人。
  2. 使用你的机器人令牌获取更新并读取 message.from.id
    Terminal window
    curl "https://api.telegram.org/bot<bot_token>/getUpdates"

第三方(隐私性较低):

  • 私信 @userinfobot@getidsbot 并使用返回的用户 id。

两个独立的控制:

1. 哪些群组被允许(通过 channels.telegram.groups 的群组白名单):

  • groups 配置 = 允许所有群组
  • groups 配置 = 仅允许列出的群组或 "*"
  • 示例:"groups": { "-1001234567890": {}, "*": {} } 允许所有群组

2. 哪些发送者被允许(通过 channels.telegram.groupPolicy 的发送者过滤):

  • "open" = 允许群组中的所有发送者发消息
  • "allowlist" = 仅 channels.telegram.groupAllowFrom 中的发送者可以发消息
  • "disabled" = 完全不接受群组消息 默认为 groupPolicy: "allowlist"(除非你添加 groupAllowFrom,否则被阻止)。

大多数用户想要:groupPolicy: "allowlist" + groupAllowFrom + 在 channels.telegram.groups 中列出的特定群组

  • 默认:长轮询(不需要公共 URL)。
  • Webhook 模式:设置 channels.telegram.webhookUrl(可选 channels.telegram.webhookSecret + channels.telegram.webhookPath)。
    • 本地监听器默认绑定到 0.0.0.0:8787 并服务 POST /telegram-webhook
    • 如果你的公共 URL 不同,请使用反向代理并将 channels.telegram.webhookUrl 指向公共端点。

Telegram 支持通过标签进行可选的线程回复:

  • [[reply_to_current]] — 回复触发消息。
  • [[reply_to:<id>]] — 回复特定的消息 id。

channels.telegram.replyToMode 控制:

  • first(默认),alloff

Telegram 区分 语音笔记(圆形气泡)和 音频文件(元数据卡片)。 OpenClaw 默认为音频文件以保持向后兼容性。

要在智能体回复中强制使用语音笔记气泡,请在回复的任何位置包含此标签:

  • [[audio_as_voice]] — 将音频作为语音笔记而不是文件发送。

该标签会从交付的文本中剥离。其他频道忽略此标签。

对于 message 工具发送,设置 asVoice: true 并带有语音兼容的音频 media URL(当存在媒体时 message 是可选的):

{
"action": "send",
"channel": "telegram",
"to": "123456789",
"media": "https://example.com/voice.ogg",
"asVoice": true
}

OpenClaw 支持接收和发送带有智能缓存的 Telegram 贴纸。

当用户发送贴纸时,OpenClaw 根据贴纸类型进行处理:

  • 静态贴纸 (WEBP): 下载并通过视觉处理。贴纸在消息内容中显示为 <media:sticker> 占位符。
  • 动画贴纸 (TGS): 跳过(不支持处理 Lottie 格式)。
  • 视频贴纸 (WEBM): 跳过(不支持处理视频格式)。

接收贴纸时可用的模板上下文部分:

  • Sticker — 对象包含:
    • emoji — 与贴纸关联的表情符号
    • setName — 贴纸集的名称
    • fileId — Telegram 文件 ID(发送回相同的贴纸)
    • fileUniqueId — 用于缓存查找的稳定 ID
    • cachedDescription — 可用时的缓存视觉描述

贴纸通过 AI 的视觉功能进行处理以生成描述。由于相同的贴纸经常被重复发送,OpenClaw 会缓存这些描述以避免冗余的 API 调用。

工作原理:

  1. 首次遇到: 贴纸图像被发送给 AI 进行视觉分析。AI 生成描述(例如,“一只热情挥手的卡通猫”)。
  2. 缓存存储: 描述与贴纸的文件 ID、表情符号和集合名称一起保存。
  3. 后续遇到: 当再次看到相同的贴纸时,直接使用缓存的描述。图像不会发送给 AI。

缓存位置: ~/.openclaw/telegram/sticker-cache.json

缓存条目格式:

{
"fileId": "CAACAgIAAxkBAAI...",
"fileUniqueId": "AgADBAADb6cxG2Y",
"emoji": "👋",
"setName": "CoolCats",
"description": "A cartoon cat waving enthusiastically",
"cachedAt": "2026-01-15T10:30:00.000Z"
}

好处:

  • 通过避免对同一贴纸的重复视觉调用来降低 API 成本
  • 缓存贴纸的响应时间更快(无视觉处理延迟)
  • 启用基于缓存描述的贴纸搜索功能

缓存随着接收贴纸自动填充。不需要手动缓存管理。

智能体可以使用 stickersticker-search 动作发送和搜索贴纸。这些默认是禁用的,必须在配置中启用:

{
channels: {
telegram: {
actions: {
sticker: true
}
}
}
}

发送贴纸:

{
"action": "sticker",
"channel": "telegram",
"to": "123456789",
"fileId": "CAACAgIAAxkBAAI..."
}

参数:

  • fileId(必需)— 贴纸的 Telegram 文件 ID。接收贴纸时从 Sticker.fileId 获取,或从 sticker-search 结果中获取。
  • replyTo(可选)— 要回复的消息 ID。
  • threadId(可选)— 论坛主题的消息线程 ID。

搜索贴纸:

智能体可以按描述、表情符号或集合名称搜索缓存的贴纸:

{
"action": "sticker-search",
"channel": "telegram",
"query": "cat waving",
"limit": 5
}

返回缓存中的匹配贴纸:

{
"ok": true,
"count": 2,
"stickers": [
{
"fileId": "CAACAgIAAxkBAAI...",
"emoji": "👋",
"description": "A cartoon cat waving enthusiastically",
"setName": "CoolCats"
}
]
}

搜索使用跨描述文本、表情符号字符和集合名称的模糊匹配。

带线程的示例:

{
"action": "sticker",
"channel": "telegram",
"to": "-1001234567890",
"fileId": "CAACAgIAAxkBAAI...",
"replyTo": 42,
"threadId": 123
}

Telegram 可以在智能体生成回复时流式传输 草稿气泡。 OpenClaw 使用 Bot API sendMessageDraft(不是真实消息),然后作为普通消息发送最终回复。

要求 (Telegram Bot API 9.3+):

  • 启用了主题的私聊(机器人的论坛主题模式)。
  • 传入消息必须包含 message_thread_id(私有主题线程)。
  • 对于群组/超级群组/频道,流式传输被忽略。

配置:

  • channels.telegram.streamMode: "off" | "partial" | "block"(默认:partial
    • partial:使用最新的流式文本更新草稿气泡。
    • block:以较大的块(分块)更新草稿气泡。
    • off:禁用草稿流式传输。
  • 可选(仅适用于 streamMode: "block"):
    • channels.telegram.draftChunk: { minChars?, maxChars?, breakPreference? }
      • 默认值:minChars: 200, maxChars: 800, breakPreference: "paragraph"(限制为 channels.telegram.textChunkLimit)。

注意:草稿流式传输与 块流式传输(频道消息)是分开的。 块流式传输默认关闭,如果你想要早期 Telegram 消息而不是草稿更新,需要 channels.telegram.blockStreaming: true

推理流(仅限 Telegram):

  • /reasoning stream 在生成回复时将推理流式传输到草稿气泡中,然后发送不带推理的最终答案。
  • 如果 channels.telegram.streamModeoff,推理流被禁用。 更多上下文:流式传输 + 分块

出站 Telegram API 调用会在瞬态网络/429 错误时进行带有指数退避和抖动的重试。通过 channels.telegram.retry 配置。参见 重试策略

  • 工具:带有 sendMessage 动作的 telegramto, content, 可选 mediaUrl, replyToMessageId, messageThreadId)。
  • 工具:带有 react 动作的 telegramchatId, messageId, emoji)。