DeepAI Paper Hermes Agent 教程,Hermes Gateway 与消息平台 Matrix 机器人能登录却不回消息?Hermes Agent 静默收不到新消息的排查思路

Matrix 机器人能登录却不回消息?Hermes Agent 静默收不到新消息的排查思路

> 问题本质:这不是“模型没响应”,也不只是 Matrix 密码、Access Token 或日志级别的问题。Hermes Agent 在 Matrix 网关中已经完成登录和同步,但 matrix-nio 拿到 SyncResponse 后没有正确进入事件分发链路,导致新消息不会触发回调;同时设备 ID、登录凭证应用、启动阶段时间判断等问题会叠加成“看起来在线,实际完全听不见”的静默故障。

如果你在部署 Hermes Agent 的 Matrix bot 时遇到这种现象:机器人能登录、能接受房间邀请、启动时能同步旧消息,但你发新消息后没有任何回复,终端也没有日志,那么这篇排查会很有参考价值。

这类故障最容易被误判成三件事:

  • LLM API 没配置好;
  • Matrix 权限、白名单或 mention 设置错了;
  • 日志没有打到 stdout / stderr。

但在 NousResearch/hermes-agent 的一次真实修复讨论中,最终根因比这些更底层:Matrix 客户端同步到了数据,却没有把响应交给 matrix-nio 的事件处理器继续分发。

适合搜索的症状关键词

如果你正在搜索类似问题,可以对照这些长尾关键词:

  • Hermes Agent Matrix bot 不回复新消息;
  • Matrix 机器人能登录但收不到消息;
  • matrix-nio sync 有数据但 callback 不触发;
  • Hermes gateway LOG_LEVEL=DEBUG 没有输出;
  • Matrix bot 每次重启生成新 device;
  • Hermes Matrix unencrypted room works / encrypted DM not working;
  • Matrix Access Token 和 password login 都静默失败。

典型现象:在线、同步、接受邀请,但就是不处理新消息

这个问题来自 Hermes Agent 的一个已关闭修复讨论。用户在 matrix.org 上创建 bot 账号,用 Hermes Gateway 连接 Matrix,配置大致包括:

  • MATRIX_PASSWORD 密码登录;
  • MATRIX_ALLOWED_USERS 白名单;
  • MATRIX_REQUIRE_MENTION=false
  • MATRIX_AUTO_THREAD=false
  • LOG_LEVEL=DEBUG
  • 清空 ~/.hermes/matrix/ 后重新启动。

启动后表面上看一切都正常:

  • bot 可以认证成功;
  • bot 会自动接受房间邀请;
  • 启动时能同步旧消息;
  • E2EE 房间里还能看到旧消息解密失败的 Megolm warning;
  • 进程没有崩溃。

但问题是:新建一个未加密房间,给 bot 发送 Hello/sethome,Hermes Gateway 没有任何输出,也不触发回复。即使 LOG_LEVEL=DEBUG,终端依然空白。

这就是最麻烦的“静默失败”:没有 HTTP 500,没有 traceback,没有权限拒绝提示,只有一个在线但失聪的机器人。

第一层误区:不要只盯着模型 API

很多人看到 bot 不回复,会第一时间检查 OpenAI、Claude、DeepAI、OpenRouter 等模型配置。但 Matrix 网关类问题要先分层:

层级要确认的问题典型信号
Matrix 登录层bot 是否成功登录 Matrix homeserver有 login success、device、sync 请求
Matrix 同步层sync() 是否持续收到数据strace / debug 中能看到网络读写
事件分发层新消息是否触发 _on_room_messagecallback 日志是否出现
Hermes 调度层message handler 是否 setdispatch 日志是否显示 handler=set
模型调用层LLM provider 是否正常进入 agent pipeline 后才看 API 报错

如果 _on_room_message 都没触发,问题还没走到模型层。此时无论你换 Claude、OpenAI-compatible API、DeepAI 中转站还是本地模型,都不会让机器人突然听见消息。

真正关键:sync() 只拿数据,不等于事件已经分发

Matrix Python 客户端 matrix-nio 的一个核心点是:sync() 返回 SyncResponse,但这不自动等于你注册的事件回调已经执行。

在这个修复中,关键缺失是:

resp = await self._client.sync(timeout=30000)
if isinstance(resp, nio.SyncResponse):
    await self._client.receive_response(resp)

没有 receive_response(resp) 时,客户端可能已经从 homeserver 收到数据,但事件不会进入已注册的 callbacks。于是你会看到一种很诡异的状态:

  • 网络连接正常;
  • Matrix sync 正常;
  • 进程有活动;
  • _on_room_message 完全不触发;
  • Hermes 看起来“在线但失聪”。

这也是为什么用户用 strace 能看到 TLS 流量、文件描述符写入、状态文件更新,却看不到 stdout / stderr 输出。问题不是简单日志重定向,而是事件没有进入应用层处理链路。

第二个坑:密码登录后凭证没有应用到客户端

这个案例里还有一个容易被忽略的身份问题:使用 MATRIX_PASSWORD 登录时,client.login() 返回的 LoginResponse 不能丢掉。

修复思路是把登录响应中的关键字段应用到 AsyncClient

if isinstance(resp, nio.LoginResponse):
    if getattr(resp, "user_id", ""):
        self._user_id = resp.user_id
        client.user_id = resp.user_id
    if getattr(resp, "device_id", ""):
        client.device_id = resp.device_id
    if getattr(resp, "access_token", ""):
        client.access_token = resp.access_token

否则,password login 表面成功,但后续同步可能处在一种身份不完整的状态。Access Token 路径通常会通过 restore_login() 处理这些字段,而 password 路径如果漏掉,就会出现“已登录但后续行为异常”。

第三个坑:每次重启都生成新 Matrix device

用户还观察到另一个症状:每次重启 Hermes Gateway,Matrix 账号里都会多一个新的 device session。

这通常说明 device id 没有稳定复用。短期 workaround 是在 .env 中设置固定设备 ID:

MATRIX_DEVICE_ID=HermesBot

更完整的修复是:从 LoginResponse 中持久化并复用 device_id,不要每次启动都让 matrix-nio 创建新的设备身份。

设备泛滥不一定直接导致“新消息不触发”,但它会让 E2EE、会话管理、密钥同步和排错难度一起变糟。Matrix bot 一旦涉及加密房间,稳定 device id 更重要。

第四个坑:启动宽限期不能只靠本地时间戳硬比对

这个修复里还有一个细节:原先的启动 grace period 使用时间戳判断新旧消息。如果本地系统时间和 Matrix homeserver 事件时间存在偏差,刚发的新消息可能被误判为 stale message,然后被丢掉。

更稳的方式是用状态标记:

  • 初始同步完成前的历史消息忽略;
  • 初始同步完成后收到的新消息全部进入处理流程。

也就是用类似 _initial_sync_done 的标志替代脆弱的时间戳比较。

这类逻辑对聊天机器人非常关键。因为“启动时不要回复历史消息”是合理需求,但如果实现得太粗糙,就会把真实新消息也吞掉。

推荐排查流程:先证明消息有没有进入回调

遇到 Hermes Matrix bot 静默不回复,可以按这个顺序查:

1. 确认 Matrix 平台是否真的启动

查看 Hermes Gateway 日志文件,而不仅是终端:

ls ~/.hermes/logs/
tail -n 200 ~/.hermes/logs/gateway.log

有些场景下日志可能写入文件描述符或 log file,而不是直接出现在当前终端。

2. 打开 DEBUG 和 asyncio debug

PYTHONASYNCIODEBUG=1 LOG_LEVEL=DEBUG hermes gateway

重点看:

  • initial sync 是否完成;
  • sync loop 是否继续运行;
  • 发送新消息后是否出现 Matrix event;
  • _on_room_message 是否被调用;
  • handler 是 set 还是 not set。

3. 区分“收不到消息”和“收到但不回复”

这是核心分界线:

现象更可能的问题
_on_room_message 不触发Matrix sync / receive_response / callback 分发
_on_room_message 触发但不 dispatchhandler 未设置、白名单、mention、room 规则
dispatch 后不回复LLM provider、API key、模型、上下文、工具调用
未加密房间正常,加密 DM 不正常Matrix E2EE / Megolm / device trust / key exchange

不要在 callback 没触发前就去换模型 API。那是在修水龙头之前换杯子。

4. 固定 Matrix device id

MATRIX_DEVICE_ID=HermesBot

然后清理旧 session,重新登录测试。这样至少能避免每次重启都创建新 device,减少变量。

5. 用未加密房间做最小复现

Matrix E2EE 会引入 Megolm session、device verification、key sharing 等额外复杂度。排查主链路时,先用:

  • 新建未加密房间;
  • 只邀请 bot 和测试用户;
  • MATRIX_REQUIRE_MENTION=false
  • 发简单文本 /sethomehello

未加密房间打通后,再单独处理 encrypted DM。

对开发者的启发:消息平台适配器要有“分层可观测性”

这个案例的价值不只是 Hermes Matrix 修了一个 bug,而是提醒所有 AI Agent 网关开发者:聊天平台适配器必须能分层观测。

至少要能看到:

  • 登录成功;
  • 初始同步完成;
  • sync loop 每轮状态;
  • 收到原始事件类型;
  • 是否进入消息回调;
  • 是否通过 allowlist / mention 过滤;
  • 是否 dispatch 到 agent handler;
  • 是否进入 LLM 请求;
  • 是否成功 send message。

否则用户只会得到一个“没反应”,而“没反应”可能横跨网络、认证、事件分发、过滤规则、LLM、发送权限六七层。

和 DeepAI API 中转站有什么关系?

这篇问题本身发生在 Matrix Gateway 层,不是 DeepAI、OpenAI 或 Claude 模型层的问题。所以不能说换成 DeepAI 就能修好 Matrix callback。

但在真实部署 AI Agent 时,DeepAI API 中转站适合放在更后面的模型调用层:

  • 当 Matrix / Telegram / Discord 等消息平台已经能正常触发回调;
  • Hermes 已经进入 LLM provider 请求阶段;
  • 你希望统一管理 OpenAI Compatible API 的 Base URL、API Key、模型名和账单;
  • 或者你在 Cherry Studio、Cline、Dify、Open WebUI 等支持 OpenAI Compatible API 的工具里复用同一套模型接入方式。

换句话说:

  • 消息进不来:先修 Gateway / Matrix / callback;
  • 消息进来了但模型报错:再看 API Key、Base URL、模型能力和 DeepAI 中转配置。

这种分层思路也能减少很多无效折腾。

最后结论

Hermes Matrix bot “能登录但不回复新消息”的本质,不是一个简单的配置项问题,而是一组 Matrix 网关事件链路问题叠加:

  • password login 后需要把 access_tokendevice_iduser_id 应用到 client;
  • device id 需要稳定复用,避免每次重启制造新 session;
  • sync() 返回 SyncResponse 后必须调用 receive_response(resp) 才能触发事件回调;
  • initial sync 期间的历史消息过滤,最好用完成标志而不是脆弱的时间戳硬比较;
  • 未加密房间和 E2EE 房间要分开排查。

如果你遇到“Hermes 在线但 Matrix 新消息完全没日志”的情况,优先检查事件分发链路,而不是先怀疑模型 API。只有当 _on_room_message、dispatch、handler 都确认正常之后,DeepAI / OpenAI-compatible / Claude / OpenRouter 这些模型层排查才真正有意义。

FAQ

Hermes Matrix bot 能同步旧消息,但为什么不处理新消息?

可能是 Matrix sync 拿到了数据,但没有调用 receive_response(resp),导致 matrix-nio 没有把 SyncResponse 分发给注册的事件回调。

LOG_LEVEL=DEBUG 没输出是不是日志坏了?

不一定。可能日志写到了 ~/.hermes/logs/gateway.log,也可能事件根本没进入回调。先查日志文件,再确认 _on_room_message 是否触发。

设置 MATRIX_DEVICE_ID 有什么用?

它能让 Matrix bot 重启时复用同一个 device,避免每次登录创建新设备。对 session 稳定性和 E2EE 排查都很重要。

Access Token 登录也不工作,说明不是 password login 的问题吗?

不完全是。这个案例里 password login 凭证应用是一个问题,但更关键的是 sync response 没有进入事件分发。Access Token 也可能受后者影响。

DeepAI API 中转站能解决 Matrix bot 不回消息吗?

不能直接解决。Matrix bot 不回消息如果发生在 Gateway 事件层,需要先修 Matrix 接入。DeepAI 更适合在消息已经进入 LLM 调用阶段后,用来统一 OpenAI Compatible API 的模型接入与 Key 管理。

Related Post

DeepSeek Anthropic-compatible API 第二轮 HTTP 400:为什么 thinking blocks 不能被一刀切剥掉?DeepSeek Anthropic-compatible API 第二轮 HTTP 400:为什么 thinking blocks 不能被一刀切剥掉?

Hermes 使用 DeepSeek Anthropic-compatible Messages API 且启用 reasoning_effort 时,多轮会话第二轮可能报 HTTP 400:content[].thinking must be passed back。本文客观复盘 #22313:convert_messages_to_anthropic 如何剥掉 thinking blocks,为什么 DeepSeek/Kimi 需要保留 unsigned thinking,以及 provider-aware adapter 的修复方向。

GPT-5 模型报 unsupported_api_for_model?Hermes Agent 自动切换 Responses API 的排错指南GPT-5 模型报 unsupported_api_for_model?Hermes Agent 自动切换 Responses API 的排错指南

Hermes Agent 使用 GPT-5.4、Copilot 或 OpenRouter 时,如果请求漂移到 /chat/completions 并报 unsupported_api_for_model,核心往往不是模型不可用,而是 GPT-5.x 必须走 Responses API / codex_responses。本文解释 provider fallback、api_mode、gateway 缓存和 OpenAI-compatible API 的正确排查顺序。

OpenAI-compatible API 报 unsupported_parameter:max_tokens 和 max_completion_tokens 为什么不能只看 Base URL?OpenAI-compatible API 报 unsupported_parameter:max_tokens 和 max_completion_tokens 为什么不能只看 Base URL?

自定义 OpenAI-compatible Base URL 调用 gpt-4o、gpt-4.1、gpt-5 或 o-series 模型时,为什么会报 Unsupported parameter: max_tokens?本文复盘 Hermes Agent #13901,解释 max_tokens / max_completion_tokens 不能只按 host 判断,而应按模型族和后端能力适配,并自然引导到 DeepAI API 中转站的统一接入场景。