ARTICLE / 开源项目
补充P2P联邦心跳与任务接力特性的研究
PR 地址:NousResearch/hermes-agent#76661 · 多设备 Hermes 联邦:心跳、断线任务接力、机队健康运维
研究摘要
多台机器各跑一个 Hermes,彼此是信息孤岛:任务在某台机器上跑着,机器一断线任务就没了;哪台机器健康、哪台掉线,没有任何全局视图;设备间互联要么手工配 IP,要么干脆不做。本 PR 用 23 个阶段建成了一套完整的 P2P 联邦体系(+15295 行,50 个文件),把孤岛连成机队:每台设备广播心跳、连续 3 次失联才判死(避免误报)、离线设备的任务由幸存节点按 Raft-lite 共识原子认领并断点续跑、GPU/CPU/内存感知的能力路由、TLS + HMAC 签名的安全层,外加 Phase 22 的机队运维层——健康评分矩阵、失联 SOS 三级升级、远程协助钩子。
实测记录扎实:220 个单元测试全部通过,CI 30 项检查全绿,并在 2 台真实设备(MacBook Pro 控制器 ↔ Mac Mini 成员,Tailscale 组网)上完成 SSH 验证——TLS 握手通过、对端出现在运维矩阵中(health_score 1.0)、健康快照每 60 秒流动。这是本系列中体量与复杂度最高的一篇,也是把"任务连续性"真正写进多设备架构的一次尝试。
一、问题背景:多设备 Hermes 的三重断裂
1.1 任务连续性断裂
单机 Hermes 的任务生命周期绑定在所在机器上:机器关机、断网、崩溃,正在跑的任务随之中断,且没有其他机器能接手。对在笔记本上跑长任务、又常切换设备的用户来说,这是最痛的一环——任务本身是可以恢复的,缺的是"换台机器继续跑"的机制。
1.2 发现与配置断裂
设备互联要么手工填写每一台对端的地址,要么干脆不连。同局域网内的设备本可以自动互相发现,却因为没有零配置路径而保持孤岛。
1.3 健康可见性断裂
机器多了以后,“机队里谁还活着"变成了玄学。没有心跳、没有健康快照、没有告警,一台成员机悄悄掉线可能几天无人发现,直到需要它时才措手不及。
PR 的定位判断很明确:只跑一台机器的用户不需要联邦;需要的是运行多台设备、并要求设备掉线时任务仍能继续的用户。
二、特性设计:四层架构 + 运维层 + 两个架构改进
2.1 核心联邦层(Phase 1-21)
心跳与死亡检测。每台设备周期性广播存活信号;一台对端连续 3 次失联(CRITICAL-3)才被判定死亡,三次的冗余设计是为了把瞬时网络抖动排除在误报之外——一次失败可能是抖动,三次连续失败才值得惊动机队。
任务接力与 Raft-lite 共识。离线设备的未完成任务由幸存节点认领。认领动作的关键在于原子性:BEGIN IMMEDIATE 事务作为认领的第一条语句,把"检查任务空闲"与"锁定任务"合并成不可分割的一步,从根上关闭了检查与认领之间的 TOCTOU 竞态——两个节点同时看到同一任务空闲、同时认领的窗口不复存在。任务进度通过 checkpoint 流式同步,接力节点从最后一个检查点继续,而不是从头重跑。
设备发现。两种模式:auto 模式用 mDNS 自动发现(stdlib socket 实现,零第三方依赖);lan 模式用显式的对端 WebSocket 地址。跨局域网或 Tailscale 场景走 lan,同局域网开箱即用走 auto。
能力匹配与计算池。路由不是随机的:FederationComputePool 维护各节点的 GPU/CPU/内存画像,任务按能力画像路由到合适节点执行。
安全层。TLS 传输加密(自签名证书在局域网内可用)、HMAC-SHA256 对消息签名(覆盖消息 ID、类型、时间戳、载荷)、auth_token 认证、IP 白名单、带 HMAC 链的审计日志(20 种事件类型)与密钥存储。
2.2 运维层(Phase 22):联邦从"转任务"到"管机队”
Phase 22 是定位跃迁:联邦不再只是任务接力管道,而是主动维护机队健康的运维层。
健康监控(HealthMonitor)。每次心跳都携带健康快照:网关状态、联邦连接状态、CPU 负载、内存、磁盘余量、Hermes 版本。每个对端的加权健康评分(0..1)实时计算,通过运维 API 输出全机队健康矩阵。
失联 SOS 三级升级(LostContactSOS)。“飞机失联"式分级:失联软告警(<60 秒)→ 确认失联(<300 秒)→ 严重失联(≥300 秒)。每一级都向幸存节点广播 OPS_ALERT;对端恢复时自动触发 recovery 告警闭环。on_assist 钩子允许运维者挂接远程恢复动作——对被判失联的主机执行 SSH 探活、远程重启网关。
连接稳定性修复。部署中暴露的真实问题被逐一修复:出站连接改用宽松的客户端 TLS 上下文以兼容局域网自签名证书(服务端上下文没有 CA 链,跨机器校验必然失败),对端身份仍由 auth_token 与消息签名强制保证;断线重连保持 2 的幂次退避(上限 10 次),并记录连接延迟。
新消息类型与 API。新增 OPS_HEALTH、OPS_ALERT、OPS_SOS、OPS_ASSIST_ACK 四种运维消息;新增三个鉴权保护的 API 端点:单机健康矩阵、近期告警列表、机队汇总视图。
2.3 两机真实部署中揪出的合并 bug
在两台真实设备上部署 v3 时,一批合入前没暴露的 bug 被发现并修复:计算评分被当作属性调用而它是个方法;FederationAdapter.send() 缺失导致集群/主节点选举路径崩溃;_federation_config 引用被移除;load_gateway_config() 此前静默丢弃 federation: 配置段导致网关根本没启动联邦;gateway/run.py 未把鉴权与 TLS 参数传给适配器,出现"配置了 require_tls 实际却是 TLS=no"的隐患。这批修复说明:联邦这类跨进程、跨机器的特性,单元测试覆盖不到真实网络拓扑,真机部署是必不可少的验证环节。
2.4 Phase 24:Sweeper 审查修复与两个架构改进
上游 agent 自动审查(Sweeper)提出的 6 项 findings 全部处理完毕:3 项已修复(任务认领后实际派发、TOCTOU、Kanban 桥接)、1 项被判定为过时(方法已存在)、1 项承认并补了启动集成测试、1 项通过单写者选举解决。同步落地两个架构改进:
联邦 → Kanban 桥。联邦认领的任务现在会创建一个真实 Kanban 任务,以 fed:<id> 为幂等键、初始状态 ready;本地 Kanban 调度监视器在下一轮 tick 发现 ready 任务后调用调度器派生真实 worker。联邦与 Kanban 完全解耦,但共享同一个执行池。
单写者 SQLite。shared_db v1 模式下,通过 O_CREAT|O_EXCL 语义在独立锁文件上选举唯一写者,只有被选中的写者执行离线检测与任务认领,其余节点只做只读心跳,从机制上消除双写冲突;超过 5 分钟无心跳的陈旧锁会被下一候选写者接管,故障转移透明。
三、实测结果
3.1 单元测试
| 测试组 | 覆盖 | 结果 |
|---|---|---|
test_federation_phase{3,5,6,7,8,9,10,11,12,16}.py | 核心阶段 | passed |
test_federation_ops.py | 健康监控、死亡与复活、SOS 升级、本地健康采集 | 4 passed |
test_federation_heartbeat.py | 心跳与死亡检测 | passed |
test_federation_v2.py | v2 协议 | passed |
| 合计 | — | 220 passed |
3.2 真机验证(2 台设备,Tailscale 局域网)
在两台真实设备上完成了端到端验证:控制器(MacBook Pro)与成员(Mac Mini)以 lan 模式、wss:// 协议、TLS 加鉴权的方式组网,WebSocket 连接与 TLS 握手均成功;成员设备出现在控制器的运维矩阵中,federation_connected 为真、health_score 为 1.0;健康快照每 60 秒持续流动。
PR body 还给出了端到端演练路径:停止成员机网关后,30 秒内控制器收到"成员确认离线"的运维告警,成员机的任务被提供给其他节点;恢复后自动触发 recovery 告警。
四、平台兼容性与能力边界
| 平台 | 联邦模式 | 密钥存储 | 健康快照 | 说明 |
|---|---|---|---|---|
| macOS | auto (mDNS) / lan / shared_db | 系统钥匙串 | CPU/内存/磁盘 | 全支持 |
| Linux | auto (mDNS) / lan / shared_db | AES-256-GCM 加密文件 | CPU/内存/磁盘 | 全支持 |
| Windows | 仅 lan(mDNS 自动回退) | 加密文件 | CPU/内存/磁盘 | 需显式对端地址 |
能力边界与已知约束:
- mDNS 依赖 UDP 组播(224.0.0.251:5353),被防火墙拦截时自动发现失效,需开放端口或改用
lan模式; - Windows 无原生 mDNS,
auto模式自动降级为lan,用户无需手动改配置,但零配置体验只在 macOS/Linux 成立; shared_db模式依赖文件共享(iCloud Drive / SMB / NFS)同步 SQLite 文件,文件不可达即不同步;该模式是 v1 选项,v2/v3 不依赖它;- Linux 健康评分的已知降级:
getloadavg()不可用时评分优雅降为 0.0,联邦功能不受影响,但评分失去参考意义; - 自签名证书信任:跨机器 TLS 校验失败是部署中最常见的坑,需要各机器使用同一证书文件或显式放行;
- 死判阈值:连续 3 次失联(配合
offline_threshold_s默认 30 秒)是防误报与响应速度之间的折中,对网络极不稳定的环境可能需要调参; - PR 状态为 open,220 测试与两机验证均为开发过程中的实测记录,尚未合入主线。
五、PR 信息
- PR 地址:https://github.com/NousResearch/hermes-agent/pull/76661
- 改动规模:+15295 / -0,50 个文件
- PR 状态:open(23 个阶段完成,Sweeper 审查项已全部闭环)
- 提交时间:2026-08-02
本文记录 x7peeps 向 Hermes Agent 上游贡献的特性研究,所有数据来自 PR 实测记录。