Agent 工具调用失败怎么办?从错误分类、超时接管到幂等重试的工程指南
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,服务端就可能把它们当作两个不同操作。
以创建订单为例,推荐的恢复过程是:
- 应用先建立本次业务操作记录,保存操作标识和稳定的请求参数。
- 第一次提交时,把该标识用于服务端支持的幂等机制。
- 发生超时后,把状态记为“结果未知”,保留原标识。
- 通过业务状态查询核对;需要重发时,按服务端约定复用原标识和原参数。
- 只有收到明确结果,或完成核对后,才更新本地状态。
操作记录和幂等保障需要由应用实现,不能只靠提示词或模型自行记忆。
还有几个不能省略的限制:
- 服务端必须真正支持幂等;给任意接口添加一个同名 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]
最后,一套实用的失败处理流程可以压缩为:
先确认有没有发生操作;可以安全重复的临时错误,有限退避重试;参数错误,给模型具体反馈;权限和额度问题,停止并交由外部处理;结果未知的写操作,查询或在已有幂等保障下恢复;超过预算,明确退出。
参考资料
- OpenAI:A practical guide to building agents:失败阈值、高风险操作与人工接管。
- Anthropic:Building effective agents:环境反馈、停止条件与 Agent 设计。
- OpenAI:Function calling:应用执行工具、严格参数模式。
- OpenAI:Error codes:限流与额度、账单错误。
- AWS:Control and limit retry calls:重试上限、退避、抖动和多层重试。
- OpenAI 官方 Python SDK:自动重试与超时配置。
- Anthropic:Writing effective tools for agents:工具设计、可操作的错误反馈和评估指标。
- Claude:Handle tool calls:工具结果及
is_error。 - MCP 工具规范,2025-06-18 版本:协议错误、执行错误与安全要求。
- AWS:Timeouts, retries, and backoff with jitter:超时不代表副作用没有发生。
- Python:subprocess:不同执行接口的超时和进程清理行为。
- Anthropic:How we built our multi-agent research system:生产系统的故障恢复与状态保存。
- AWS:Making retries safe with idempotent APIs:请求标识、参数一致性与核对。
- Stripe:Idempotent requests:幂等键的具体服务约定。
- τ-bench 论文,Shunyu Yao 等,2024;后发表于 ICLR 2025:最终状态验证与重复执行可靠性。
- Anthropic:The “think” tool:Claude 3.7 Sonnet 在复杂工具任务中的实验。
原文发布于 SunAI 论坛。
术语与实现细节补充见 原帖评论。
最后更新于 2026-10-09
评论 0