为什么没有错误恢复策略的 Agent 会一错就崩

用 4+1 分类、4 问诊断 SOP 和反模式清单,讲清 Agent 出错后如何活下来。

Module A · 第 3 讲

立靶:没有恢复策略的 Agent,一错就崩

先想象一个没有任何错误恢复设计的 Agent。它调一个外部接口,遇到一次网络超时——直接抛异常、整条任务终止;用户看到的是一个转圈之后的白屏,或者更糟,一句没头没尾的「出错了」。

更隐蔽的崩法是「静默」。Agent 内部走进了一条没人处理的分支,于是默默返回了一个空结果、一个半成品,甚至一个看起来正常其实是错的答案。用户不知道,系统也不知道。等到下游发现时,错误已经被当成事实传播出去了。

这两种崩法对应两类代价:

  • 显式崩溃:任务失败率高,用户当场失去耐心。
  • 静默错误:信任崩塌——用户一旦发现 Agent「会一本正经地交付错的东西」,就再也不敢把重要的事交给它。

错误恢复策略要解决的,正是「出错之后怎么办」。它不是给 Agent 加一层 try/catch 那么简单,而是一套结构化的分诊与补救体系:什么错该重试,什么错该降级,什么错该老实认输,什么错必须叫人来。

核心结论先放在这里:错误恢复有 5 种动作,但统计时只有 4 种是主路径——第 5 种「回滚」是正交维度。

框架:4+1 分类

把「出错之后怎么办」拆成两个独立的问题:如何完成任务(4 条主路径,互斥且穷尽,加起来 100%)、如何清理副作用(回滚,跟前面 4 条独立的正交维度)。

错误恢复升级路径:错误发生→显式捕获→分诊→重试→降级→优雅失败/人工介入,回滚正交叠加
错误恢复升级路径:错误发生→显式捕获→分诊→重试→降级→优雅失败/人工介入,回滚正交叠加
策略量级适用场景是否告知用户主要风险
重试瞬态错误:网络抖动 / 超时 / 限流一般不告知(静默重试)对非幂等操作重试 → 重复副作用
降级主路径走不通但仍可交付次优结果明显降质应告知用户以为拿到的是完整结果
优雅失败——低价值 / 不可恢复,无补救空间必须诚实告知滥用成「遇事就放弃」
人工介入不可逆 + 低置信 + 连续失败 + 用户主动要求必须告知并交接SLA 超时无人接 → 任务悬挂
回滚(正交)——已产生副作用、状态不一致需要清理看副作用是否已触达用户误把有价值的中间产物当垃圾删掉

几点要说清楚:

  • 重试 的前提是幂等性,建议指数退避、最多 N=3 次。幂等性本身是「预防层」的事,不是恢复层。
  • 降级 不是一种动作,而是 4 个子类:模型降级 / 能力降级 / 范围降级 / 时延降级。
  • 优雅失败 是 fail-safe close——宁可不做,也不做错。关键是「诚实」:明确告诉用户做不了,而不是假装做了。
  • 人工介入 是最重的兜底,建议 SLA 30s,超时则退回优雅失败,避免任务无限悬挂。

为什么回滚是正交,不是第 5 条主路径? 主路径 4 类 × 回滚 {触发 / 不触发} = 8 种组合,每一种都成立:可以「重试且无需回滚」,也可以「降级且需要回滚已写入的脏数据」。每个格子都填得满,说明两者独立。正交的实际价值在统计:主路径分布(和=100%)和回滚触发率是两个独立指标,不能混进同一个 100%。

case:一个「已交付副作用」的真实教训

案例来自一个文档自动审查类 Agent(场景脱敏)。这类 Agent 帮用户审一批合规文档,输出「有无风险点」的结论。

事故经过:某次 Agent 漏检了一个本应标红的风险条款,并且已经把「该文档通过」的结论交付给了用户,用户据此做了下一步动作。后来在 QA 抽检中才发现这次漏检。

新手第一反应往往是:「那就转人工呗。」——这个答案不及格。因为副作用已经触达用户了,光转人工解决不了已经发出去的错误结论。正确的处理是一套 5 步动作:

  1. 撤回:尽快收回或标记那条错误结论,阻止进一步传播。
  2. 重审:用更高规格(人工 / 更强模型)重新审一遍这份文档。
  3. 沟通:主动、诚实地告知用户「之前那条结论有误」,而不是等用户自己发现。
  4. 合规上报 + RCA:按合规要求在时限内(如 72h)上报,并做根因分析。
  5. 具体补偿:给出可执行的补救方案,而不是一句「抱歉」。

这个 case 的关键启发:副作用是否已触达用户,决定了恢复动作的重量级。 同样是漏检,「只是内部写了草稿没发出」和「已经发给用户并被采信」是完全不同的两件事。

另一个常见误区:合同审查这类场景应该优先保召回率(宁可误报也别漏检,漏检=法律风险),而代码审查、面向用户的外呼电话等场景应该优先保精确率(误报会造成告警疲劳或骚扰用户)。同一套恢复机制,在不同业务里调的方向是相反的。

可操作做法

4 问诊断 SOP(最重要,先答这 4 个再下判断):

Q1 错误类型?  瞬态(网络/超时/限流)   vs  永久(输入质量差/边界外)
Q2 副作用?    无  vs  已写未交付  vs  已交付给用户
Q3 可恢复?    可续接  vs  必须重做  vs  不可恢复
Q4 层别?      预防层(设计漏洞)  vs  恢复层(运行时补救)

这 4 问直接映射到策略选择:瞬态+可续接 → 重试;永久但还能出次优 → 降级;不可恢复+价值低 → 优雅失败;已触达用户/不可逆 → 人工介入+回滚;落在预防层 → 回到设计阶段修,别在运行时打补丁。没答完这 4 个问题之前,不许下任何恢复判断。

错误发生后的升级路径:

错误发生 → 显式捕获(严禁 silent fallthrough)
   ↓ 分诊(4 问)
重试(N=3 仍失败)→ 升级
   ↓
降级(4 子类按场景选)
   ├─ 已写副作用 → 回滚(正交叠加,不占主路径名额)
   ├─ 低价值/不可恢复 → 优雅失败
   └─ 全失败且严重 → 人工介入(SLA 30s,超时退回优雅失败)

5 个反模式(逐条对照自查):

  1. 「重试」包打天下——永久错误重试多少次都没用,只是浪费 token 和时间。
  2. 「回滚 = 删数据」——回滚是清理不一致状态,不是无脑删;有价值的中间产物该保留。
  3. 已交付副作用只答「转人工」——必须走撤回+重审+沟通+合规上报/RCA+补偿的 5 步。
  4. 把幂等性问题当成错误恢复——幂等性、原子性是预防层的事,混淆这两层会把架构问题误当偶发故障。
  5. 边界问题在末端拦截——该在入口阶段就拦掉的脏输入,拖到流程末端才发现,代价高且容易已产生副作用。

指标体系:别只测结果,也要测过程。 北极星是「恢复后完成率」(恢复后最终完成数 / 触发恢复的任务数);正交看回滚触发率(异常升高是坏信号);过程代价看恢复带来的额外延迟 / 打断次数 / token 成本——一个靠疯狂重试和频繁打断用户换来的高完成率,并不健康。

收口

错误恢复有 5 种动作、4 条主路径加 1 个正交的回滚;任何判断之前先做「4 问诊断」(瞬态还是永久 / 有无副作用 / 能否续接 / 是预防层还是恢复层),并且——任何意外路径都必须显式处理,silent fallthrough 永远是反模式。