Wood Chen

Agent 工具调用失败怎么办?从错误分类、超时接管到幂等重试的工程指南

0 评论0 阅读4.5k 字

Agent 调用工具失败后,不能只给它加一句“失败就重试三次”。查资料时多试一次,可能只是多花几秒;发邮件、创建订单、执行部署时多试一次,却可能真的做两遍。

更可靠的处理顺序是:先判断哪里失败、操作是否已经发生,再决定等待重试、修改参数、查询状态,还是停止并交给人处理。

OpenAI 和 Anthropic 的官方指南都要求为 Agent 设置退出条件、失败边界和人工接管机制。具体到退避、进程清理和防重复执行,还需要沿用分布式系统的工程方法。[1][2]

一、先分清:模型请求失败,还是工具执行失败?

一次工具调用通常有几个环节:应用请求模型,模型给出工具名和参数,应用执行工具,再把结果交回模型。

因此,“Agent 报错”至少可能发生在这些位置:

失败位置 常见表现 首先检查什么
模型 API 限流、余额不足、请求过大、服务异常 API 错误码、请求 ID、额度与请求大小
工具调用格式 工具不存在、缺少字段、类型不符 工具定义、参数校验、协议格式
工具运行环境 网络断开、命令卡住、依赖不可用 连接状态、进程状态、执行日志
业务操作 库存不足、订单状态不允许、无权限 业务规则和实际状态
结果回传 执行完成,但响应丢失或会话中断 执行记录、任务 ID、业务对象是否已创建

OpenAI 的 Function calling 文档明确把工具执行放在应用侧。模型提出调用,并不等于模型 API 替应用完成了业务操作。[3]

这一区分直接影响恢复方式:重新请求模型,不能代替检查上一次订单是否已经创建;工具参数错误,也不应该靠反复请求同一个外部服务解决。

二、错误类型和操作风险,要分开判断

“网络错误”“参数错误”“超时”描述的是失败情况;“是否会扣款、是否会修改数据”描述的是操作属性。它们不是互斥的四种错误。

同样一次网络超时,读取天气和创建付款的处理方式就不同。

建议按下面的表确定第一步。实际允许哪些错误自动恢复,应由工具实现和服务接口约定决定,而不是只看 HTTP 状态码。[4][5]

情况 默认处理 不应该做什么
临时限流、短暂服务不可用 在确认可以安全重复后,有限退避重试 立即连续发送相同请求
缺字段、参数非法 返回具体错误,让模型修正后重新提交 原参数原样重放
余额不足、权限不足 停止相关操作,提示需要外部处理 让模型反复尝试绕过限制
超时或响应丢失 先确认执行状态 直接认定“没有执行”
写入操作且结果未知 查询状态,或在已有幂等保障下恢复 换一个新请求标识再试
超出恢复预算 停止、降级或人工接管 一直循环到“成功”为止

一个容易误判的例子是 429。OpenAI 的错误文档区分了请求速率受限和额度、账单限制;后者需要先调整额度或账单条件,等待几秒并不会恢复访问。[4]

三、瞬时错误可以重试,但需要边界

对于接口明确允许安全重复的请求,临时故障适合退避重试。AWS 的工程资料建议使用指数退避、随机抖动,并限制重试次数或累计时间,避免服务已经过载时再增加压力。[5]

一套可落地的配置应包含:

  • 哪些错误允许重试,哪些必须立即停止。
  • 单次调用的超时。
  • 最大尝试次数,以及整个任务的截止时间。
  • 等待间隔的上限和随机化规则。
  • 服务端给出的等待提示如何处理。
  • 重试预算耗尽后,返回什么状态、交给谁处理。

例如,可以把等待时间设计为 random(0, min(cap, base × 2^n))。这是实现选择,不是所有工具必须采用的统一公式。服务端返回有效的 Retry-After 时,应结合接口约定和剩余任务时间安排等待;如果需要等待的时间超过任务预算,就应结束本轮或安排稍后恢复,而不是继续占着执行槽位。

还要检查 SDK 是否已经自动重试。OpenAI 官方 Python SDK 文档说明,部分连接错误、408、409、429 和服务端错误默认有自动重试行为。它针对的是模型 API 请求,不能据此推断自己的付款工具也能安全重试。[6]

如果 SDK、工具封装和 Agent 外层各自都允许最多三次尝试,三层嵌套最坏可能形成 27 次底层请求。这个数字是配置示例,不是某个框架的默认行为。AWS 明确提醒不要在多个层级叠加重试,建议选择合适的一层统一控制。[5]

四、参数错了,应该让模型改;权限错了,应该停

确定性错误的共同点是:在条件不变的情况下,原样再试通常不会变好。

但“回传给模型”不等于“模型都能修好”。

缺少日期、传错枚举值,可以给出字段要求,让模型修正。余额不足、账号无权限、缺少用户授权,则需要停止相关操作或请求用户处理。模型不应该为了完成任务,自行改账号、扩大权限或绕过审批。

Anthropic 建议把工具错误写成可操作的反馈,指出具体问题和允许的下一步,而不是只返回一个 failed 或大段堆栈。[7]

例如,创建日程失败后,可以返回:“结束时间早于开始时间;本次未创建日程。请检查两个时间字段。”这比“参数错误”更容易帮助模型恢复。

对于输入格式,OpenAI 推荐使用严格模式约束工具参数,使调用符合声明的结构。但符合结构不代表符合业务:一个金额可以类型正确,却超过允许的上限;一个订单 ID 可以格式正确,却属于其他用户。应用仍然需要验证业务条件和权限。[3]

错误标记也不是跨平台统一的:Claude 的客户端工具结果可以使用 is_error: true,MCP 的工具执行错误使用 isError: true;OpenAI 的函数结果则按其 API 格式回传。这些字段不能直接互换。[8][9][3]

五、超时后,先确认执行状态

超时只说明等待方没有按时拿到结果,不说明操作没有发生。 AWS 的重试资料特别提醒,调用超时或失败时,副作用可能已经发生。[10]

对本地命令和远端接口,需要分别处理。

本地命令:取消等待,不一定会结束进程

以 Python 为例,Popen.communicate(timeout=...) 超时后不会自动杀死子进程;官方文档要求应用在异常后清理进程并完成输出收集。另一种接口 subprocess.run(timeout=...) 的行为不同,不能把某个接口的行为推广到全部执行器。[11]

对短命令,工程上可以采用明确的终止流程:请求正常退出,超过宽限期后再强制结束,并回收输出和执行状态。涉及 shell、子进程或进程树时,还需要执行器按操作系统实现相应的清理。

但终止进程也不等于撤销已完成的修改。命令可能已经写了一半文件,或者向远端发出部署请求。恢复前仍要检查实际状态。[10]

长任务:从启动时就交给可查询的任务系统

构建、批量测试、数据导出等耗时任务,可以从启动时就由任务管理器托管,返回任务 ID,再查询状态、日志和结果。

推荐至少区分“已受理”“运行中”“成功”“失败”“已取消”;无法确认最终结果时,保留“结果未知”,不要伪装成失败或成功。这能让应用知道自己下一步能安全做什么。

所谓后台接管,也不是发生超时后再随手补一个 &。执行环境必须提前支持任务持久化、状态查询、取消和资源回收。否则只是让用户看不到进程,并没有解决任务管理。

Anthropic 在多 Agent 研究系统的工程总结中提到,长时间运行的系统需要保存状态并支持从故障中恢复,而不是每次故障都从头重启。[12]

远端操作:优先查询业务状态

创建订单、发邮件、提交部署等接口超时后,应先用已有的订单号、任务 ID 或业务请求标识查询状态。查询暂时没有结果,也未必就能证明原请求没有到达;如果接口没有防重复执行的约定,结果未知时应暂停并核对。[13]

六、有副作用的工具,幂等保障必须在第一次执行前准备好

发送邮件、创建工单、退款、发布帖子,和付款一样,都可能因重试而重复执行。

同一个业务操作的重试,需要复用同一个幂等键;新的业务操作才使用新键。 AWS 关于幂等 API 的资料说明,请求标识应在重试过程中保持一致,服务端也需要识别相同标识对应的请求。[13]

如果模型超时后重新发起调用,而应用每次都生成新 key,服务端就可能把它们当作两个不同操作。

以创建订单为例,推荐的恢复过程是:

  1. 应用先建立本次业务操作记录,保存操作标识和稳定的请求参数。
  2. 第一次提交时,把该标识用于服务端支持的幂等机制。
  3. 发生超时后,把状态记为“结果未知”,保留原标识。
  4. 通过业务状态查询核对;需要重发时,按服务端约定复用原标识和原参数。
  5. 只有收到明确结果,或完成核对后,才更新本地状态。

操作记录和幂等保障需要由应用实现,不能只靠提示词或模型自行记忆。

还有几个不能省略的限制:

  • 服务端必须真正支持幂等;给任意接口添加一个同名 HTTP 头不会自动生效。
  • 相同 key 对应的参数通常需要保持一致。改变金额或收件人,不能继续假装是原请求的重试。
  • 服务端必须处理并发重复请求,不能只有“先查缓存、再执行”的松散逻辑。
  • key 的保留时间、接口范围和失败结果处理方式,都要按具体服务约定确认。

Stripe 提供了具体例子:它会保存某个幂等键首次进入执行后的状态码和响应体,后续同键请求可返回相同结果,包括 500;记录达到其保留条件后可能被清理。因此,幂等机制不是“重试一定成功”,也不是永久有效的去重凭证。[14]

如果底层服务不支持幂等,只在 Agent 这一侧加缓存,并不能完整覆盖“远端成功、本地还没来得及记录就崩溃”的窗口。需要结合可查询的业务标识和核对机制;无法确认时,停止比再次提交更安全。[13]

七、模型负责调整计划,执行层负责守住边界

根据 OpenAI、Anthropic 的指南,可以把职责整理为下面的工程分工,而不是把所有恢复逻辑都塞进提示词。[1][2][7]

执行层应强制保证 模型可以决定
输入和权限校验 根据明确错误修正参数
超时、取消、重试预算 选择允许使用的替代工具
幂等键和业务状态保存 缩小查询范围、拆分任务
高风险操作的确认机制 解释阻塞原因、向用户补问
操作日志与结果查询 根据已验证的状态调整后续计划

应用可以告诉模型“最多尝试两次”,但也应在执行层真的拦住第三次。尤其是换个工具名、换个会话、换个子 Agent 后,不能重新获得一份无限预算。

OpenAI 的 Agent 指南把超出失败阈值和高风险操作列为人工介入的典型触发条件;Anthropic 的指南则要求 Agent 持续从工具结果获得实际反馈,并设置最大迭代次数等停止条件。[1][2]

八、研究如何评估工具调用的可靠性?

对 Agent 可靠性,独立研究 τ-bench 提供了更直接的评估思路:它模拟用户与工具 Agent 的多轮交互,通过对比最终数据库状态与目标状态判断任务是否完成,还考察同一任务多次执行的一致性。[15]

论文在 2024 年所测试的配置中发现,工具 Agent 的完成率和重复执行的一致性仍有明显不足。这是当时特定模型、提示和任务的实验结果,不是今天所有模型的能力上限。

Anthropic 的 “think” tool 实验则研究了 Claude 在复杂工具使用中增加中间思考步骤的效果。在其 Claude 3.7 Sonnet 航空领域配置里,优化提示后的单次通过指标从 0.370 提高到 0.570,属于该实验条件下的结果。[16]

这项实验说明,模型处理工具结果和业务规则的方式会影响完成率;它没有验证幂等协议,也不能证明让模型多想一会儿就能安全处理重复写入。

实际评估不应该只看 Agent 最后有没有说“完成”,还应检查最终数据是否正确、有没有多发邮件或重复创建对象、是否在预算内停止。[15][7]

九、上线前,至少测试这些故障

上线前,可以按下面的清单做故障注入测试:

测试情境 应检查的结果
临时限流后恢复 等待后有限重试,没有请求风暴
额度耗尽或权限不足 停止调用,没有反复原样提交
缺字段、字段值非法 错误能帮助模型修正,未发生写入
本地命令一直运行 按执行器策略结束或托管,资源可回收
远端写入成功,但响应丢失 核对后确认成功,没有创建第二份对象
同一业务操作被两个 Agent 同时提交 服务端仍满足约定的防重复要求
应用执行到一半崩溃 恢复时保留业务标识,不盲目重新提交
用户中途取消 停止新增动作,报告已发生和尚未发生的操作

日志至少应能关联任务、工具调用、业务操作标识、耗时、错误类型、重试次数和最终确认状态。记录时还要处理密钥和个人信息,不能为了排障把完整凭据写进日志。

Anthropic 建议同时收集任务准确率、调用耗时、工具调用次数、token 消耗和工具错误;MCP 规范也要求考虑输入校验、敏感操作确认、超时和审计记录。[7][9]

最后,一套实用的失败处理流程可以压缩为:

先确认有没有发生操作;可以安全重复的临时错误,有限退避重试;参数错误,给模型具体反馈;权限和额度问题,停止并交由外部处理;结果未知的写操作,查询或在已有幂等保障下恢复;超过预算,明确退出。

参考资料

  1. OpenAI:A practical guide to building agents:失败阈值、高风险操作与人工接管。
  2. Anthropic:Building effective agents:环境反馈、停止条件与 Agent 设计。
  3. OpenAI:Function calling:应用执行工具、严格参数模式。
  4. OpenAI:Error codes:限流与额度、账单错误。
  5. AWS:Control and limit retry calls:重试上限、退避、抖动和多层重试。
  6. OpenAI 官方 Python SDK:自动重试与超时配置。
  7. Anthropic:Writing effective tools for agents:工具设计、可操作的错误反馈和评估指标。
  8. Claude:Handle tool calls:工具结果及 is_error。
  9. MCP 工具规范,2025-06-18 版本:协议错误、执行错误与安全要求。
  10. AWS:Timeouts, retries, and backoff with jitter:超时不代表副作用没有发生。
  11. Python:subprocess:不同执行接口的超时和进程清理行为。
  12. Anthropic:How we built our multi-agent research system:生产系统的故障恢复与状态保存。
  13. AWS:Making retries safe with idempotent APIs:请求标识、参数一致性与核对。
  14. Stripe:Idempotent requests:幂等键的具体服务约定。
  15. τ-bench 论文,Shunyu Yao 等,2024;后发表于 ICLR 2025:最终状态验证与重复执行可靠性。
  16. Anthropic:The “think” tool:Claude 3.7 Sonnet 在复杂工具任务中的实验。

原文发布于 SunAI 论坛。

术语与实现细节补充见 原帖评论。

最后更新于 2026-10-09

相关文章

评论 0