为什么简单的 try-catch 对 Agent 不够用?
在传统编程中,遇到错误只需重试相同的逻辑。但对于 Agent,如果连续 3 次用同样的方式修改代码都报错,继续盲目重试只会白白浪费 Token 并加剧系统状态的混乱。
分级自愈工程模式
- 错误特征分类(Error Taxonomy):
- 瞬时网络错误(Transient):执行指数退避(Exponential Backoff)重试,不打断模型上下文;
- 确定性语法/类型错误(Deterministic):捕获编译器的详细行号与报错日志,作为 Observation 喂给模型触发自省(Self-Correction);
- 语义认知死胡同(Cognitive Impasse):当连续 2 次修复失败时,清除最近的尝试历史,退回上一个 Checkpoint,强制更换思路(如重写方案架构);
- 死循环熔断器(Loop Breaker):记录最近 5 步的动作签名哈希,一旦检测到循环振荡,立即挂起并向人类工程师求助。
Checkpoint 的工程实现
自愈的前提是"回得去",落地时注意三点:
- 每个子步骤开始前做快照:代码任务用独立分支逐步提交,文件级操作用差异存档;
- 快照不只存文件状态,还要记录环境事实——测试基线结果、本轮已调用过的工具清单;
- Checkpoint 必须与任务计划绑定:回滚时同步恢复"当前执行到第几步"的指针,否则模型会拿着第 3 步的世界状态去执行第 7 步的指令。
重试参数基线(经验值)
| 错误类别 | 等待策略 | 重试上限 | 超限后动作 |
|---|---|---|---|
| 瞬时网络错误 | 指数退避叠加随机抖动 | 约 3~5 次 | 升级人工或切换通道 |
| 确定性编译错误 | 立即重试,不等待 | 同一位置约 2 次 | 回滚 Checkpoint 并换思路 |
| 语义死胡同 | 不适用 | 约 2 次 | 清历史、重建方案 |
加抖动是为了避免多个 Agent 同步重试把下游服务打得更惨;上限数值应结合任务时长预算调整,重要的是"必须有上限"。
验证方法:故障注入演练
模式搭好后要主动注入故障验证:人为掐断网络十秒,确认退避重试自动恢复;在待改代码里埋一个低级类型错误,确认报错被完整捕获为 Observation 而不是被截断;构造一个"修 A 坏 B、修 B 坏 A"的死胡同场景,确认熔断器在规定步数内挂起任务,并且通过 智能体可观测性架构:基于 OpenTelemetry 的链路追踪与决策树还原 中的链路数据能还原整个决策过程。
常见故障速查
| 现象 | 原因 | 处理 |
|---|---|---|
| Agent 明显打转但熔断器不触发 | 动作签名只哈希了输入、未包含关键结果 | 把每步的核心产出并入签名计算 |
| 回滚后状态依然错乱 | Checkpoint 只回滚了代码没回滚环境 | 快照中同步记录测试基线与工具状态 |
| 重试成本失控、Token 暴涨 | 确定性错误也带着全量历史重试 | 回滚场景只重放报错与必要上下文 |
| 挂起后人工看不懂现场 | 求助消息只有一句"需要人工" | 挂起时输出错误分类与尝试摘要 |
小结
可执行的判断标准:对同一类故障连续注入五次,系统的反应是否一致。如果三次直接等人工、两次自己重试了二十轮,说明错误分类还没有真正建立——先修分类器,再加模型。自愈设计的终点不是"永远不用人",而是每一次交给人处理时,人都能看到清晰的现场。