第五章 容错与恢复:系统挂了怎么办¶
5.1 容错是编排器的核心价值¶
一个没有容错的编排器比没有编排器更危险——它给人"自动化"的错觉,让你以为系统在正常运转,其实Agent可能已经卡死半小时了。
五大项目在容错上的投入差异极大,从1层到4层不等。本章系统性地拆解每层容错机制。
5.2 第一层:进程存活监控¶
最基础的容错——Agent进程是否还活着?
tmux会话检测¶
所有基于tmux的项目都用这个方式:
# 精确匹配(=前缀防止前缀匹配bug)
tmux has-session -t "=$SESSION" 2>/dev/null
# Overstory:ZFC原则(Zero Failure Crash)
# 信号优先级:tmux liveness > PID liveness > 记录状态
# tmux dead + recorded "working" → 立即标记zombie
# tmux alive + recorded "zombie" → investigate(不自动杀)
进程存活检测细节:
is_generic_process_alive() {
local pane_pid=$(tmux list-panes -t "$SESSION" -F "#{pane_pid}" 2>/dev/null)
pstree -p "$pane_pid" | grep -qE "hermes|codex"
}
关键:不是只检查tmux会话是否存在,而是检查会话里是否有Agent进程。tmux会话可能存在但Agent已经退出了。
PID进程检测¶
Overstory的ZFC健康检查状态机进一步区分了:
可观察状态(tmux/pid存活)优于记录状态
这是健康判断的真实来源
状态只允许向前转换:
booting → working → completed/stalled/zombie
tmux dead + recorded "working" → 立即 zombie
pid dead + tmux alive → 视为 zombie
LifecycleWorker(Composio)¶
// 后台Worker持续监控Agent进程
ensureLifecycleWorker(config): void;
// 检测到异常退出时尝试恢复或通知
// 防止重复启动:isAlreadyRunning(id)
// 防止系统休眠:preventIdleSleep()
5.3 第二层:行为异常检测¶
Agent可能进程活着但行为异常——卡住了、陷入循环、被限流了。
# 每轮capture-pane取最后30行算MD5
# 与上次对比,判断是否"卡住"
SCREEN_MD5=$(tmux capture-pane ... | tail -30 | md5sum)
# 早停检测:3次检查无变化 + Agent在提示符 + 执行Agent空闲
# → nudge推送
# 硬超时:STALE_THRESHOLD(3600s)无变化 → 强制重启
这是最精细的限流处理方案:
检测:capture-pane最后3行扫描429/rate.limit等关键词
首次触发 → 进入RATE_LIMIT_COOLDOWN(300s)
↓
状态持久化到磁盘(重启后恢复)
↓
衰减续期:每次续期缩短冷却时间 cooldown/renew_count
↓
4次续期强制重启:打破无限限流循环
↓
冷却到期 → 通知架构师恢复派发
为什么需要"4次续期强制重启"?因为Agent可能反复请求被限流→等待→再请求→再限流,形成死循环。衰减续期打破了这个循环。
AI分诊(Overstory Tier 1)¶
当机械监控无法判断时,调用一个短暂的AI Agent来分析:
这是一个聪明的混合策略——机械守护处理确定性场景(进程死了),AI分诊处理模糊场景(进程活着但不知道在干嘛)。
5.4 第三层:自愈与恢复¶
检测到问题后,怎么恢复?
渐进式恢复(Overstory 4层Watchdog)¶
Tier 0 — 机械守护进程
Level 0 (warn): 日志警告
Level 1 (nudge): 发送tmux nudge(按键唤醒)
Level 2 (escalate): 调用Tier 1 AI分诊
Level 3 (terminate): 杀死tmux会话
渐进式处理:先轻后重,不要上来就杀进程
自调度链(Tmux-Orchestrator)¶
schedule_with_note.sh <minutes> "<note>" [target_window]
# 工作原理:
# 1. 将调度信息写入 next_check_note.txt
# 2. nohup后台sleep进程
# 3. sleep结束后,tmux send-keys发送唤醒命令
这是Tmux-Orchestrator最核心的创新——Agent能给自己设闹钟。Orchestrator调度自身检查、PM调度自身复查、Engineer调度自身同步。
脆弱性:依赖nohup+sleep,系统重启后调度链断裂。
第一层:内置Watchdog(fork子进程)
- 检查心跳文件(每60s更新)
- 心跳超过600s未更新 → TERM信号 → 等30s → KILL → 重启
第二层:外部Watchdog(systemd timer)
- 每5分钟检查心跳文件
- 作为最后防线:内置Watchdog也挂了时触发
为什么需要两层?
safe_session()可能全部超时(每个10s,多个会话),导致内置Watchdog卡死
此时心跳文件不更新,systemd timer触发外部重启
会话交接与恢复(Overstory)¶
// Checkpoint:保存完整会话状态
{
agentName, taskId, progressSummary,
filesModified, pendingWork, currentBranch,
lastCommit, openQuestions
}
// Handoff:记录交接历史
{ fromSessionId, toSessionId, reason, timestamp }
// 恢复:找到最近的未完成handoff,加载checkpoint
resumeFromHandoff(agentName)
这是唯一一个支持"精确恢复"的方案——不是简单重启Agent,而是恢复到之前的工作进度继续。
crash_restart() {
CRASH_TIMESTAMPS+=(now_ts)
# 保留最近10次崩溃时间戳
# 120秒内3次崩溃 → 强制120s冷却
# 防止Agent反复崩溃导致无限重启循环
}
5.5 第四层:质量保障¶
即使Agent没崩溃,也可能产出低质量结果。质量保障是容错的最高形态。
开发-测试循环(agency-agents-zh)¶
核心规则: - 每个任务必须在推进之前通过QA - 每个任务最多3次重试 - 重试必须携带具体的QA反馈
现实检验者(agency-agents-zh)¶
默认判定:NEEDS WORK(需要改进)
只有在压倒性证据下才给出 READY(就绪)
三种判定:
READY → 可以上线
NEEDS WORK → 回到第3阶段修改
NOT READY → 回到第1/2阶段重新设计
这是防止"过早上生产"的最后一道防线。首次实现预期需要2-3轮修改,这是正常的。
# 每300秒检查prompt中的IRON_LAW标记
# 如果标记被删除(Agent自己改了规则):
# 1. git checkout HEAD -- scripts/auto_push.sh # 从git恢复
# 2. 发送警告消息给架构师
PM质量保证协议(Tmux-Orchestrator)¶
- 代码审查在合并前进行
- 测试覆盖率监控
- 性能基准测试
- 安全扫描
- 强制git纪律:每30分钟提交、特性分支、有意义提交信息
5.6 五大项目容错能力对比¶
|| 容错能力 |---------|-----------------|-------------------|----------|-----------|-----------------|| || 进程监控 | tmux+pid | tmux | LifecycleWorker | ZFC状态机 | 无运行时 || || 限流处理 | 持久化+衰减+4次重启 | 无 | 无 | 无 | 无 || || 卡住检测 | MD5快照+早停+硬超时 | 自调度链 | 无 | 4层Watchdog | 质量门禁 || || AI辅助诊断 | 无 | 无 | 无 | Tier 1分诊 | 无 || || 会话恢复 | 无(重启) | 无(重启) | git回滚 | checkpoint+handoff | MCP rollback || || 崩溃保护 | 快速崩溃限速 | 无 | 无 | 渐进式nudge | 升级协议 || || 规则守护 | 规则守护 | CLAUDE.md约定 | 无 | constraints字段 | Prompt规则 || || 质量保障 | 无(信任架构师) | PM审查 | Orchestrator审查 | Reviewer角色 | 证据收集+现实检验 || || 双层保护 | 内置+systemd | 无 | LifecycleWorker | 4层Watchdog | 4级容错 ||
实战中的容错模式¶
Tmux-Orchestrator的Git纪律作为容错: - 强制每30分钟提交,防止工作成果丢失 - 特性分支和稳定标签创建恢复点 - 项目经理作为第一道防线执行质量标准 - 自调度链确保Agent不会永久卡住
agency-agents-zh的多阶段QA作为容错: - 七阶段流水线,配备强制质量门禁 - 证据收集者测试每次实现 - 现实检验者提供三层判定(READY/NEEDS WORK/NOT READY) - 每个任务最多3次重试,携带具体反馈
Composio的CI/CD集成作为容错: - Agent自主修复CI失败 - 基于PR的工作流提供人工监督 - 每个Agent在独立的git worktree中工作,防止冲突 - 仪表盘监控实时状态
Overstory的4层Watchdog系统: - Tier 0:机械守护进程(日志记录、nudge唤醒) - Tier 1:AI分诊(分析模糊情况) - Tier 2:渐进式升级(warn → nudge → escalate → terminate) - Tier 3:带检查点恢复的会话交接
5.7 容错设计的核心原则¶
原则一:机械监控优于AI判断¶
ZFC原则的核心——用确定性信号(进程是否活着、心跳是否更新)而非不确定信号(AI觉得卡了)作为恢复触发器。AI分诊只在机械监控无法判断时介入。
原则二:渐进式恢复¶
不要上来就杀进程。warn → nudge → escalate → terminate,逐步加重。很多"卡住"只是Agent在思考,nudge一下就好。
原则三:状态必须持久化¶
限流状态、崩溃记录、检查点——这些必须写入磁盘。重启后丢失状态意味着重复犯同样的错。
原则四:防循环机制¶
快速崩溃保护、4次续期强制重启——这些看似边缘的场景,在7×24小时运行中一定会发生。没有防循环机制,编排器会陷入"崩溃→重启→崩溃"的死循环。
原则五:质量是最高级容错¶
防止低质量产出比防止崩溃更重要。崩溃可以重启,但低质量代码合入了主分支,回退成本远高于重新运行。