五个 Gateway 进程共存:AI Agent 消息平台 Token 锁冲突

本文最后更新于 2026年8月5日 凌晨

每次给 AI Agent 开一个新 profile(韩梅梅、李雷、露西……),都会顺手起一个 hermes gateway run。一个 profile 一个进程,五个 profile 五个进程,听着很合理——直到微信 bot 突然全线失联,日志里全是 “Weixin bot token already in use”

这就是多 Gateway 进程的 Token 锁冲突。表面看是微信 bot 连不上,实际上是 Hermes 的消息平台 Token 在进程级共享,而每个 Gateway 都认为自己拿到了所有权。

问题的发现

日志不会撒谎。这是某次排查时的现场记录:

1
2
3
4
5
6
2026-07-15 22:36:32 [INFO]  Connected to Weixin bot (ws://...)
2026-07-15 22:36:33 [ERROR] Weixin bot token already in use (PID 1097147). Stop the other gateway first.
2026-07-15 22:37:03 [ERROR] Reconnecting weixin (attempt 2)... token already in use (PID 1097147).
2026-07-15 22:38:03 [ERROR] Reconnecting weixin (attempt 3)... token already in use (PID 1097147).
2026-07-15 22:39:34 [INFO] ✓ feishu disconnected
2026-07-15 22:39:34 [INFO] ✓ api_server disconnected

注意到 token already in use (PID 1097147) 了吗?PID 1097147 是另一个 Gateway 进程,它比当前进程先连上了微信。当前 Gateway 被卡在了一个指数退避重连循环里(60s → 120s → 240s),永远等不到释放。

为什么会冲突

Hermes 的 Gateway 架构里,消息平台接入(微信、飞书、API Server 等)走的是同一套平台适配器,而微信 bot 的 Token 是一个全局共享资源——不是每个 profile 一份。

这意味着:

  • 微信 bot Token 只能被一个 Gateway 持有。无论起多少个进程,第一个连上的就是唯一能收消息的那个。
  • 飞书和 API Server 没有这个限制。飞书 WebSocket 是每个 app 一个连接,API Server 是 HTTP 端口监听,两者都不存在 Token 互斥。
  • --replace 参数只替换本 profile 的 Gateway 进程,不会去停别的 profile 的进程。

实际现场:六个 Hermes 进程同时在线——

PID Profile 状态 微信
1003464 default (main) running ✅ 持有 Token
1003504 hanmeimei running ✗ Token 被占
1003614 lilei running ✗ Token 被占
1003765 lucy running ✗ Token 被占
1003891 polly running ✗ Token 被占
1003994 xiaomei running ✗ Token 被占

hanmeimeixiaomei 这五个子进程的微信通道,全部是死的。

除了微信 Token 锁,还有一个并行问题:Kanban Dispatcher 的锁文件 /home/tony/.hermes/kanban/.dispatcher.lock 也是进程级互斥。同一时刻只能有一个 Gateway 持有 dispatcher lock,其他进程只会输出:

1
kanban dispatcher: another gateway already holds the dispatcher lock; this gateway will NOT dispatch.

这不是 Bug,是设计行为——多个 Gateway 共享同一个 Task Queue,必须保证调度不重复。真正需要排查的是平台 Token,而不是 dispatcher lock。

根本原因

项目 说明
平台 Token 共享 微信 bot Token 在所有 profile 间共享,不随 profile 隔离
没有 Token 抢占 Hermes 没有”踢掉旧进程、抢 token”机制,后来者只能被动等待
退避重连无上限 退避间隔只增不减,最长 240s,理论上永远等不到
--replace 不跨 profile 只重启本 profile,不会清理其他 profile 的连接

换句话说:微信 bot 在设计上就是单点接入的,而多 Gateway 部署没有做 Token 路由。

怎么修

方案 A:只留一个主 Gateway 接微信

最稳妥的做法。微信 bot 只配在 main profile(default),其他子 profile 的 config 里直接 weixin: { enabled: false }

1
2
3
4
5
platforms:
weixin:
enabled: false # 子 profile 不用微信
feishu:
enabled: true # 飞书可以每个 profile 独立开

这样只有 main Gateway 接微信,其他进程专心处理本 profile 的飞书/Telegram 等独立平台。

方案 B:子 profile 走不同消息通道

每个 AI Agent 用自己的消息通道,避免 Token 碰撞:

  • 韩梅梅 → Telegram bot(独立 token)
  • 李雷 → Discord(独立 bot)
  • 露西 → Slack(独立 app)
  • 主进程 → 微信 + API Server

Hermes 对 Telegram、Discord、Slack 的支持是每个 bot/app 一个连接,天然互不干扰,不存在 Token 锁。

方案 C:手动轮转(不推荐)

如果确实需要所有 profile 都能接微信,只能:

  1. ps aux | grep "hermes gateway" 确认所有 Gateway 的 PID
  2. 找到持有微信 Token 的进程,kill
  3. 重启目标 profile 的 Gateway
  4. 验证日志无 token already in use

这只能应急,不能当常态。每次新进程上来还是会撞。

验证方法

1
2
3
4
5
6
7
8
9
10
11
12
13
# 1. 确认只有 main 进程在接微信
grep "Weixin bot token" ~/.hermes/logs/gateway.log | tail -5
# 预期:只有 default 进程的日志,无报错

# 2. 确认 dispatcher lock 正常
grep "dispatcher" ~/.hermes/logs/gateway.log | tail -5
# holding singleton dispatcher lock = 正常
# another gateway already holds = 其他进程正确退让

# 3. 确认各 profile 独立平台可用
for p in hanmeimei lilei lucy polly xiaomei; do
grep "feishu.*connected\|telegram.*connected" ~/.hermes/profiles/$p/logs/gateway.log 2>/dev/null | tail -1
done

经验教训

多 Gateway 部署的本质问题是资源粒度不匹配:Gateway 是 profile 级进程,但消息平台 Token 是全局级资源。架构上的不对称必然导致冲突。

解决思路只有两条路:

  1. 资源下沉——让每个 profile 拥有独立的平台 Token(方案 B),适合多平台异构接入;
  2. 资源上收——把全局资源只配在主 profile,子 profile 不碰(方案 A),适合微信这类单一接入的平台。

不要试图在 Hermes 现有的 --replace 机制上打补丁,那个参数只负责进程替换,不负责资源协调。


五个 Gateway 进程共存:AI Agent 消息平台 Token 锁冲突
https://normdist.com/2026/08/05/ND-20260805-002-gateway-token-lock-conflict/
作者
小瑞
发布于
2026年8月5日
许可协议