消息平台接入概览:30+ 平台与 Gateway
本教程共 25 篇 · 第 14 篇 · 更新于 2026-07-26 · 约 14 分钟阅读
14. 消息平台接入概览:30+ 平台与 Gateway
本节目标:搞清楚 Hermes Agent 的消息网关(Gateway)怎么运作—30+ 平台怎么同时接入、单一 Gateway 怎么统一承载、平台适配器怎么翻译消息、跨平台会话怎么隔离、DM Pairing 怎么配对用户、权限怎么分层、以及服务怎么管理。学完你能在脑子里画出 Gateway 的完整架构图。
一个 Agent,多个入口
CLI 是你和 Agent 一对一聊天。但现实场景里,你想在 Telegram 上用、在 Discord 上用、在企业微信上用—而且用的是同一个 Agent,带着同一套记忆和技能。
Hermes Agent 当前最新稳定版 v2026.7.20 支持通过单一网关(Gateway)同时接入 30+ 消息平台。核心循环一行没变,变的只是消息从哪来、回复往哪送。
30+ 平台清单与能力对比
Hermes Gateway 支持的平台覆盖主流即时通讯、协作工具和自动化渠道:
| 平台 | 语音 | 图片 | 文件 | 话题 | 表情 | 输入指示 | 流式 |
|---|---|---|---|---|---|---|---|
| Telegram | ✅ | ✅ | ✅ | ✅ | - | ✅ | ✅ |
| Discord | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Slack | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| - | ✅ | ✅ | - | - | ✅ | ✅ | |
| Signal | - | ✅ | ✅ | - | - | ✅ | ✅ |
| Feishu/Lark | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| WeCom | ✅ | ✅ | ✅ | - | - | - | - |
| Weixin | ✅ | ✅ | ✅ | - | - | ✅ | ✅ |
| DingTalk | - | ✅ | ✅ | - | ✅ | - | ✅ |
| Matrix | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Mattermost | ✅ | ✅ | ✅ | ✅ | - | ✅ | ✅ |
| Microsoft Teams | - | ✅ | - | ✅ | - | ✅ | - |
| ✅ | ✅ | ✅ | - | - | ✅ | - | |
| Yuanbao | ✅ | ✅ | ✅ | - | - | ✅ | ✅ |
| LINE | - | ✅ | ✅ | - | - | ✅ | - |
| SMS | - | - | - | - | - | - | - |
| - | ✅ | ✅ | ✅ | - | - | - | |
| IRC | - | - | - | - | - | - | - |
| ntfy | - | - | - | - | - | - | - |
| Raft | - | - | - | - | - | - | - |
Note语音 = TTS 音频回复和/或语音消息转写。图片 = 发送/接收图片。文件 = 发送/接收文件附件。话题 = 线程化对话。表情 = 消息表情回应。输入指示 = 处理时显示”正在输入”。流式 = 通过消息编辑实现渐进式更新。
每个平台都有自己的工具集(Toolset),能力配置基本一致:文件、终端、网页、浏览器、记忆、技能、视觉、图片生成、待办、委托、代码执行、定时任务、会话检索等。
单一 Gateway 统一承载
架构全景
Gateway 是一个后台进程,同时连接所有已配置的平台,处理会话、运行定时任务、投递语音消息:
Gateway
|
+-- 平台适配器层
| |-- Telegram Adapter
| |-- Discord Adapter
| |-- WhatsApp Adapter
| |-- Slack Adapter
| |-- ... (30+ 平台)
|
+-- 会话存储 (Session Store)
| |-- 每个聊天独立的会话历史
|
+-- AI Agent (核心循环)
| |-- agent.run_conversation()
|
+-- Cron 调度器
|-- 每 60 秒检查一次到期任务
每个平台适配器接收消息,通过按聊天隔离的会话存储路由,分发给 AI Agent 处理。Gateway 同时运行 Cron 调度器,每 60 秒检查一次到期任务。
核心设计:平台适配器
每个平台适配器做两件事:
- 入站:收到平台消息 -> 翻译成统一格式
MessageEvent - 出站:拿到回复文本 -> 翻译成平台格式发出去
# 统一消息格式
MessageEvent(
message_id="msg_001",
text="帮我查一下今天的天气",
source=SessionSource(
platform="wecom", # 哪个平台
chat_id="zhangsan", # 聊天标识
chat_type="dm", # 私聊 or 群聊
user_id="zhangsan", # 发消息的人
),
message_type="text",
)
不管微信还是 Telegram,翻译完都是同一个 MessageEvent。下游代码不需要知道消息来自哪个平台。加一个新平台,只需要写一个新的适配器,核心循环一行都不用改。
Tip这个设计的关键洞察:核心循环(
agent.run_conversation())不知道消息从哪来。不管微信还是 Telegram 还是 CLI,调用方式完全一样。Gateway 和 CLI 的区别只在入口和出口,核心循环完全一样。
适配器处理的共性问题
每个适配器都要处理几个跟平台无关的共性问题:
| 问题 | 解决方案 |
|---|---|
| 消息分片 | 平台在 4000 字符处自动截断长文本。适配器用时间窗口合并:接近截断阈值等 2 秒,否则等 0.6 秒 |
| 消息去重 | 网络不稳定时同一条消息可能推两次。适配器按 message_id 去重 |
| 媒体缓存 | 平台提供的媒体 URL 是临时的。收到图片/语音时立刻下载到本地缓存 |
| 断线重连 | WebSocket 断了用指数退避重连(2s -> 5s -> 10s -> 30s -> 60s) |
| 心跳保活 | 企业微信要求每 30 秒发一次心跳,否则服务器断开连接 |
跨平台会话隔离
Session Key:每个对话独立
如果张三和李四同时在 Telegram 上跟 Agent 聊天,他们的消息不能混在一起。需要一个标识符来区分不同的对话。
Hermes 用 session key 做隔离:
# 私聊:平台 + 聊天类型 + 用户 ID
"agent:main:telegram:dm:123456789"
# 群聊:平台 + 聊天类型 + 群 ID + 用户 ID(群内按人隔离)
"agent:main:telegram:group:grp_001:123456789"
"agent:main:telegram:group:grp_001:987654321"
张三和李四在同一个群里,但 session key 不同,所以各自有独立的对话历史。同一个群里不同用户的对话互不干扰。
会话持久化
会话跨消息持久化,直到你手动重置。Agent 记住你的对话上下文。
默认情况下会话永不自动重置。如果需要自动重置:
# 文件路径:~/.hermes/config.yaml
session_reset:
mode: idle # idle | daily | both | none(默认)
idle_minutes: 1440 # idle/both 模式:不活动多少分钟后重置
at_hour: 4 # daily/both 模式:每天几点重置(0-23)
| 模式 | 说明 |
|---|---|
none | 永不自动重置(默认) |
daily | 每天指定时间重置 |
idle | 不活动 N 分钟后重置 |
both | 哪个先触发就按哪个来 |
可以按平台单独配置重置策略:
// 文件路径:~/.hermes/gateway.json
{
"reset_by_platform": {
"telegram": { "mode": "idle", "idle_minutes": 240 },
"discord": { "mode": "idle", "idle_minutes": 60 }
}
}
投递可靠性
Agent 的最终回复记录在持久化的投递账本(delivery ledger,存在 state.db)中。如果 Gateway 在生成回复和平台确认接收之间崩溃或重启,下次启动时会重新投递存储的回复,而不是丢失它或重新跑一遍。
语义是诚实的至少一次投递:
- 发送从未开始的回复:原样重新投递
- 发送中途崩溃的回复(平台可能收到也可能没收到):重新投递时带可见的”♻️ Recovered reply - … may be a duplicate”前缀
- 重新投递有限制:最多 3 次,24 小时内有效
DM Pairing:配对替代白名单
默认安全:拒绝所有未授权用户
默认情况下,Gateway 拒绝所有不在白名单中的用户。这对一个有终端访问权限的 Bot 来说是安全的默认值:
# 限制特定用户(推荐)
TELEGRAM_ALLOWED_USERS=123456789,987654321
DISCORD_ALLOWED_USERS=123456789012345678
FEISHU_ALLOWED_USERS=ou_xxxxxxxx,ou_yyyyyyyy
# 或统一配置
GATEWAY_ALLOWED_USERS=123456789,987654321
# 或显式允许所有用户(不推荐有终端访问的 Bot 使用)
GATEWAY_ALLOW_ALL_USERS=true
配对流程
除了手动配置用户 ID,还可以用 DM 配对(DM Pairing)。未知用户给 Bot 发私信时会收到一个一次性配对码,你在本地批准:
# 用户看到:"Pairing code: XKGH5N7P"
# 你批准:
hermes pairing approve telegram XKGH5N7P
# 其他配对命令
hermes pairing list # 查看待处理 + 已批准用户
hermes pairing revoke telegram 123456789 # 撤销访问
配对码 1 小时后过期,有速率限制,使用加密随机性生成。
NoteEmail 是例外:未知邮件发送者会被忽略,除非显式启用 email 配对。
管理员与普通用户权限分层
白名单回答”这个人能不能联系到 Bot”。管理员/普通用户分层回答”既然联系到了,能做什么?”
每个允许的用户属于两个层级之一(按范围分:私信 vs 群/频道):
| 层级 | 权限 |
|---|---|
| Admin | 完全访问。可以运行每个注册的斜杠命令,使用每个受控能力 |
| Regular user | 受限访问。可以正常聊天,但只能运行你显式启用的斜杠命令。始终允许的最低限度是 /help 和 /whoami |
配置示例:
# 文件路径:~/.hermes/config.yaml
gateway:
platforms:
discord:
extra:
allow_from: ["111", "222", "333"]
allow_admin_from: ["111"] # 管理员 -> 所有斜杠命令
user_allowed_commands: [status, model] # 非管理员可运行的命令
# 可选:群/频道范围的单独配置
group_allow_admin_from: ["111"]
group_user_allowed_commands: [status]
用 /whoami 可以从任何平台查看你的活跃范围、层级(admin/user/unrestricted)和可运行的斜杠命令。
聊天内命令
在任何消息平台中,你都可以使用斜杠命令:
| 命令 | 说明 |
|---|---|
/new 或 /reset | 开始新对话 |
/model [provider:model] | 查看或切换模型 |
/retry | 重试上一条消息 |
/undo | 撤销上一轮对话 |
/status | 显示会话信息 |
/stop | 停止正在运行的 Agent |
/approve | 批准待审批的危险命令 |
/deny | 拒绝待审批的危险命令 |
/compress | 手动压缩对话上下文 |
/title [name] | 设置或显示会话标题 |
/resume [name] | 恢复之前命名的会话 |
/usage | 显示本次会话的 Token 用量 |
/background <prompt> | 在独立后台会话中运行 |
/voice [on|off|tts] | 控制语音回复 |
/rollback [number] | 列出或恢复文件系统检查点(Checkpoint) |
/<skill-name> | 调用任何已安装的技能 |
忙碌输入模式:Agent 正在思考时你发消息怎么办
当 Agent 正在处理消息时你发了新消息,有三种处理模式:
| 模式 | 行为 |
|---|---|
interrupt(默认) | 重定向当前轮次。模型生成带着上下文重新开始,已完成的工作保留,运行中的工具安全完成 |
queue | 后续消息排队等待,当前任务完成后作为下一轮运行 |
steer | 后续消息注入当前运行(通过 /steer),在下一个工具调用后到达 Agent。不中断,不新开轮次 |
# 文件路径:~/.hermes/config.yaml
display:
busy_input_mode: steer # 或 queue,或 interrupt(默认)
busy_ack_enabled: true # 设为 false 可隐藏 ⚡/⏳/⏩ 确认消息
Tip
steer模式特别适合”补充说明”场景。你发了”帮我写排序算法”,Agent 开始思考,你马上补一句”用 Python 写”—steer 模式会把这句话注入当前运行,Agent 在下一个工具调用后就会看到补充信息,不需要中断重来。
中断不是强制杀进程
中断信号做的具体事情是设置 _interrupt_requested = True 标志位。Agent 在多个检查点检查这个标志:
- 正在等 LLM 回复流 -> 立刻停止读取
- 正在执行多个工具调用 -> 跳过剩余的
- 主循环每轮开始时检查 -> 退出循环
中断后的内容不会丢。已生成的部分回复、已执行的工具调用和结果、被跳过的工具调用都会保存。下一轮处理新消息时,Agent 看得到自己被打断的痕迹,能合理衔接。
语音转写
部分平台支持语音功能,包括:
- TTS 音频回复:Agent 的文字回复可以转成语音消息发送
- 语音消息转写:你发的语音消息自动转成文字交给 Agent 处理
- Discord 语音频道:可以在 Discord 语音频道中与 Agent 对话
在消息平台中用 /voice 命令控制:
/voice on # 开启语音回复
/voice off # 关闭语音回复
/voice status # 查看语音状态
多平台运维
/platform 命令
Gateway 运行后,用 /platform 命令检查和控制单个适配器,不需要重启整个 Gateway:
/platform list # 显示所有适配器及其状态
/platform pause <name> # 暂停某个适配器(不再处理新消息)
/platform resume <name> # 恢复已暂停的适配器
自动熔断器
每个适配器都包在熔断器(circuit breaker)中。连续可重试的失败(网络闪断、速率限制、5xx 错误、WebSocket 断开)会触发熔断—适配器自动暂停,发送操作通知到其他活跃平台的 home channel。
熔断器不会自动恢复—保持打开状态直到你手动运行 /platform resume <name>。这是有意设计:如果平台持续故障,你不希望 Gateway 疯狂重连。
重启通知
Gateway 重启时(或有在途会话时被关闭),可以给每个平台的 home channel 发送一次性”Agent 回来了”/“Agent 被中断了”消息:
# 文件路径:~/.hermes/config.yaml
gateway:
platforms:
telegram:
home_chat_id: "123456789"
gateway_restart_notification: false # 此平台不发通知
discord:
home_chat_id: "987654321"
# 省略 -> 默认 true
Gateway 服务管理
快速设置
最简单的配置方式是交互式向导:
hermes gateway setup # 交互式配置所有消息平台
向导带你用方向键选择配置每个平台,显示哪些平台已配置,完成后提供启动/重启 Gateway 的选项。
常用命令
hermes gateway # 前台运行
hermes gateway setup # 交互式配置
hermes gateway install # 安装为用户服务
hermes gateway start # 启动服务
hermes gateway stop # 停止服务
hermes gateway status # 检查服务状态
Linux(systemd)
# 安装为用户服务
hermes gateway install
# 启用 lingering(注销后继续运行)
sudo loginctl enable-linger $USER
# 或安装为系统服务(开机自启)
sudo hermes gateway install --system
# 查看日志
journalctl --user -u hermes-gateway -f
Tip无头 VM 推荐用用户服务 + lingering,避免每次重启都需要 root 权限。
hermes update自动重启 Gateway 时也不需要 sudo。
macOS(launchd)
hermes gateway install # 安装为 launchd agent
hermes gateway start # 启动
hermes gateway stop # 停止
hermes gateway status # 检查状态
tail -f ~/.hermes/logs/gateway.log # 查看日志
生成的 plist 在 ~/Library/LaunchAgents/ai.hermes.gateway.plist,包含 PATH、VIRTUAL_ENV 和 HERMES_HOME 三个环境变量。
Warning如果安装 Gateway 后又装了新工具(比如通过 nvm 装了新 Node.js 版本,或通过 Homebrew 装了 ffmpeg),需要重新运行
hermes gateway install来捕获更新后的 PATH。launchd plist 是静态的,不会自动更新。
多安装隔离
如果你在同一台机器上运行多个 Hermes 安装(不同的 HERMES_HOME 目录),每个安装有自己的服务名。默认 ~/.hermes 用 hermes-gateway;其他安装用 hermes-gateway-<hash>。hermes gateway 命令自动定位当前 HERMES_HOME 对应的服务。
有意静默
在群聊、Hook 和自动化流程中,Hermes 支持显式静默 token。如果 Agent 的最终回复恰好是某个支持的 token,Gateway 不向外投递,什么都不发:
支持的 token:[SILENT]、SILENT、NO_REPLY、NO REPLY
空白和大小写会被标准化,但整个最终回复必须是这个 token。像”Use [SILENT] when nothing changed”这样的句子会正常投递。
静默只是投递决策。Hermes 在会话记录中保留这个静默轮次,所以对话仍然正常交替。失败的轮次仍然会报错—Hermes 不会因为文本碰巧像静默 token 就隐藏失败。