Hermes Agent 升级踩坑实录:从版本冲突、非终端死锁到完美恢复

今天围绕 Hermes 做了一整套「定时播报体系搭建 + 两次故障排雷」,折腾跨度从下午到深夜,把过程和结论记录如下。

一、落地成果:三条每日自动播报线

在北京时间错峰排布,全部自动投递到 Telegram:

  • 6:50 X 十大热搜(job: 5e77c742db45)—— 抓 trends24.in 美国区公开榜,curl 解析 twitter.com/search 链接取前 10,逐条中文解读;
  • 7:00 每日热搜解读(job: f7229f447bc3)—— 全网 8~10 条热点,每条「核心事件 + 看点」,晨间阅读版;
  • 10:00 微博十大热搜(job: fef0b3c61896)—— 官方接口 weibo.com/ajax/side/hotSearch,取 data.realtime 前 10 的 word 与 num(热度),带一句话解读。

三条任务全部先手动试跑验收通过,再挂正式排期。任务间用独立锁文件(.tick.lock)防重复触发,各自跑在全新会话里,互不串台。

二、排雷之一:定时任务连续失败的真凶——漏配的 API 密钥

环境:cron 任务固定到 custom:lfree-mimo 通道(mimo-v2.6-flash)。
症状:连续 3 次试跑全部报「every provider in the fallback chain kept failing over」,且 0 次成功 API 调用。

排查路径(错误信息是幌子,日志才是真相):

  1. cron 报错只说「备用链全挂了」,但真正的报错在 /opt/data/logs/errors.log 里:HTTP 401: Incorrect API key provided or endpoint mismatch;
  2. 对比配置发现:模型别名 model_aliases.mimo26 里带着 api_key,而 custom_providers 里的 “lfree mimo” 条目没配 api_key;
  3. 代码层面(runtime_provider_custom.py)确认解析顺序:显式 key → 条目 api_key → key_env → 凭据池 → 都没有就发占位符 no-key-required;
  4. 实测复现:占位符 key → 401,别名里的真 key → 200。根因坐实。

修复:hermes config set custom_providers.1.api_key <key>(把 mimo26 别名里已验证的密钥同步过去),试跑第 4 次成功。同时把三个任务都固定到该通道,避开当时集体故障的备用链(GitHub Models 空流、Gemini 免费额度 429 要等 17 小时)。

教训:Hermes 的兜底设计是「别名路径带 key 时正常,直连 custom_providers 路径才暴露缺 key」——同一个通道两条解析路径,配置只补了一半。新配自定义通道时,custom_providers 条目和 model_aliases 别名要两处都写密钥,或干脆只用带 key 的那条路径。

三、排雷之二:Docker 沙箱模式——一次「安全改造」引发的全线瘫痪

背景:另一会话把 terminal.backend 从 local 切成了 docker(沙箱隔离防爆门)。
症状:当晚 22:50 的 X 热搜、次日 02:00 的微博热搜接连失败,报 EnvironmentConnectionError: 'docker version' failed——所有要跑 shell 的工具(terminal、execute_code、文件搜索)全线熄火,只有靠网络搜索的任务幸存。

排查:

  1. 时间线高度吻合:上午手动试跑还全好,切 docker 模式后当晚开始全挂;
  2. 容器内有 docker 命令文件,但 /var/run/docker.sock 不存在——Hermes 自己就跑在容器里,宿主机的 docker 门铃线根本没牵进来;
  3. 官方镜像启动脚本(stage2-hook.sh)确实支持挂 socket 后自动配组,但前提是宿主机侧重建容器时挂载它。

修复:hermes config set terminal.backend local 切回本地模式,工具链立即恢复(注意:容器内没有 hermes 命令时要 docker exec hermes-agent /opt/hermes/bin/hermes ... 在宿主机上进容器执行)。

四、关键决策:为什么最终放弃挂 docker.sock

修复方案曾考虑「挂载宿主机 docker.sock 重建容器」让沙箱真正可用,经二次验证(交叉咨询)后否决,理由:

  • 目的与手段自相矛盾:沙箱本意是锁住 AI,而 docker.sock 等于宿主机 root 总钥匙——容器内一条 docker run -v /:/host -it alpine chroot /host 即可穿透接管整台宿主机。锁匠自己把锁拆了,不叫升级,叫开门揖盗;
  • 现有架构已是合格沙箱:Hermes 本身跑在容器里(第一层隔离),AI 砸烂的最多是容器自己;数据盘之外的宿主机系统碰不着;
  • 另有 DinD / gVisor / Firecracker 等真隔离方案,但在 ARM 云服务器上维护成本过高,与省心诉求不匹配,记为日后选项。

最终安全配置(三层安全垫,不裸奔):容器隔离 + 命令白名单(delete in root path、heredoc 脚本等已列管)+ 危险操作审批模式。

五、经验总结

  1. 报错信息会骗人,日志不会:cron 的「备用链失败」只是表象,401 才是根因,必须下钻 errors.log;
  2. 安全改造先过「目的审查」:新防线如果同时打开了一扇更大的门,先停下来问一句——这到底是防谁;
  3. 时间线是排障捷径:故障起点与配置变更时刻对齐,八成就是它干的;
  4. 重要决策交叉验证:这次挂 socket 方案被另一方分析否决后放弃,避免了一次真实提权隐患——AI 给的方案也要让 AI 再审一遍。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注