你的 AI 代理今天正常工作,明天可能就因为重复支付烧掉几百 U,而且你根本不知道。
上周一个朋友跑过来给我看他的代理日志:一个简单的链上数据拉取任务,网络抖动了一下,代理重试了 3 次,x402 扣了 3 次钱,但数据只拿到了一份。他说"我设了单笔限额啊,每笔才 0.5 U,怎么就没了?"问题不在单笔金额,在次数。一个陷入重试循环的代理,每分钟可能发出几十上百笔小额支付,累积起来几分钟就能烧光预算。
x402 没有协议层面的退款机制。一旦扣款成功,钱回不来。所以你需要的是"幂等"——同一件事,做一百次也只扣一次钱。
概念拆解:为什么代理容易重复扣款
先搞清楚钱是怎么被重复扣的,再动手。
场景还原:
- 代理发起请求,服务器返回 402(需要付钱)。
- 代理签名、转账、带着支付凭证重试。
- 服务器扣款成功,返回数据。
- 网络丢包,代理没收到响应,以为失败了。
- 代理重新发起请求——再次走了一遍完整的支付流程。
关键点:x402 的每笔支付凭证是一次性的。但如果代理没有"记住"这笔交易已经完成,它就会重新生成凭证、重新扣款。
两个核心概念:
幂等键(Idempotency Key):一个唯一字符串,代表"这次要做的具体事情"。比如
task_123:get_eth_price:v1。代理在第一次请求时带上它,服务器记录"这个键已经付过钱了"。重试时,服务器看到同一个键,直接返回上次的结果,不再扣款。断路器(Circuit Breaker):监控支出速度,不是单笔金额。如果代理在短时间内(比如 1 分钟)花了超过阈值,暂停支付并报警。防止重试循环悄悄烧钱。
对比选择:三种防重复方案
| 方案 | 适用场景 | 工作量 | 防护级别 |
|---|---|---|---|
| 幂等键(应用层) | 自己有后端,能改代码 | 低 | 防止同一逻辑任务重复扣款 |
| SDK 内置幂等(如 StableOps Agent SDK) | 使用现成代理支付框架 | 极低 | SDK 自动处理重试幂等 |
| 重放检测中间件(如 Presidio 的 Replay Guard) | 高安全要求,多实例部署 | 中 | 基于支付指纹防重放,跨进程去重 |
参考资料:
- 幂等键模式:HTTP x402 小额支付工程化通用方案
- StableOps SDK:支持
idempotencyKey参数,重试时复用签名 - Presidio Replay Guard:支持 Redis 跨进程去重,TTL 可配置
下一步动作:三行代码解决 80% 的问题
如果你用的是 Node.js 且自己控制请求逻辑,最直接的做法:
步骤 1:为每个付费动作生成一个幂等键
const idempotencyKey = task_${taskId}:action_${actionType}:v1步骤 2:带上它发起请求
如果用 StableOps Agent SDK:
const result = await payments.x402Fetch('https://api.example.com/paid', {idempotencyKey: 'task_123:paid-resource:v1'})如果自己手搓:
- 在请求头或请求体中带上
Idempotency-Key: xxx - 服务端根据这个键判断是否已经处理过
步骤 3:服务端记录已结算的幂等键
if (await ledger.has(idempotencyKey)) {return ledger.get(idempotencyKey) // 直接返回上次结果,不扣款}// 正常扣款流程await ledger.record(idempotencyKey, receipt)完成标准: 重试同一请求时,返回的是 200 OK 而不是新的 402,且钱包没有多出一笔扣款记录。
情况分支
情况 A:你用 StableOps 或类似框架
- 直接在用
x402Fetch时传idempotencyKey参数。SDK 会自动处理重试复用签名。
情况 B:你自己实现 x402 客户端
- 需要自己维护一个"已结算幂等键"的存储(Redis 或数据库)。重试时先查这个存储,有就直接返回结果。
情况 C:你是 API 提供方(被代理调用)
- 在服务端实现幂等键检查。收到请求先看
Idempotency-Key,如果已经处理过,返回缓存结果而不是重新扣款。Rootstock 的文档建议用 Redis 存储已用过的交易哈希,TTL 设 30 天。
高危提醒:单笔限额挡不住重试循环。代理每分钟发 60 笔 0.5 U 的请求,单笔都在限额内,但一小时能烧掉 1800 U。必须加支出速度监控。
操作完成的校验方式
跑一个测试:让代理执行一个会触发重试的任务(比如故意把目标服务搞挂几秒,再恢复)。观察:
- 钱包扣了几笔?
- 日志里的
idempotencyKey是否重复出现且返回了缓存结果? - 如果用了断路器,支出速度是否触发了暂停?
核验渠道: 查看代理的审计日志或钱包的交易历史。应该有且仅有一笔 settled 状态的支付记录对应这个 idempotencyKey。



