博客
可靠性与生产环境

发布于 更新于

Anshu 和 Shouryamaan

AI Agent 故障恢复:重试、检查点与人工审批

以 Markdown 阅读

AI agent 故障恢复负责决定失败步骤应该停止、重试、核对结果、等待审批、执行补偿,还是从检查点恢复。具体选择取决于错误类别,以及外部影响是否可能已经发生。

只有操作契约能保证重复安全时,自动重试才安全。超时并不能证明操作失败。

先对故障分类,再采取行动

故障 默认处理方式
输入或 schema 无效 停止并修正请求
身份验证或授权失败 停止并请求有效权限
策略拒绝 停止或请求指定审批
速率受限并返回重试时间 等待后在操作预算内重试
临时读取失败 采用有限退避重试
写入超时且结果未知 重试前先核对结果
提供商永久失败 失败,或使用文档约定的备用路径
Worker 崩溃 从持久化状态恢复
多系统只完成一部分 按策略继续、补偿或升级处理

工具应返回稳定错误码。不要让模型从“发生错误”之类的文本中推断重试是否安全。

一次逻辑写入只使用一个操作 ID

在高影响调用前创建操作记录,保存操作、租户、资源、规范化输入 hash、幂等键、状态、尝试次数、提供商引用和结果。

同一逻辑影响的所有重试都复用相同幂等键,不同参数复用时应拒绝。Stripe 的幂等请求文档展示了服务端如何为重复键返回已存结果。其保留规则只适用于该提供商,因此你的有效期应覆盖 agent 可能遇到的最长实际恢复时间。

如果提供商不支持幂等性,操作表可以防止两个本地 worker 主动重复发起操作,却无法判断提供商执行后丢失响应的情况。应增加提供商查询、Webhook 或人工核对步骤。

为已经验证的进度建立检查点

在系统验证外部影响后建立检查点,而不是在模型声称完成后。保存提供商标识符或操作引用。恢复时,应在再次调用模型前加载检查点和权威后端状态。

持久执行指南介绍了工作流历史、确定性重放和持久等待。故障恢复则为每种状态补充运维决策。

为每类重试指定唯一责任方

HTTP 客户端、队列、工作流引擎、模型 SDK、工具和提供商都可能重试。每类故障应选择一个责任方,并将所有尝试归入同一项操作。

设置最大尝试次数、最长时间、退避方式和终态。遇到校验、授权和策略失败时停止。对于模型调用,还要决定重试是沿用相同提示词和工具,还是形成一次新决策,并记录这项区别,因为它会影响评估。

核对结果未知的操作

写入超时时:

  1. 将操作标记为 unknown,而不是 failed;
  2. 根据幂等键、提供商引用或预期业务状态查询;
  3. 如果影响存在,将其标记为已完成;
  4. 只有提供商确认没有发生时才重试;
  5. 两种结果都无法确定时请求人工审核。

不要用成功消息掩盖未知状态。核对期间,用户可能需要避免重复提交请求。

在尝试高影响操作前审批

审批应绑定操作、资源、参数、执行者和过期时间。恢复执行时重新检查授权。“继续”之类的宽泛审批不能覆盖参数已经变化的付款或删除操作。

Railway 的 agent 删除事故促使其将 API 删除改为保留 48 小时的软删除。可恢复操作能减轻恢复压力,但仍然需要范围受限的身份和审计记录。

区分取消与补偿

取消会阻止后续工作,却无法撤回已经发送的邮件、付款或外部发布。补偿是作废发票或恢复软删除资源等独立操作。

补偿需要自己的授权、幂等性、操作记录和失败路径。多个外部系统没有共享事务时,不要将补偿描述为自动回滚。

编写人工可执行的运行手册

对每条高影响工作流记录:

  • 如何停止新运行和活跃 worker;
  • 应撤销哪项凭据;
  • 如何找到范围内的任务和操作;
  • 如何对未知结果分类;
  • 哪些重试安全;
  • 哪些影响可以补偿;
  • 由谁审批恢复,以及如何验证完成。

将运行手册关联到 trace 和操作查询。可观测性指南列出了端到端追踪事故所需的标识符。

在关键位置演练故障

分别在调用前、提供商收到请求后、成功但响应返回前、检查点之后、审批期间和取消期间注入故障。使用没有本地状态的新 worker 恢复,并验证影响次数和最终业务状态。

下方的提示词会在不触碰生产的情况下设计最有价值的演练。如果运行手册无法区分“失败”和“可能已成功”,应先修复该分支,再提高自主程度。