系列第五篇。本文解析 Hermes 消息网关的架构哲学:职责分离的边界为什么画在这里,COMMAND_REGISTRY 单一真相源如何在实践中运作,以及双重消息守卫保护的是哪种具体的竞态场景。


引子:平台差异是污染源

Hermes 支持的消息平台清单读起来像一份当代通讯软件市场调研:Telegram、Discord、Slack、WhatsApp、Signal、Matrix、Mattermost、Email、SMS、钉钉、企业微信、微信、飞书、QQ机器人,以及更多。

每个平台的技术特性都不同:

如果 Agent 的业务逻辑直接调用各平台的 API,会发生什么?每个平台的一次 API 变更都需要修改 Agent 核心代码。当你想为 Telegram 和 Discord 同时添加一个"AI 回复中请稍候"的打字指示器时,需要在两处写相似但不完全相同的逻辑——迟早会产生行为偏差。

Hermes 网关层的核心价值不在于"它支持多少平台",而在于它建立了一道隔离边界:平台适配的任何变化都不会传染到 Agent 逻辑,Agent 逻辑的任何变化也不需要各平台适配器知情。


职责分离:边界为什么画在这里

网关层的职责被明确分成三层:

平台适配层(gateway/platforms/<name>.py):处理平台特定的连接、认证、消息格式转换。将平台原生事件统一转换为 MessageEvent 对象,将 AIAgent 的输出转换为平台原生的发送调用。

会话路由层(gateway/session.py 中的 SessionStore):根据消息来源确定这条消息属于哪个会话,决定是创建新会话还是继续已有会话,管理会话的生命周期(超时、重置、挂起)。

业务逻辑层(gateway/run.py 中的 GatewayRunner,以及 run_agent.py 中的 AIAgent):解释斜杠命令、调用工具、管理上下文、返回回复。

关键问题是:为什么会话路由逻辑不放在各平台适配器里?

考虑一个具体场景:Telegram 和 Discord 都需要支持"同一个频道里的不同线程/话题各有独立的 AI 会话"这个功能。