Telegram(Bot API)
Telegram 机器人设置:从 @BotFather 获取 token 并填入。状态:通过 grammY 支持私聊与群组,可用于生产。默认 long-polling;可选 webhook。
快速设置(入门)
- 用 @BotFather 创建机器人并复制 token。
- 设置 token:
- 环境变量:
TELEGRAM_BOT_TOKEN=... - 或配置:
channels.telegram.botToken: "..."。 - 若两者都设,以配置为准(环境变量仅作默认账号回退)。
- 环境变量:
- 启动网关。
- 私聊默认配对;首次联系时批准配对码。
最小配置:
{
channels: {
telegram: {
enabled: true,
botToken: "123:abc",
dmPolicy: "pairing"
}
}
}说明
- 由网关持有的 Telegram Bot API 频道。
- 确定性路由:回复始终发回 Telegram;模型不会选择频道。
- 私聊共享 agent 主会话;群组独立(
agent:<agentId>:telegram:group:<chatId>)。
设置(快速路径)
1) 创建机器人 token(BotFather)
- 打开 Telegram,与 @BotFather 对话。
- 发送
/newbot,按提示填写名称和以bot结尾的用户名。 - 复制 token 并妥善保存。
可选 BotFather 设置:
/setjoingroups— 允许/禁止将机器人加入群组。/setprivacy— 控制机器人是否接收所有群组消息。
2) 配置 token(环境变量或配置)
示例:
{
channels: {
telegram: {
enabled: true,
botToken: "123:abc",
dmPolicy: "pairing",
groups: { "*": { requireMention: true } }
}
}
}环境变量:TELEGRAM_BOT_TOKEN=...(仅对默认账号生效)。若环境变量与配置都设,以配置为准。多账号:使用 channels.telegram.accounts,每账号单独 token 并可设 name。共享模式见 配置。
- 启动网关。解析到 token(先看配置,再回退环境变量)后 Telegram 会启动。
- 私聊默认配对。首次联系机器人时批准配对码。
- 群组:将机器人加入群组,决定隐私/管理员行为(见下),再通过
channels.telegram.groups控制 @ 提及门控与白名单。
Token、隐私与权限(Telegram 侧)
创建 token(BotFather)
/newbot会创建机器人并返回 token(请保密)。- 若 token 泄露,通过 @BotFather 撤销/重新生成并更新配置。
群组消息可见性(隐私模式)
Telegram 机器人默认开启隐私模式,会限制收到的群组消息。若机器人必须看到所有群组消息,有两种做法:
- 用
/setprivacy关闭隐私模式,或 - 将机器人设为群组管理员(管理员机器人会收到所有消息)。
说明:切换隐私模式后,Telegram 要求从每个群组中移除并重新添加机器人,更改才会生效。
群组权限(管理员)
管理员在群组内设置(Telegram 界面)。管理员机器人始终会收到所有群组消息,若需完整可见性请使用管理员。
行为说明
- 入站消息被规范为统一频道信封,带回复上下文与媒体占位符。
- 群组回复默认需要 @ 提及(原生 @ 或
agents.list[].groupChat.mentionPatterns/messages.groupChat.mentionPatterns)。 - 多 agent 覆盖:在
agents.list[].groupChat.mentionPatterns上设每 agent 规则。 - 回复始终路由回同一 Telegram 会话。
- Long-polling 使用 grammY runner 按会话排序;总并发受
agents.defaults.maxConcurrent限制。 - Telegram Bot API 不支持已读回执;无
sendReadReceipts选项。
格式(Telegram HTML)
- 出站 Telegram 文本使用
parse_mode: "HTML"(Telegram 支持的标签子集)。 - 类 Markdown 输入会渲染为** Telegram 安全 HTML**(粗体/斜体/删除线/代码/链接);块级元素会压成带换行/列表的文本。
- 模型输出的原始 HTML 会被转义,避免 Telegram 解析错误。
- 若 Telegram 拒绝 HTML payload,Moltbot 会以纯文本重发同一条消息。
命令(原生 + 自定义)
Moltbot 在启动时向 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 被阻断。 - 若出现
sendMessage或sendChatAction失败,检查 IPv6 路由与 DNS。
更多帮助见 频道故障排查。说明:
- 自定义命令仅作为菜单项;除非你在别处处理,否则 Moltbot 不会实现它们。
- 命令名会规范化(去掉前导
/、转小写),且必须匹配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。
群组激活模式
默认机器人仅在群组中被人 @ 时回复(@机器人名 或 agents.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— 需要 @ 提及(默认)
说明:命令只更新会话状态。若要重启后仍生效,请用配置。
获取群组 chat ID
将群组中任意一条消息转发给 Telegram 上的 @userinfobot 或 @getidsbot 即可看到 chat ID(负数如 -1001234567890)。提示:要查自己的用户 ID,可私聊机器人,配对消息中会回复你的用户 ID,或启用命令后使用 /whoami。隐私说明:@userinfobot 为第三方机器人。若介意,可将机器人加入群组、发一条消息,用 moltbot logs --follow 查看 chat.id,或使用 Bot API 的 getUpdates。
配置写入
默认允许 Telegram 写入由频道事件或 /config set|unset 触发的配置更新。会在以下情况发生:
- 群组升级为超级群组且 Telegram 发出
migrate_to_chat_id(chat ID 变更)。Moltbot 可自动迁移channels.telegram.groups。 - 你在 Telegram 会话中执行
/config set或/config unset(需commands.config: true)。
禁用方式:
{
channels: { telegram: { configWrites: false } }
}主题(论坛超级群组)
Telegram 论坛主题中每条消息带有 message_thread_id。Moltbot:
- 在 Telegram 群组会话键后追加
:topic:<threadId>,使每个主题独立。 - 发送输入中与回复时带上
message_thread_id,使回复留在主题内。 - 通用主题(thread id
1)较特殊:发送消息时不带message_thread_id(Telegram 会拒绝),但输入中仍会带。 - 在模板上下文中暴露
MessageThreadId与IsForum,用于路由/模板。 - 每主题配置在
channels.telegram.groups.<chatId>.topics.<threadId>下(skills、白名单、自动回复、系统提示、禁用)。 - 主题配置继承群组设置(requireMention、白名单、skills、prompts、enabled),除非按主题覆盖。
私聊在少数情况下也可能带 message_thread_id。Moltbot 保持私聊会话键不变,但若存在则仍用 thread 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"。
发送按钮
使用 message 工具的 buttons 参数:
{
"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 数据会以消息形式发回 agent,格式为:callback_data: value
配置选项
Telegram 能力可在两个层级配置(上为对象形式;旧版字符串数组仍支持):
channels.telegram.capabilities:全局默认能力配置,应用于所有 Telegram 账号,除非被覆盖。channels.telegram.accounts.<account>.capabilities:每账号能力,覆盖该账号的全局默认。
所有 Telegram 机器人/账号行为一致时用全局;不同机器人需要不同行为时(例如一个只处理私聊、另一个允许群组)用每账号配置。
访问控制(私聊 + 群组)
私聊访问
- 默认:
channels.telegram.dmPolicy = "pairing"。未知发件人收到配对码;批准前消息被忽略(配对码 1 小时后过期)。 - 批准方式:
moltbot pairing list telegram、moltbot pairing approve telegram <CODE>。 - 配对是 Telegram 私聊的默认 token 交换方式。详见 配对。
channels.telegram.allowFrom接受数字用户 ID(推荐)或@username。不是机器人用户名;请用人类发件人的 ID。向导接受@username并在可能时解析为数字 ID。
查找你的 Telegram 用户 ID
更安全(无需第三方机器人):
- 启动网关并私聊你的机器人。
- 运行
moltbot logs --follow,查找from.id。
替代(官方 Bot API):
- 私聊你的机器人。
- 用机器人 token 拉取 updates 并读取
message.from.id:
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 中列出具体群组。
Long-polling 与 webhook
- 默认:long-polling(无需公网 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(默认)、all、off。
语音消息(语音与文件)
Telegram 区分语音消息(圆泡)与音频文件(元数据卡片)。Moltbot 默认按音频文件处理以保持兼容。若希望 agent 回复以语音消息泡显示,在回复中任意位置加入标签:[[audio_as_voice]] — 以语音消息而非文件发送音频。该标签会从发出的文本中移除,其他频道会忽略。message 工具发送时,对兼容语音的 media URL 设置 asVoice: true(有 media 时 message 可选):
{
"action": "send",
"channel": "telegram",
"to": "123456789",
"media": "https://example.com/voice.ogg",
"asVoice": true
}贴纸
Moltbot 支持接收与发送 Telegram 贴纸,并带智能缓存。
接收贴纸
用户发送贴纸时,Moltbot 按贴纸类型处理:
- 静态贴纸(WEBP):下载并通过视觉模型处理。贴纸在消息内容中以
<media:sticker>占位符出现。 - 动图贴纸(TGS):跳过(Lottie 格式不支持处理)。
- 视频贴纸(WEBM):跳过(不支持该视频格式处理)。
接收贴纸时可用的模板上下文字段:Sticker — 对象,含 emoji、setName、fileId、fileUniqueId、cachedDescription(有缓存时)。
贴纸缓存
贴纸经 AI 视觉能力生成描述。同一贴纸常被重复发送,Moltbot 会缓存这些描述以减少重复 API 调用。流程:首次遇到时发送贴纸图片给 AI 做视觉分析并生成描述;描述与 file ID、emoji、set name 一起存入缓存;再次遇到同一贴纸时直接使用缓存描述,不再发图给 AI。缓存位置:~/.clawdbot/telegram/sticker-cache.json。
发送贴纸
Agent 可通过 sticker 和 sticker-search 动作发送与搜索贴纸。默认关闭,需在配置中启用:channels.telegram.actions.sticker: true。发送贴纸时 fileId 必填(来自接收时的 Sticker.fileId 或 sticker-search 结果);可选 replyTo、threadId。搜索贴纸:agent 可按描述、emoji 或 set name 搜索缓存贴纸,使用 sticker-search 动作。
流式(草稿)
Telegram 可在 agent 生成回复时流式显示草稿泡。Moltbot 使用 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.streamMode 为 off,推理流式会被关闭。更多说明见 流式与分块。
重试策略
出站 Telegram API 在瞬时网络/429 错误时会指数退避与抖动重试。通过 channels.telegram.retry 配置。见 重试策略。
Agent 工具(消息 + 表态)
- 工具:
telegram,动作sendMessage(to、content,可选mediaUrl、replyToMessageId、messageThreadId)。 - 工具:
telegram,动作react(chatId、messageId、emoji)。 - 工具:
telegram,动作deleteMessage(chatId、messageId)。 - 表态移除语义见 表态。
- 工具门控:
channels.telegram.actions.reactions、channels.telegram.actions.sendMessage、channels.telegram.actions.deleteMessage(默认启用),以及channels.telegram.actions.sticker(默认禁用)。
表态通知
Telegram 表态以独立的 message_reaction 事件到达,而非消息 payload 中的属性。用户添加表态时,Moltbot:1) 从 Telegram API 收到 message_reaction 更新;2) 转为格式为 "Telegram reaction added: {emoji} by {user} on msg {id}" 的系统事件;3) 使用与普通消息相同的会话键将系统事件入队;4) 当下一条消息到达该会话时,系统事件被取出并追加到 agent 上下文前。Agent 在会话历史中看到的是系统通知形式的表态,而非消息元数据。配置:channels.telegram.reactionNotifications 控制哪些表态触发通知(off、own(默认)、all);channels.telegram.reactionLevel 控制 agent 表态能力(off、ack(默认)、minimal、extensive)。
投递目标(CLI/定时任务)
- 使用 chat id(
123456789)或用户名(@name)作为目标。 - 示例:
moltbot message send --channel telegram --target 123456789 --message "hi"。
故障排查
机器人在群组中不回复非 @ 消息:若设置了 channels.telegram.groups.*.requireMention=false,Telegram Bot API 的隐私模式必须关闭(BotFather:/setprivacy → Disable,然后从群组移除并重新添加机器人)。moltbot channels status 在配置期望未 @ 的群组消息时会显示警告。快速测试:/activation always(仅会话级;持久化需用配置)。
机器人完全收不到群组消息:若设置了 channels.telegram.groups,群组必须在列表中或使用 "*";在 @BotFather 中检查「Group Privacy」应为 OFF;确认机器人确实是成员;查看网关日志 moltbot logs --follow(查找 “skipping group message”)。
机器人回复 @ 但不响应 /activation always:/activation 只更新会话状态,不会写入配置;要持久生效,请在 channels.telegram.groups 中为该群组添加 requireMention: false。
/status 等命令不工作:确认你的 Telegram 用户 ID 已授权(通过配对或 channels.telegram.allowFrom);即使 groupPolicy: "open" 的群组中,命令也需要授权。
Node 22+ 下 long-polling 立即中止:Node 22+ 对 AbortSignal 更严格;可升级到规范化 abort 信号的 Moltbot 版本,或在能升级前用 Node 20 运行网关。
机器人启动后静默不再响应(或日志 HttpError: Network request ... failed):部分主机会优先将 api.telegram.org 解析为 IPv6。若服务器没有可用 IPv6 出口,grammY 可能卡在仅 IPv6 请求。解决:启用 IPv6 出口或强制对 api.telegram.org 使用 IPv4(例如在 /etc/hosts 中添加 IPv4 A 记录,或在系统 DNS 中优先 IPv4),然后重启网关。快速检查:dig +short api.telegram.org A 和 dig +short api.telegram.org AAAA 确认 DNS 返回结果。
配置参考(Telegram)
完整配置见 配置。本频道选项包括:channels.telegram.enabled、botToken、tokenFile、dmPolicy、allowFrom、groupPolicy、groupAllowFrom、groups(含 requireMention、skills、allowFrom、systemPrompt、enabled、topics.<threadId>.*)、capabilities.inlineButtons、replyToMode、textChunkLimit、chunkMode、linkPreview、streamMode、mediaMaxMb、retry、network.autoSelectFamily、proxy、webhookUrl、webhookSecret、webhookPath、actions.reactions、actions.sendMessage、actions.deleteMessage、actions.sticker、reactionNotifications、reactionLevel。相关全局选项:agents.list[].groupChat.mentionPatterns、messages.groupChat.mentionPatterns、commands.native、commands.text、commands.useAccessGroups(可被 channels.telegram.commands.native 覆盖)、messages.responsePrefix、messages.ackReaction、messages.ackReactionScope、messages.removeAckAfterReply。