← 返回文章列表

用 Telegram 给多机 AI Agent 做一个可见的指挥面

为什么还需要一个聊天指挥面

我已经有两层 agent 协作基础设施。

第一层是基于 Git 的记忆和交接:规则、长期记忆、项目上下文、agent 之间的异步留言都进仓库。这一层可靠、可审计、可回放,但它不是实时入口。它适合保存事实,不适合在手机上临时喊一句「这台机器帮我跑一下」。

第二层是 A2A 这种机器间实时调用:一个 agent 可以把任务派给另一个 agent,等结果回来。这一层解决的是机器到机器的执行通道。

但中间还缺一层:人怎么进入这张网。

我不想每次都 SSH 到某台机器,也不想在十几个终端里找哪个 agent 在线。更自然的入口应该像一个群:我能看到各台机器在说什么,能按设备发任务,能在执行中插话,必要时也能把一条任务广播给所有 agent。

这就是 Telegram 适合的位置。它不是记忆层,也不是执行协议;它是人可见的指挥面。

拓扑:一个大群,每台机器一个话题

最终的结构很简单:

Telegram supergroup
  ├─ Topic: control
  │    └─ control bot -> control machine agent
  ├─ Topic: laptop
  │    └─ laptop bot -> laptop agent
  ├─ Topic: cloud
  │    └─ cloud bot -> cloud agent
  └─ Topic: phone
       └─ phone bot -> phone agent

这里有两个关键选择。

第一,每台机器一个 bot。 不要让多台机器共用同一个 Telegram bot token。Telegram 的 long polling 对同一个 token 只能有一个消费者,多机共用会互相抢 getUpdates,最后表现成某台机器突然收不到消息。多个 bot 在同一个群里没有问题,前提是每个 bot 有自己的 token。

第二,用 topic 做设备路由。 群是共同的观察面,topic 是设备的边界。某台机器的 bot 只处理自己 topic 里的消息,别的 topic 静默忽略。这样就不会出现「我在群里说一句话,所有机器一起抢答」。

Telegram bot 的几个真实坑

Telegram 的接入并不复杂,但有几个坑很容易浪费时间。

Group Privacy 默认会挡掉群消息。 新建 bot 后,如果没有在 BotFather 里关闭 Group Privacy,bot 在群里只能看到非常有限的消息。最迷惑的是:这个状态可能在 bot 加群时被缓存。正确顺序是先关闭隐私模式,再把 bot 加进群;如果顺序反了,就把 bot 移出群后重新加入,或者把它设为群管理员。

chat 白名单和 topic 白名单是两层门。 用户白名单只能说明「谁可以操作」,不能替代「在哪个群、哪个话题响应」。群消息要同时经过 chat 和 topic 的过滤。发错 topic 时,最常见的现象不是报错,而是静默丢弃。

手动调 getUpdates 会和 gateway 抢轮询。 排查时用它拿 user id 或看 poller 是否还活着没问题,但要知道它会和正在运行的 gateway 竞争同一个 long polling。健康的 gateway 占着轮询时,手动请求看到冲突反而可能是好信号;如果一直空返回,才要怀疑 gateway 没在真正收消息。

进程活着不等于 poller 活着。 有些故障里 gateway 进程还在,状态文件也看起来正常,但底层长轮询已经停了。只用 pgrep 做健康检查会漏掉这种半死状态。更可靠的检查应该包含应用层信号:消息是否真的被拉取、是否还在占用 long polling、是否能回应一条只读测试。

常驻问题:手机和服务器不是同一种环境

在标准 Linux 服务器上,gateway 常驻可以交给 systemd。写一个 unit,设置 restart policy,开机自启,这件事就结束了。

但手机上的 Linux 子系统不是标准服务器。没有 systemd,没有 cron,进程还可能被宿主系统电池策略回收。这里就不能照搬服务器思路。

我最后用的是四层兜底:

开机触发
  -> 前台 holder 保持子系统会话
  -> keepalive watchdog
  -> ensure 脚本做幂等启动
  -> gateway 前台长轮询

这套结构的重点不是脚本名字,而是职责拆开:

  • ensure 只负责「如果没起来,就用脱离当前 shell 的方式启动」。
  • keepalive 负责「进程或应用层健康失败时拉起」。
  • 开机触发负责「设备重启后恢复」。
  • shell 启动钩子负责「人工进入环境时顺手自愈」。

还有一个很小但很致命的坑:不要随手写 pkill -f "some command"。它可能匹配到正在执行这条命令的 shell 自己,导致排障命令把自己杀掉。按 pid 操作,或者用不会自匹配的模式。

安全边界:这是能驱动本机 shell 的入口

Telegram 看起来只是聊天工具,但这条链路背后连的是本机 agent,agent 又可能驱动 terminal。换句话说,这不是普通 bot,这是远程操作入口。

所以安全约束必须前置:

  • bot token 只放本机密钥文件,不写进仓库、文章、提交信息。
  • 只允许明确的用户 id。
  • 只允许明确的群。
  • 只允许明确的 topic。
  • 不让陌生群和陌生用户触发本机 agent。
  • 公网服务至少要有 TLS 和可轮换的 bearer token。
  • 真正执行 shell 的工具要尽量收窄权限,不能把「聊天入口」等同于「无限制远程 root」。

这类系统的危险不在于单条命令,而在于链路太顺:手机上发一句话,远端机器真的执行了。顺是优点,也是风险。

它和 A2A、Git 记忆的分工

现在回头看,三层分工很清楚。

Git 记忆层解决的是:长期事实、规则、项目上下文和跨会话交接放在哪里。它慢,但可靠。

A2A 数据层解决的是:机器之间怎么实时派发任务和拿结果。它快,但更像执行通道。

Telegram 指挥面解决的是:人怎么观察、插话、派活、临时接管。它不是事实源,也不应该承担最终审计;它只是让这张网变得可操作。

这三个东西混在一起会出问题。把 Telegram 当记忆库,会丢上下文;把 Git 当实时指挥面,会太慢;把 A2A 当人类入口,又缺少可见性和插话能力。

正确的组合应该是:

Telegram = 人类可见指挥面
Git       = 长期记忆与审计面
A2A       = 机器间实时执行面

最大的收获:先把路由和可见性做好

这次接入看似是在「把 bot 接进群」,本质上是在给多机 agent 系统补一层操作台。

如果没有 topic 路由,群会变成噪音池;如果没有白名单,群会变成风险入口;如果没有常驻和健康检查,群会变成一个看似在线、实际半死的假入口;如果没有 Git 记忆和 A2A 执行层,群又只剩聊天,没有系统能力。

所以这层的设计重点不是酷炫,而是四个字:可见、可控。

可见,是我能知道哪台机器在响应、哪条任务去了哪里。可控,是我能把任务限制在正确的群、正确的话题、正确的用户和正确的执行面里。

多 agent 系统越往后走,越不像「开几个 AI 聊天窗口」,越像在维护一组有权限、有状态、有网络拓扑的自动化节点。Telegram 只是入口,但入口设计不好,后面的系统能力就会变成不可控的黑箱。