Hermes Agent v0.20.3
Overview
v0.20.3 — The Resilience Patch(韧性补丁)。 发布于 2026 年 8 月 16 日。自 v0.20.2 以来 合并约 125 个 PR · 约 250 个提交 · 改动约 461 个文件(+42,613 / −1,641)。
在 Connections Patch 发布一天后,这个版本回答了一个更安静的问题:当你的自动化悄悄停摆、而没有任何人告诉你时,会发生什么?cron 调度器现在能扛住文件描述符耗尽(EMFILE),能对照执行台账(ledger)清理陈旧 claim,能自动重新武装卡死的周期任务,还能补跑外部 provider 漏掉的触发——同时 last_fire_error 让每一次漏触发在 CLI、dashboard 和 agent 自己的工具输出里都看得见。围绕这个核心:MCP 2.x SDK 迁移与 2026-07-28 无状态协议支持、CommandCode 成为一等公民供应商、受 Copilot CLI 启发的 /worktree 与安全 /rollback、子进程 Python 运行时归属加固,以及会话交接(handoff)的数据丢失修复。
这是补丁版本,官方说明从简,完整文档随 v0.21.0 发布。本页覆盖该窗口最有价值的部分。
Highlights
1. cron 调度器学会自我修复
三种曾经会让任务死掉数小时、而一切“看起来都很健康”的静默停摆故障,现在都能自愈:
- EMFILE(文件描述符耗尽):
tick()过去把所有OSError都吞成“另一个实例持锁”,于是锁文件上的 fd 耗尽被记为一次成功 tick,之后没有任何任务再跑过。现在锁获取的 errno 会被分类:只有真正的锁竞争(EWOULDBLOCK/EAGAIN/EACCES-on-flock)才静默跳过,真实故障会作为失败的 tick 传播出去;ticker 还会尽力回收 fd(gc.collect()+ 提高软 nofile 上限),指数退避、上限 15 分钟(#88335,基于 @webtecnica 的 #87796)。 - 陈旧的 in-flight claim: 年龄小于窗口(2×interval,30 分钟)的泄漏 claim 过去会把周期任务卡死到需要人工介入。现在清理逻辑会对照持久化的执行台账:只要该次运行的终态行证明它已结束,claim 就会被强制释放——并带保护,避免把新 claim 误判成上一次运行的已完成结果(#88343,基于 #87259)。
- 卡死在持久化错误态的任务:
last_status=error且next_run_at停在未来的周期任务,过去对任何清理都不可见,重启网关也没用。现在它会在下一个 tick 自动重新武装——而且重新武装尊重调度合法性,周一到周五的 cron 表达式绝不会在周六触发(#88339,基于 #87261)。
2. 漏触发变得可见,而且会补跑
2026-08-14 的线上事故(连续 4 个晚上漏跑,除了日志里一行之外毫无痕迹)带来了两个持久修复。第一,当托管触发路径无法到达网关时,任务会被盖上 last_fire_error 印记,在 cronjob list、hermes cron list(红色 ⚠ Missed scheduled fire: 行)和 dashboard 中可见;下一次成功运行会清除它,所以这个印记始终描述当前健康状态(#88555)。第二,外部 cron provider(Chronos / 托管 cron)现在支持漏触发补跑:当一次触发迟迟不来且重试耗尽,网关会在宽限期后检测到逾期任务并在本地补跑——cron.misfire_grace_minutes(默认 10,≤0 关闭)。故障代价从“悄悄丢一整天”变成“几分钟”(#88563)。
3. MCP:SDK 2.x + 2026-07-28 无状态协议
Hermes 迁移到 MCP 2.x SDK(#88180),并端到端支持 2026-07-28 无状态协议(#88299)。没有 initialize 握手的服务器现在开箱即连:四个传输调用点(stdio、SSE、新 HTTP、旧 HTTP)统一走一个 _negotiate_session() 收口。每个服务器可配 protocol 键:auto(默认)先尝试旧握手,服务器拒绝(-32022/-32601)时回退到 server/discover——对现有服务器零额外往返;stateless 直接先 discover;legacy 关闭回退。SEP-2549 的 ttlMs/cacheScope 提示会从 tools/list 捕获进带 TTL 的 schema 缓存;OAuth 注册遵循新规范(native application_type、RFC 9207 iss 校验)。
4. 新供应商:CommandCode(Muse Spark 已在 main)
CommandCode(commandcode.ai)成为一等公民供应商——commandcode(OpenAI chat completions)与 commandcode-anthropic(Anthropic Messages,Bearer 认证)两个 profile 共用一个 COMMANDCODE_API_KEY,覆盖 GOAT/Pro/Max/Provider 套餐(约 30+ 个开源与闭源模型,从公开 /provider/v1/models 端点实时发现)(#88308,抢救自 #32909)。在 main 上(超出本 tag),Meta Model API(Muse Spark) 也作为内置插件加入:--provider meta-ai 开箱即用,MODEL_API_KEY 认证(别名 META_API_KEY/META_MODEL_API_KEY,可用 META_BASE_URL 覆盖),内置 muse-spark-1.2 / muse-spark-1.2-contributor 目录(#88565)。
5. /worktree 与安全 /rollback——可撤销的 agent 改动
本窗口落地两个受 Copilot CLI 启发的命令。/worktree new [name] 在会话中途创建隔离的 git worktree(仓库内 .worktrees/,分支基于刚 fetch 的远端 tip,遵循 worktree_sync),并把会话的终端与文件工具重定向进去——无需重启;/worktree 显示当前树,/worktree list 列出全部,退出清理与 hermes -w 一致(有未推送提交则保留)。/rollback 现在默认安全恢复:通过按项目记录的 agent 写入台账(每次落地的 write_file/patch 的 sha256),只回滚 agent 改过的东西、删除 agent 创建的文件、保留你手工改的内容;--all/--force 恢复全部,被跳过的文件会带提示报告。
6. 子进程 Python 运行时归属加固
execute_code 等工具现在完整掌控自己的 Python 子进程环境:PYTHONHOME/PYTHONPATH 由受管运行时组合,不再继承父 shell 里被污染的变量,堵住了一类“我终端里好好的,agent 里就坏”的怪问题,也加固了不可信代码的边界。
7. 会话交接数据丢失修复
两个用户上报的数据丢失 bug 已修复(#88244)。/handoff telegram 之后存在一个 CLI→网关竞态:CLI 可能在网关正在写入的会话行上触发 finalize,导致整个交接段从历史与 session_search 中消失;CLI 现在记录已交接的 session id 并跳过清理性 finalize。另外,损坏的 state.db(曾让消息全部无法落盘)现在会直接告知用户:网关向所有主渠道广播恢复指引(含 hermes doctor --fix 与 sqlite3 .recover),而不是把失败埋在日志里。
Improvements
- 插件安装/更新安全扫描(受 Claude Cowork 启发):安装前扫描可疑内容。
- UTF-16 文本文件通过转码为 UTF-8 读取(移植自 MoonshotAI/kimi-code#2647);Gemini 3 tool-call ID 在适配器改写后得以保留(移植自 earendil-works/pi#7494)。
- Git worktree 自愈:
hermes -w创建失败/超时后会自行清理(残留目录、LOCKED 管理条目、孤儿分支),启动维护还会在 pack 膨胀时 repack——8 月事故中的 39 个 pack(638 MB)变成 2 个(287 MB),worktree 创建从 30 秒超时降到 0.5 秒(#88306)。 - Cua Driver 0.20 运行时契约:computer use 在更新与运行时校验驱动,安装的驱动不符合契约时自动修复(#87646 系列)。
- 桌面端:DiffusionCanvas 渲染有界(暂停策略、15fps 预算、实例上限),空闲时像素蛋动画休眠,Bot Mode 群聊渲染 Markdown,远程网关桌面不再显示幻影本地默认(#88564、#88406、#88553、#88554)。
- 委派:git 检查失败时保留子 agent 的未提交工作,父 agent 会收到 worktree 未经检查被保留的通知。
Fixes
/handoffCLI→网关竞态丢失交接段(#88234);state.db 损坏现在带恢复指引告知用户(#88235)。- Matrix:
m.audio/m.file/m.video消息体中的空白裸媒体文件名被清除;Telegram 优先 IPv4 API 地址,首个选择记录降为 info 日志。 - Cron:一次性任务派发失败时清除
run_claim;漂移修复指向用户拥有的 pin。 - 压缩:中止的轮转不再撑大它无法发布的父级。
- 桌面端:启动前 settle 等待不再卡死 composer;恢复/编辑臂保持 composer 可用。
Upgrade
hermes update
升级后运行 hermes doctor 验证安装,并重启网关(hermes gateway)让平台变更生效。如果使用外部 cron provider,先跑一次 hermes cron list,确认 last_fire_error 没有待处理项。