智能体支付超时后为何不能直接重试
支付请求超时并不代表交易失败,智能体直接重试可能因接口缺乏幂等保护而重复下单。文章将网络故障、自动重试和异步结算的交汇处定位为需要专门处理的未知结果状态。
AI 深度解读
Agent 调用购买接口,等到超时就重试,看起来是在提高成功率,却可能把同一件商品买两遍。问题在于:没收到响应,只能证明客户端没拿到结果,不能证明商家没建单、资金没结算。
这篇文章讨论的就是这种「支付结果未知」:作者主张,在购买前留下持久记录,由商家执行去重,超时后先核对交易状态,再决定是否重试。对正在给 Agent 接入付费工具、订单接口的开发者,它提供了一套恢复思路,也交代了 SAAX 方案尚未做到的部分。
为什么一次超时会变成两笔订单
作者把问题拆成三个条件:Agent 遇到网络故障通常会进行有次数上限、带退避的重试;购买操作默认不幂等,第二次 POST 可能创建第二张订单;结算又是异步的,接口确认接单时,支付未必已经确认。
三者单独看都合理,组合起来就有麻烦。
假设商家已经接受订单,但响应在途中丢失。Agent 看见的仍然是超时,和「请求根本没送到」几乎一样。此时直接重试,可能重复购买;直接记为失败,又可能把真实发生的交易漏掉。
超时应该进入「结果未知」,不能直接归入「购买失败」。
还要区分两件事:订单是否创建,以及资金是否结算。原文提到 EIP-3009 风格的 nonce 授权,可以让链拒绝使用同一 nonce 的第二次结算,但商家可能在授权上链之前就接受了两张订单。因此,防止重复扣款和防止重复下单,需要分别处理。
为什么已有的去重措施仍有缺口
幂等键是最直接的办法,作者也认可它对 Agent 有效。前提是,同一次购买在重试、会话重启、跨进程执行时始终复用同一个键。
容易出错的地方,是恢复代码重新生成了键。客户端觉得自己在补做旧任务,服务端看到的却是新请求。即便键保存正确,调用方仍要查清第一次执行到了哪里,才能更新自己的订单记录。
运行时的工具调用去重也有类似边界。它需要稳定地识别「这是同一次调用」,但进程退出、上下文重置后,这个判断依据未必还在。
消费限额则只能控制损失。如果两笔重复购买的总额仍在限额以内,它甚至不会触发拦截。
作者认为,这些措施各自覆盖了一部分风险,缺少的是一份在尝试执行之前就写下、崩溃后仍可读取的记录。它既要让重复请求能够被识别,也要让恢复流程有依据可查。
购买前留什么,超时后查什么
作者提出的持久记录模式分为三步。
第一步,在执行前创建 commitment,可以理解为一份「购买承诺记录」。它包含购买意图、授权、交易条款、验收标准和恢复策略,并获得一个稳定 ID。同一购买意图的所有重试都携带这个 ID。
第二步,让商家的执行路径真正执行去重:已经处理过的 ID,再次到达时必须被拒绝重复执行。只在日志里记下 ID 没用,Agent、商家和结算通道需要围绕同一标识协作。
第三步,在结果未知时进行对账,也就是核对不同系统里的交易状态。原文要求同时检查链上结算状态和 commitment 记录:这个引用是否已经转过资金?这个 ID 是否还有执行中的任务?随后才决定能否重试。
如果链读取失败,或者记录存储也不可用,恢复流程依然缺少结论。作者没有给出完整的状态判定表,也没有说明每种状态组合该等待多久、怎样解除不确定性,只明确要求有限重试最终必须收敛到人工或恢复流程。
SAAX 将 commitment 作为购买流程的主要记录,把失败、超时、部分完成和争议纳入生命周期。但原文明确限定:恢复需要操作人员协助,只在特定崩溃边界做过演示,尚非自动恢复。
按原文披露的状态,x402/MPP 即时支付在 Base 主网处于公开 beta,采用非托管模式;托管资金的 escrow 仅为测试网预览;涉及治理工作的 Custody V3 候选版本仍在开发,尚未经过独立审查。这些是原文的状态说明,不能直接当作今天的产品进度。
我的判断
我赞同它最关键的提醒:支付工具不能照搬普通查询接口的重试策略。稳定标识、服务端去重、结果查询,确实应该一起设计。把未知结果保留下来,也比仓促写成失败更利于排查和交接。
但「持久记录」并不天然要求引入新协议。对于商家接口可控的团队,持久保存的幂等键、订单状态查询和明确的恢复流程,也可能覆盖同类需求。原文没有给出 SAAX 与这些做法的对照数据,无法据此判断它更省事或更可靠。
commitment 的价值取决于谁执行约束。如果商家没有接入去重,客户端再完整的记录也挡不住第二次建单。原文没有展开去重的并发实现,也未说明如何保证记录状态与实际执行保持一致,工程落地仍需补足。
此外,链上核对适用于原文讨论的支付路径。常规支付接口应查询相应渠道的交易状态,不能把「查链」当作通用步骤。
文章给出的是架构建议和有限边界的演示说明,没有重复购买率、故障注入覆盖率等量化结果。它适合作为设计检查项,还不足以证明某个产品已经解决恢复问题。
能拿来做什么
- 给 Agent 的购买工具增加持久化尝试记录,在请求发出前保存稳定 ID,并确保 Node 进程重启或任务恢复后继续复用它。
- 检查商家的订单创建接口是否真正按 ID 去重,同时提供结果查询能力,避免客户端只能在「再买一次」和「假定失败」之间选择。
- 将支付超时保留为待核对状态,让前端展示与后端恢复任务使用同一份状态依据;每次核对都记录查询结果、判断理由和下一步动作。
- 用测试端点模拟请求未到达、订单已创建但响应丢失、执行中进程退出等情况,验证同一购买意图不会重复建单,并确认无法判定时能够停止和转交处理。