🤖HermesBlog
Hermes 实战教程 · 第3篇2026/8/9· Easy Understand Hermes Agent

实战:团队 Telegram 助手

Hermes 实战教程第3篇:团队 Telegram 助手。给整个团队配一个 AI。

实战:团队 Telegram 助手

实战:团队 Telegram 助手

兄弟们,今天咱们来点硬核又实用的——把 Hermes Agent 接进 Telegram,搞一个团队都能用的智能助手。别慌,全程不用写代码,跟着点几下就行。

💡 懒人福音:如果你用的是 dashboard 或桌面应用,直接打开 Messaging → Telegram 页面,点 Create with QR 按钮,扫码(或点开链接)就行——Hermes 会自动帮你创建机器人、识别你的 Telegram 用户 ID,把 TELEGRAM_BOT_TOKEN 和 TELEGRAM_ALLOWED_USERS 写进你配置的 .env,然后重启网关。想自己动手的,接着往下看。

第一步:找 BotFather 要个“机器人身份证”

Telegram 里所有机器人都是 @BotFather 管的。操作超简单:

  1. 打开 Telegram,搜 @BotFather(或者直接访问 t.me/BotFather)
  2. 发送 /newbot
  3. 给它起个显示名,比如 “Hermes Agent”
  4. 再起个唯一的用户名,必须以 bot 结尾,比如 my_hermes_bot
  5. BotFather 会回你一串 API Token,长这样:
123456789:ABCdefGHIjklMNOpqrSTUvwxYZ

⚠️ 这串 Token 就是机器人的命根子,谁拿到谁就能控制你的机器人。万一泄露了,赶紧回 BotFather 用 /revoke 吊销重来。

第二步:给机器人“化妆”(可选但推荐)

想让队友用得舒服?给 BotFather 发这些命令:

命令 作用
/setdescription 设置机器人开场白
/setabouttext 个人主页简介
/setuserpic 上传头像
/setcommands 设置 / 菜单命令
/setprivacy 控制群聊消息可见性

推荐用 /setcommands 设置一组基础命令:

help - Show help information
new - Start a new conversation
sethome - Set this chat as the home channel

第三步:在线状态指示(小彩蛋)

Telegram 机器人没有“在线绿点”,但我们可以曲线救国——用简介文字显示状态。在 ~/.hermes/config.yaml 里加:

gateway:
  platforms:
    telegram:
      extra:
        status_indicator: true
        status_online: "🟢 Online"
        status_offline: "🔴 Offline"

这样网关一连接,机器人简介就显示“🟢 Online”,正常关闭时变“🔴 Offline”。注意:只有干净退出才会变 Offline,直接杀进程的话状态会卡住。另外这个简介是全局的(所有用户都能看到),不是每个聊天单独显示,而且默认关闭,因为它会改动机器人的全局资料。

第四步:冷启动时别丢消息(可选)

默认情况下,网关冷启动时会丢掉 Telegram 服务器上堆积的待处理消息(第一次 start_polling 时 drop_pending_updates=True)。这对 7×24 常开的服务器挺合适——重启就当清理旧账。但如果你是把 Hermes 跑在会关机的机器上(比如晚上关掉的台式机),那离线期间别人发的消息就会在下次开机时被悄悄扔掉,没日志、没重试。

想让这些积压消息在启动时按顺序补上,就把它关掉:

platforms:
  telegram:
    extra:
      drop_pending_on_cold_boot: false

几点提醒:默认是 true,不设就是老行为;网络抖动导致的 watcher 重连(进程还活着)永远保留队列,跟这个开关无关;崩溃后补发的队列可能重放一条已经处理过一半的消息,Telegram 的 offset 一般能挡住,但长时间离线期间发的时效性命令会在开机时执行。

第五步:重复消息去重(可选)

Telegram 偶尔会把同一条 update_id 重复投递过来,Hermes 会在消息批处理、命令/媒体处理、群历史写入和插件观察者之前就把重复的 update_id 拦掉。这个检查按接收适配器 + 数字 bot ID 划分作用域,不按文本或 message_id 去重——所以一条真正的新编辑(带新的 update ID)照样能处理。

这是一层有界的内存保护,不是“精确一次”的保证:

  • 适配器记住最近 4096 条已完成的准入记录,不设过期时间。正在处理的 update 会一直保持“已认领”状态,直到分发和它调度的 PTB handler 任务(包括非阻塞的原生插件和注册的错误回调)跑完。
  • 同一个适配器重连会保留这份历史;但淘汰、适配器替换或进程重启都可能让旧 update 再次进来——磁盘上不写任何重放账本。
  • 准备阶段失败或被取消、且还没交接出去的话,会释放认领;一旦 update 进入批处理/暂存队列、网关分发、观察者或原生插件,之后再出错也不会重新打开。原生插件自己负责自己的部分副作用,所以进入它们的 update 或注册的错误回调会被保守地视为“已交接”。PTB 自己的异常日志不算交接。未缓存的静态贴纸视觉分析也算交接:取消 await 也撤不回已经提交的辅助模型请求。交接前被捕获的准备错误仍可重试;主动拒绝则是终态。
  • 释放认领只是允许后续再投递,并不会主动向 Telegram 请求重发。轮询确认和 agent 是否跑完是两码事。这个检查不会重试失败的回复,也挡不住下游组件自己重复干活。

怀疑遇到迟到的重放时,把两次出现的 bot/profile、chat/topic、update_id、update 类型、message_id 和实际接收时间都对比一下——编辑可以复用 message_id,而消息的发送时间戳不等于接收时间。

第六步:命令菜单优化(团队必备)

默认命令菜单上限 60 个,够用但可能不够“顺手”。想让你团队的常用命令排前面?这样配:

platforms:
  telegram:
    extra:
      command_menu:
        max_commands: 60
        priority_mode: prepend  # prepend | append | replace
        priority:
          - my_plugin_command
          - songsee

priority_mode 三种玩法:

  • prepend:你的命令排最前
  • append:你的命令排最后
  • replace:完全用你的列表

重点来了:以前技能命令总是被优先裁剪,现在只要在 priority 里点名,保证有菜,不会被挤掉。Telegram 本身最多允许 100 条命令,但命令太多容易发送失败,所以 Hermes 默认取 60 条保稳,配置值会被限制在 1..100 之间;想看完整命令列表用 /commands。

第七步:隐藏大招——内联搜索

/ 菜单有上限,但 Telegram 的内联模式没有!在任意聊天框输入 @你的机器人名 加关键词,就能实时搜索所有命令和技能:

@my_hermes_bot plan            → 找到 /plan
@my_hermes_bot plan migrate    → 直接发送带参数的命令
@my_hermes_bot pdf             → 搜到所有跟 pdf 相关的技能

第一个词用来过滤目录,后面的内容会作为参数带进发送的命令里。点一下结果,命令就会以普通消息的形式发出去,走标准命令通道(带命令前缀的消息即使开了隐私模式也能到达机器人)。

注意:内联模式默认关闭,得去 @BotFather 发 /setinline 开启(随便设个占位提示文字,比如 Search commands and skills...)。而且只有通过你网关白名单的人才能看到结果,外人搜到的永远是空列表,隐私安全有保障。

第八步:并发处理,别让一个慢请求拖垮全群

团队场景里最怕的就是“一个人卡住,全群陪跑”。现在 Hermes 把不同聊天的消息改成并发处理了——某个聊天里遇到超长的模型重试、大文件下载,不会再拖住其他聊天。同一个聊天里的消息仍然按到达顺序一条条来,不会乱。

跨聊天的并发池默认是 32,填了非法值会打一条警告并回退到默认值:

platforms:
  telegram:
    extra:
      max_concurrent_updates: 32   # 设为 1 就恢复成完全串行处理

第九步:澄清问题别干等(超时可配)

机器人有时候会反问你一句(比如“你要发到哪个频道?”),然后等你回复。这个等待时间现在可以配了,在 ~/.hermes/config.yaml 里改 agent.clarify_timeout(默认 3600 秒,也就是一小时)。如果你一直不回,agent 不会傻等,会带着 "outcome": "timed_out" 自己往下走、随机应变。不想回答某个问题时,直接回 skip 跳过就行。

最后一步:隐私模式

群聊里机器人默认只看被 @ 的消息。想让它“眼观六路”?在 BotFather 用 /setprivacy 关掉隐私模式即可。不过建议团队场景保持默认,省得被刷屏。

💡 小技巧:不想关隐私模式,也可以把机器人提升为群管理员——管理员机器人无视隐私设置,永远能收到所有消息。

进阶:让机器人“潜水观察”但不乱插嘴

想要 OpenClaw / 元宝那种群聊效果——机器人能看到普通群消息,但只在被直接触发时才回应?这样配:

telegram:
  allowed_chats:
    - "-1001234567890"
  group_allowed_chats:
    - "-1001234567890"
  require_mention: true
  observe_unmentioned_group_messages: true

开启后,来自白名单群/话题的未 @ 消息会作为“观察到的上下文”追加到共享会话记录里,但不会触发 agent。之后在同一个群/话题里 @ 机器人、回复机器人或命中配置的触发词时,就能用上这些上下文。allowed_chats 决定机器人在哪里回应,group_allowed_chats 授权用于观察上下文的共享群会话,所以这个模式下两个列表填一样的 chat ID。这个功能同样要求 Telegram 把普通群消息投递给网关,所以还是得关隐私模式或把机器人设为群管理员。

进阶:DM 话题模式下根消息怎么处理

开了 /topic 话题模式后,有些 Telegram 客户端会把你在根 DM(General / All Messages)里发的消息投递过来,却不带 message_thread_id。默认情况下 Hermes 把它当成“续聊”,回复到你最近活跃的那个话题里(lobby recovery)。

想让每条根 DM 消息都开一个全新会话,就打开 dm_topic_auto_transfer:

gateway:
  platforms:
    telegram:
      extra:
        dm_topic_auto_transfer: true   # 默认 false

开启后,根 DM 里的普通消息会让 Hermes 新建一个话题(自动改名前叫 “Hermes Chat”),在那里开新会话并把回复发进该话题。根 DM 里输入的斜杠命令仍算 lobby 命令,不会创建话题。如果建话题失败(比如 BotFather 里把 Threaded Mode 关了),Hermes 会回退到默认行为,回复到你最近活跃的话题。这个开关只在 /topic 模式开启时才有意义。顶层的 telegram.extra.dm_topic_auto_transfer 键(桌面设置里显示的那个)同样生效。

进阶:多机器人同群,防止“无限套娃”

群里放了多个 Hermes 机器人时,如果开了 TELEGRAM_ALLOW_BOTS=all,两个机器人互相回复引用可能无限循环——因为对机器人的回复总能通过 require_mention 这道门。把 telegram.bots_require_mention: true(环境变量 TELEGRAM_BOTS_REQUIRE_MENTION)打开就能堵住这条路:来自其他机器人的消息只有明确 @ 本机器人才会触发回应,人类回复不受影响。

另外还有一个机器人循环守卫,会统计每个允许机器人发言的聊天(TELEGRAM_ALLOW_BOTS 设为 mentions 或 all):5 分钟内某个聊天里机器人消息达到 20 条,接下来 10 分钟该聊天的机器人消息会被丢弃,并记录一条警告;人类消息永远不计数、不丢弃。配置在 config.yaml:

gateway:
  bot_loop_guard:
    enabled: true        # false 关闭守卫
    max_events: 20       # 每个聊天每个窗口的机器人消息数
    window_seconds: 300
    cooldown_seconds: 600

注意:如果某个正经机器人确实需要 5 分钟内往一个聊天发超过 20 条消息,也会触发守卫,这种情况把 max_events 调高即可。


搞定!现在你的团队可以在 Telegram 里随时 @ 机器人干活了——发语音自动转文字、定时任务结果推送、群聊协作,全都能玩。快去试试吧!

📖 官方文档

本文根据 Hermes Agent 官方文档编写,原文见:官方文档 › user-guide/messaging/telegram