系列第三篇。在 Harness Engineering 的官方三支柱中,Architectural Constraints 强调"用确定性规则强制约束 Agent 行为"。在运行时层面,这最集中地体现在工具调用的容错机制上——当 Agent 出错时,Harness 用确定性的代码逻辑来防止错误扩散。
为什么错误恢复是最重要的课题?
因为模型的输出是有概率性的,实际一个在生产环境跑的 Agent,大概率每几轮就会遇到一次某种类型的失败,当遇到失败的时候,怎么去处理失败进行错误恢复很重要,Agent 的可靠性,80% 取决于它怎么处理失败,而不是怎么处理成功。
通常来说,有下面几类常见的失败,从轻到重,处理策略完全不同:
-
L1 瞬时错误(最常见):网络超时、API 限流 429、服务不可用 503。几秒后重试大概率成功。
-
L2 参数错误(常见):LLM 传了不存在的工具名、参数类型不对。需要错误回注让 LLM 自我修正。
-
L3 工具执行失败(偶发):文件不存在、权限不足、SQL 语法错误。工具可用但执行失败。
-
L4 逻辑死循环(最隐蔽):没有技术错误,但 LLM 反复用相似关键词搜索、反复生成相同代码。需要有手段能够检测出模型的执行是否会陷入死循环了,可以工程上介入进行修正。
-
L5 LLM 自身故障(罕见):服务崩溃、返回空内容、输出格式完全异常。
针对上面提到的几种常见的错误情况,有四种常见的容错策略:
- 策略一:指数退避重试(对付 L1)
每次重试等待时间翻倍 + 随机抖动,加上随机抖动可以避免"重试风暴",即一下子所有的流量都一起重试了。关键:区分可重试错误(超时)和不可重试错误(参数错)。 这本身就是一种 Architectural Constraint——确定性地区分错误类型。参考代码:
class RetryPolicy:
def execute(self, func):
for attempt in range(self.max_retries + 1):
try:
return func()
except (TimeoutError, RateLimitError): // 超时或者限流等网络抖动
delay = min(base * (2 ** attempt) + random.uniform(0, 1), max_delay) // 加上一些随机抖动的超时时间
time.sleep(delay)
except InvalidArgError:
raise # 不可重试,立即失败
- 策略二:错误回注(对付 L2、L3)
把错误信息当作 tool result 回传给 LLM,让它自己修复。好的错误消息 = "出了什么错 + 可以怎么修":
# 差的回注
"Error: File not found"
# 好的回注
"文件 /data/report.csv 不存在。建议用 list_files('/data/') 查看可用文件。"
LLM 看到后者,下一步就会调 list_files() 自己找到正确路径。错误信息的质量直接决定了 Agent 的自愈能力。
- 策略三:循环检测(对付 L4)
三种检测方法:相似调用计数、输出相似度检测、定期进展审计。
检测到后不是直接终止,而是注入干预消息——要明确告诉 LLM "基于已有结果行动"而不只是"重新思考"。
- 策略四:优雅降级(对付 L5)
逐步降低服务质量但不崩溃。永远不返回空结果——部分结果 + 诚实解释永远比裸错误好。
Claude Code 的实际做法
我们在使用 Claude Code 的时候实际上很少看到错误——其实这并不是不出错,是大部分错误在底层被自动处理了:
首先在我们看不到的地方,Claude Code 的 API 会进行重试(11 次指数退避),命令失败后模型自己换路径、测试失败后自己修复再跑。
在我们能看到的地方,Claude Code 支持了 Checkpoint/Rewind(改崩了可以回退)、fix-the-fix spiral 需要人工叫停。
核心启示: 最好的错误恢复是让用户感知不到错误发生过。但自动化有极限——当模型陷入"越改越烂"的循环时,最有效的干预者还是人类。好的 Harness 要让人类容易介入。
这和 OpenAI 的 Harness Engineering 理念一致:他们把 Linter 的错误信息设计为直接注入 Agent 上下文的修复指令——反馈循环是 Harness 的核心机制。
小结
- 失败是常态,不是异常——分层防御是关键
- 五类失败,四种策略——重试、回注、循环检测、降级各司其职
- 错误信息是工程产品——它的质量直接决定 Agent 的自愈能力
- 容错机制是 Architectural Constraints 在运行时的体现——用确定性代码防止 Agent 的错误无限扩散
下一篇讲可观测性——怎么"看见" Agent 在做什么。