跳到正文
Elaine Blog
返回

工具调用失败以后:超时、重试、幂等与取消

更新于:
Tool Calling 与 MCP

应用向退款服务发出请求,等了十秒后超时。模型没有收到成功结果,便再次请求退款。看起来很合理,但第一次请求可能早已受理,只是响应在网络中丢失。

**超时描述的是调用方没有按时得到结果,不是业务系统证明什么都没发生。**工具执行一旦涉及外部状态,就必须把通信结果与业务结果分开。

先识别失败属于哪一类

非法订单号通常可以修正参数;权限拒绝需要停止越权调用;余额不足或订单关闭是业务拒绝;暂时不可用可能适合有限重试;已经发出写请求却没收到结果,则可能处于未知状态。

统一把这些错误写成 retryable=true,会让模型不断尝试本来不该重复的动作。应由执行器和业务契约决定重试方式,模型可以解释错误或补齐参数,但不能自行给写操作提供幂等保证。

状态可以是 planned、submitted、succeeded、rejected、unknown。unknown 不代表永久失败,它提示后续先查询业务操作结果。若查询也不可用,可以报告处理中或转人工核实,不能编造“已撤销”。

幂等在业务上意味着什么

对于同一逻辑操作,多次请求应产生同一业务效果,而不是多扣几次钱。它并不要求每次 HTTP 响应字节完全相同,第二次可以返回已有操作结果。

业务操作 ID 由可信应用在创建具体意图时生成。重复传输同一意图保留 ID,新的合法部分退款使用新 ID。用户修改金额或收款对象,不能继续借旧 ID 改写已经批准的操作。

订单 A1042 可以先退 100 元,再退 50 元。这是两个合法操作,订单号只标识对象,不足以标识意图。反过来,模型重新生成 call_02 也不能自动成为第二次退款的依据。

相同 ID 配不同参数怎么办

执行端保存操作参数的规范化表示或指纹。第一次提交 op-9 对应 A1042、10000 分、CNY;第二次 op-9 携带 20000 分,应该返回幂等冲突,而不是覆盖原记录。

规范化需要明确字段和单位。哈希只是便于比较,不能替代业务授权,也不能自动匿名化低熵参数。幂等键还应有主体范围,避免不同租户恰好使用相同键时互相命中。

approval_runtime.py下载 用内存账本演示参数绑定和重复返回。它不宣称具有生产持久性;进程退出后账本消失,跨进程竞争也需要外部存储解决。

为什么内存集合不能保证只执行一次

假设代码先检查 op_id not in done,再执行退款,最后把 ID 放入集合。两个线程可能同时通过检查;也可能退款成功后、写集合前崩溃。重启后看不到记录,就会再次执行。

数据库唯一键可以原子占用一个操作身份,但占用成功与外部支付成功之间仍有空隙。常见设计是保存操作意图,由执行任务使用支付服务认可的幂等键提交,并记录回执;未知结果通过同一操作 ID 查询和对账。

如果下游根本没有幂等或结果查询能力,不能仅在上游包一层重试就承诺 exactly-once。需要限制自动重试、人工核实,或重新设计业务接口。

有限重试怎样避免放大故障

对于允许重试的读取,可使用指数退避与随机抖动,避免所有请求同一时刻再次冲击服务。假设最多三次、初始间隔 0.2 秒,等待可逐步增加,同时不超过任务剩余时间。这些参数需要根据服务能力调整。

如果 SDK 重试三次,工具执行器重试三次,工作流再重试三次,最坏情况下可能放大到二十七次底层尝试。应明确哪一层拥有重试预算,并把剩余次数和截止时间传递下去。

HTTP 429 或 503 并不自动证明任意写操作可以重试。需要结合服务定义、响应时点和幂等机制。若后端提供 Retry-After,读取重试也要尊重剩余总预算。

取消不等于回滚

用户点击停止后,可以停止继续发出新调用,并尝试取消正在等待的请求。但底层服务器可能已经受理,Python 取消 await 也不一定能终止正在运行的线程或远程任务。

取消前已成功创建的草稿可以根据业务提供的删除或作废接口处理;已受理退款未必可撤回。应查询真实状态,再展示“停止继续处理,但操作 op-9 的结果仍待确认”等准确说明。

长任务最好返回业务 handle,支持后续查询状态。这个 handle 需要授权,不能因为它是随机字符串就默认任何知道它的人都能读取。

多步流程怎样处理部分成功

创建售后单成功、安排取件失败,系统已经处于部分成功状态。补偿可以是取消售后草稿,也可能是保留售后单并让用户重新选择时间,取决于业务语义。

补偿本身也是新的操作,也会失败,也需要记录。不能把“调用了补偿函数”当成原状态必然恢复,更不能让模型生成一句“已恢复”替代结果确认。

本文的 failure_scenarios.py下载 模拟后端已记录成功但调用方超时,随后通过稳定操作 ID 找回结果。它不会实际等待或调用支付服务,专门用于观察未知状态怎样被消除。

正确的失败处理最终应让用户知道:哪些动作已完成、哪些未完成、哪些结果尚不确定。它比笼统的“工具调用失败,请重试”更能支持任务继续。

继续阅读

上一篇:一次工具调用怎样完成:执行循环、结果回填与多工具协作

下一篇:工具什么时候可以执行:授权、审批与可恢复工作流

下载文件、依赖与运行边界见配套指南下载


分享这篇文章:

上一篇
一次工具调用怎样完成:执行循环、结果回填与多工具协作
下一篇
工具什么时候可以执行:授权、审批与可恢复工作流