恢复要有分级和熔断
恢复按对用户透明的程度分级,能低级别解决就不升级;每条恢复路径都要有来自生产数据的熔断上限,否则恢复逻辑自己变成故障源。
恢复不是「再试一次」,是一套有级别、有上限、有出口的机制:能低级别解决就不升级,每条路径都要有熔断,错误处理逻辑自己不许再制造错误。阈值从哪来?答案是生产数据,不是拍脑袋。
三级恢复,逐级透明
第一级静默重试:可重试错误的默认动作。两个细节决定成败——指数退避叠加随机抖动,避免大量客户端同步重试造成二次拥塞,并尊重服务端返回的等待时长提示;区分前台与后台调用,主循环失败要重试,标题生成这类辅助后台调用失败直接放弃,否则后台重试挤占主链路配额,形成「重试放大」ai-agent-book-5。第二级降级与接续:输出触顶被截断,先静默提升输出上限重发,仍不够就在消息末尾追加元指令让模型从断点接续;主模型持续过载就降级到备用模型——前提是剥离旧模型私有的格式块,否则新模型无法解析历史消息。第三级才暴露给用户,并附上已经尝试过的恢复动作。工具层错误另走一条路:不终止会话,把结构化的错误结果喂回上下文,让模型下一轮自行纠正——错误喂得越具体,自我纠正成功率越高。
熔断上限要从生产数据里来
上一条给了每条路径独立的计数器,这一条消费它:每条恢复路径都必须有明确的熔断上限——上下文压缩连续失败若干次就放弃压缩,权限分类连续失败就回退到人工询问,输出接续最多尝试固定轮数 ai-agent-book-5。阈值怎么定?Claude Code 的压缩熔断取「连续 3 次」,依据是真实会话统计:曾有一个会话在这条路径上连续失败三千余次,仅这类无效重试每天就在全球造成约 25 万次 API 调用的浪费;逾千个会话出现过 50 次以上的连续失败。3 次正是「绝大多数故障在此之前已恢复」与「继续重试基本无望」之间的经验拐点。自己系统里的拐点,同样只能从计数器的真实分布里读——这也是上一篇要求每条路径独立计数的原因。
恢复逻辑自己也会造成故障
比单点失效更隐蔽的是死亡螺旋:错误处理路径里的逻辑又调用 LLM,再次出错,引发连锁。真实发生过的案例——Agent 因上下文溢出而停止,触发「结束时自动提交代码」的停止钩子,钩子调用 LLM 生成 commit message,再次上下文溢出,又一次触发钩子 ai-agent-book-5。防护靠两条:在错误路径上禁用一切会再次调用模型的副作用逻辑,宁可丢掉一次自动记忆提取这样的辅助功能;用递归深度计数器检测并打断残余连锁。在所有单点机制之上,还需要全局的终止与升级条件:最大迭代轮数、会话预算上限、连续失败超阈值转人工。重试上限不是经验值,是架构决策——第四次尝试仍失败时系统怎么办,决定它是安全失败还是隐藏错误:面向用户的场景通常优雅降级——一个安全但普通的回复总好过报错;内部流程宁可明确失败,下游需要知道 Agent 已经耗尽重试;高风险任务连续三次生成失败后继续自动输出通常都是错的 agents-in-action-7。
中间错误不该越过恢复循环
核心原则一句话:错误处理的边界不是单次请求,而是整个恢复循环 ai-agent-book-5。在确认无法恢复之前,中间错误不暴露给消费者——无论用户还是订阅事件的下游:恢复期间扣留错误,恢复成功则消费者毫无感知,全部手段失败后才统一呈现。做不到这条,用户会在恢复成功后仍看到一堆报错弹窗,下游系统会把已恢复的瞬时故障当成任务失败。成本视角同样成立:被扣留的重试照样烧 token,成本要能归因到每一步 说总量一个数分不清「Agent 变好了还是开始更多重试」,恢复循环就是那个藏起来的花销项。
换供应商不是换个地址
主模型持续不可用时,要换一家把这条轨迹接着跑完。真正的障碍不是接口地址:思考内容由可读文字和厂商签发的凭证两部分组成,文字换一家仍读得懂,凭证换一家就失效——带得走的是文字,带不走的是凭证 ai-agent-book-5。接管方案只能按最严格厂商的要求设计,并留退路:把历史工具调用改写成文字叙述,模型不再当作真实调用,但至少能接着跑。由此的设计原则是轨迹按中立格式存储:思考拆成可移植文字与不可移植凭证,工具调用只记名称与参数,切换时凭证一律丢弃。同一份中立轨迹还服务评估重放和经验提取——故障切换只是它最省钱的那个用途。
