使用Hermes 排查OpenClaw 从 5.12 升级到 6.10 的故障

使用Hermes 排查OpenClaw 从 5.12 升级到 6.10 的故障 半年前用 OpenClaw 搭了一套多 Agent 协作系统跑在 Ubuntu 虚拟机里接飞书做消息通道算是半个生产环境。最近抽空从 2026.5.12 升到 2026.6.10升级完满怀期待地测试结果发现「龙虾」不吭声了——飞书里发消息过去已读不回。打开openclaw 报了一些故障翻配置文件、查网络连接、看 API Key折腾了半天最终发现问题不在配置不在网络也不在 API Key而是升级中的一个陷阱核心版本升了插件版本没跟着升。这篇文章复盘了完整的排查和修复过程包括诊断命令、数据库查询、修复步骤以及 OpenClaw 和 Hermes 两个网关的架构关系。老规矩先看效果升级前给飞书里的「龙虾」发消息WebSocket 连接正常日志能看到received message但就是不回复。查数据库入站事件表的 count 是 0——消息到了 WebSocket 层但没进入处理管线。升级修复后发什么回什么一切正常。整个修复涉及四个层面逐一排查定位下面展开来讲。系统环境交代这台 Ubuntu 24.04 虚拟机上跑着两套 AI 网关系统。一套是 Hermes AgentPython 后端系统级服务负责日常的飞书对话。另一套是 OpenClawNode.js 后端手动启动跑着五个 Agent 的多角色协作体系——龙虾主 Agent、投资专家、财务总监、技术总监、市场总监。两套系统共用~/.hermes/目录作为 HOME 路径但各自的配置、状态库、插件是独立的。维度HermesOpenClaw配置文件~/.hermes/config.yaml~/.openclaw/openclaw.json状态数据库~/.hermes/state.db(114MB)~/.openclaw/state/openclaw.sqlite(6MB)飞书 App IDcli_aa9b...cli_aa816...插件管理Python 内置 50 插件Node.js npm 独立安装飞书连接方式WebSocket系统服务WebSocket手动启动关键点两套系统用的飞书 App ID 不同是两条完全独立的 WebSocket 连接。不存在「一个端口被抢了另一个连不上」的情况。升级方式很简单npm update -g openclaw把核心从 2026.5.12 拉到了 2026.6.10。启动 gateway 就开始报 warning。第一个警告deepseek 插件缺失升级后首次启动openclaw gateway --port 18789 --verbose终端出现 Config warningsplugins.entries.deepseek: plugin not installed: deepseek原因是在 6.10 版本里deepseek provider 从内置变成了外部插件需要单独安装。配置文件里还写着plugins.entries.deepseek.enabled: true但实际的 npm 包不存在。另外还有 Doctor warningsLeft plugin install index in place because shared SQLite state has conflicting plugin install metadata for: feishu。这是 OpenClaw 启动时读~/.hermes/state.dbHermes 的会话存档做迁移检查发现 Hermes 内置的 feishu 和 OpenClaw npm 安装的 feishu 元数据冲突选择保留不动。不影响任何功能先放一边。执行openclaw plugins install openclaw/deepseek-provider。npm 安装openclaw/deepseek-provider2026.6.10到~/.openclaw/npm/projects/。重启 gatewaydeepseek 警告消失。但龙虾还是不回消息。第二个警告API Key 没存进去查openclaw.jsonauth.profiles里定义了deepseek:default模式api_key。框架有了但去查 agent 工作区的auth-profiles.json——profiles字段是空的。这里有个容易忽略的点openclaw.json里的auth.profiles只定义元数据provider 类型、auth 模式真正的 API Key 需要存在 agent 的凭证存储里。如果只改了配置文件没存 Keyagent 调 DeepSeek API 时会因为没有凭证而静默失败——SDK 吞掉了这个异常日志里看不到任何 API 调用错误。通过管道把 Hermes 那边已在用的 Key 存进去openclaw models auth paste-api-key --provider deepseek执行后openclaw models auth list显示deepseek:default [deepseek/api_key]。重启龙虾还是没反应。深入数据库发现了真正的根因前两步修的都是「启动时能看到的」问题但龙虾不响应的根因还没找到。开始做数据层诊断。查 OpenClaw 的 SQLite 状态库~/.openclaw/state/openclaw.sqlite三个关键发现channel_ingress_events的 count 是 0。从启动到现在一条入站事件都没收到。但 WebSocket 连接正常openclaw channels status显示 main agent runningTCP 连接也在。delivery_queue_entries里 17 条记录全部 failed。错误有两类Feishu account default not configured和card table number over limit飞书卡片表格数超限错误码 11310。时间戳都是 6 月 13 日的旧数据。current_conversation_bindings是空的。没有任何飞书会话被绑定到 agent。消息到了 WebSocket 但没进数据库——问题出在 WebSocket 和数据库之间的消息路由环节。关键发现feishu 插件版本不匹配查~/.openclaw/npm/node_modules/openclaw/feishu/package.jsonversion 字段是2026.5.12。OpenClaw 核心 2026.6.10feishu 插件 2026.5.12——差了将近一个月的版本。这就是根因。npm update -g openclaw只升级了核心包不会自动升级通过openclaw plugins install单独安装的外部插件。feishu 是外部 npm 包有自己的版本管理不在 bundled extensions 里。新版核心的 channel adapter 接口变了消息对象的解析方式也变了。旧版 feishu 插件收到 WebSocket 数据后还是用 5.12 的格式解析传给核心后路由失败消息被静默丢弃。这也解释了日志的矛盾received message是 feishu 插件自己的 WebSocket 层打的——它代表「WebSocket 收到了原始字节并解析成了消息对象」。但这个消息对象传给核心的 channel adapter 时因为格式不兼容被丢弃了所以 channel_ingress_events 始终是 0。执行升级openclaw plugins install openclaw/feishuinstall 命令检测到旧版自动卸载~/.openclaw/npm/node_modules/openclaw/feishu5.12 路径安装新版到~/.openclaw/npm/projects/。验证feishu plugin: v2026.6.10与核心版本一致。模型切换顺手把模型从 flash 切到 proopenclaw models set deepseek/deepseek-v4-pro四步修复全部完成。重启 gateway给龙虾发「你是什么模型」秒回。修复命令汇总整个修复用了四条命令更新 deepseek 提供者插件解决plugin not installed警告openclaw plugins install openclaw/deepseek-provider将 DeepSeek API Key 存入 agent 凭证存储。Key 从 Hermes 的环境变量获取通过管道输入openclaw models auth paste-api-key --provider deepseek升级 feishu 通道插件到与核心一致的版本这是最关键的一步——新旧接口不兼容导致消息路由失败openclaw plugins install openclaw/feishu切换默认模型到 Proflash 和 pro 可随时切换openclaw models set deepseek/deepseek-v4-pro每次切换模型或升级插件后需要重启 gateway。SQLite 诊断速查排查过程中用到的核心 SQL 查询全是读操作不改数据入站事件总量——这是最高优先级的诊断指标。如果是 0问题一定在消息接收和路由环节SELECT COUNT(*) FROM channel_ingress_events;出站队列状态和失败原因——即使 agent 成功处理了消息如果回复发不出去问题就在这里SELECT id, status, channel, account_id, last_error FROM delivery_queue_entries ORDER BY enqueued_at DESC LIMIT 10;插件安装索引——查看所有插件的版本号和安装来源。升级后第一时间对比版本不一致的就是重点怀疑对象SELECT value_json FROM installed_plugin_index;Agent 凭证状态——确认 API Key 正确存储避免因为凭证缺失导致的静默失败SELECT * FROM auth_profile_state;一条COUNT(*) 0的信息量远大于「日志里没有错误」——日志可能因为代码根本没执行到而保持安静但数据库不会撒谎。state.db 的那些事排查过程中有一个持续出现的 warningLeft plugin install index in place because shared SQLite state has conflicting plugin install metadata for: feishu。这个 state.db 是 Hermes 的会话存档存了 103 个 session 和 6780 条消息带 FTS 全文搜索索引用于session_search功能。OpenClaw 启动时用它做迁移兼容检查发现 Hermes 内置 feishu 和 OpenClaw npm feishu 的安装记录冲突选择保留不动。用lsof验证OpenClaw 运行时根本不持有 state.db 的文件句柄。只在启动时读一次读完就关。两个网关真正的关系是独立配置、独立数据库、独立飞书 App、独立插件。state.db 的共享只是历史遗留的目录结构没有实际数据耦合不影响功能。为什么升级不自动更新插件这是这次升级踩坑的核心教训。OpenClaw 6.x 做了重大的插件架构调整——provider 和 channel 拆分成了独立的外部包。Bundled extensionsduckduckgo、searxng 等在dist/extensions/下随npm update -g openclaw自动更新。但通过openclaw plugins install单独安装的外部插件有自己独立的安装路径和版本管理。这导致了一个隐蔽的不一致状态核心 API 变了但外部插件还停在旧版本接口不兼容。轻则功能异常重则静默失败——消息被丢弃没有任何错误提示。升级后的检查清单基于这次经验以后版本升级的检查流程升级核心后立即用openclaw plugins list对比所有外部插件的版本号跟核心版本对齐用openclaw models auth list确认 API Key 还在——某些升级可能重置 auth state用openclaw doctor扫描所有 warning逐条分析SQL 查询 channel_ingress_events 和 delivery_queue_entries 确认消息收发正常发一条测试消息验证端到端流程关于飞书卡片消息的限制delivery_queue 里那些 failed 消息还暴露了另一个细节飞书 API 对卡片消息有严格的结构限制。卡片里的表格、按钮、图片数量都有上限。错误码 11310 表示 agent 生成的回复里表格超限了。这是 AI agent 输出格式的一个常见问题AI 喜欢用表格组织信息但飞书卡片渲染引擎对表格数量有限制。新版 6.10 的 feishu 插件对卡片渲染做了优化flatten 了一些嵌套结构这也是升级插件后 delivery 成功率提高的附带收益。网络层面的一点验证排查中还做了网络验证。用ss -tnp看 OpenClaw 进程的 TCP 连接确认它连到了飞书 WebSocket 服务器。飞书 WebSocket 域名是msg-frontier.feishu.cn通过 DNS 解析到多个 CDN 边缘节点 IPOpenClaw 同时维护着 4 到 5 条到这些节点的连接。连接数稳定没有频繁断连重建——网络层健康问题确定在应用层。对其他 Agent 的影响这次主要修了 main agent龙虾但 openclaw.json 里还有四个 agent。升级后 openclaw doctor 显示 cfo、cmo、cto 三个 agent 缺少 message 工具——它们能收消息、能调 LLM但不能通过飞书发回复。修法是在每个 agent 配置里加 tools.allow 包含 message。暂时不用的可以先放不影响龙虾正常使用。investor agent 没有这个 warning配置跟 main 一样完整。后续维护建议升级前做状态快照把 openclaw.json 和插件列表 dump 出来升级后对比差异。定期查 delivery_queue 的 failed 趋势和 channel_ingress_events 的 count 变化——如果 count 突然变成 0说明插件或连接出了问题。对于同时跑多套 agent 的场景可以让 OpenClaw 使用独立的 HOME 目录彻底消除 state.db 共享但这个优化可以放到下次大版本升级一起做。写在最后排查花了几个小时修复只用了四条命令。时间主要花在理解问题上——理解新版插件架构理解消息为什么没进数据库理解那些 SQLite 表代表什么状态。工具越来越复杂出问题时能给你最多信息的往往不是日志而是安静躺在数据库里的数据。一条COUNT(*) 0比任何错误日志都更好地告诉你消息从来没进来过。