跳到主内容

智能体执行写操作怎么不重复下单:幂等键、补偿动作与对账清单

100%
智能体执行写操作怎么不重复下单:幂等键、补偿动作与对账清单

智能体重复下单基本不是模型的问题,而是「重试、并行、超时」三件事叠加的必然结果;解决办法不在提示词里,而在工具层——给每个写操作配幂等键、预检、补偿动作和对账,四件套缺一件,重复动作迟早会发生。

重复动作从哪来

三个来源,单独看都不难理解,叠在一起就防不住:

  • 结果丢失后的重试:退款已经成功,但网络在返回结果前抖动了一下。智能体认为失败,于是再调一次,第二笔退款真实发生;
  • 并行调用同一动作:为了提速让多个工具并行执行,两个分支都判断「还没下单」,于是各下一单;
  • 超时后的重新发起:调用超时,智能体不知道服务端到底执行了没有,只能重来一次。

共同点是:智能体并不知道这次调用到底成没成功。它在猜,而猜的代价由业务承担。所以正确的位置是工具层——让重试天然安全,而不是让模型学会谨慎。

四件套之一:幂等键

每个有副作用的工具都接受一个 idempotency_key 。同一个键重复调用时,直接返回首次的结果,不重复执行动作:

async function sendEmailTool(input) {
  const key = sha256(JSON.stringify(normalize(input)));
  const existing = await db.toolCalls.findFirst({
    where: { key, tool: "send_email" }
  });
  if (existing?.result) return existing.result;

  const result = await actuallySend(input);
  await db.toolCalls.create({
    data: { key, tool: "send_email", result, createdAt: new Date() }
  });
  return result;
}

三个设计要点:

  • 键由调用方生成,工具层校验:不要让工具自己随机生成,否则重试时键不同,等于没做;
  • 入参要规范化后再哈希:字段顺序、空格、大小写差异都会让同一个意图算出不同的键;
  • 记录要落库并设置保留期:内存里存一份没有意义,进程重启就失效了。

键的构成建议是 工具名 + 业务域 + 规范化入参哈希。纯用入参哈希在「同一分钟内确实要发两封相同内容的邮件」时会误杀,加一个业务域或显式序号可以区分。

四件套之二:写前预检

在执行写操作前先查一次当前状态。比如下单前先查该订单号是否已存在、发券前先查该用户是否已领过。预检本身是只读操作,重试无害,成本极低,能挡掉大部分「重复是因为判断滞后」的场景。

预检的局限是存在竞态:查的时候没有,写的时候可能已经有了。所以预检不能替代幂等键,两者是叠加关系。

四件套之三:补偿动作

每个写工具配一个反向工具,并且反向工具自身也必须幂等:

写操作补偿动作补偿的幂等要求
创建订单取消订单重复取消返回成功,不报错
扣款退款同一笔只能退一次,重复退款请求返回首次结果
发通知撤回或补发更正撤回幂等,已撤回再撤返回成功
写入记录软删除或标记作废标记操作是幂等的,物理删除不是

一条重要原则:优先设计成可撤销,而不是不可逆。能软删除就别物理删除,能标记作废就别直接覆盖。不可逆操作的出错成本无法用兜底逻辑挽回。

四件套之四:对账

前三件都是事前防护,对账是事后兜底。按 trace 汇总每次运行的全部工具调用,定期与业务侧比对:

  • 同一 trace 内同一工具的写调用次数;
  • 业务侧的实体数量与工具侧成功次数是否一致;
  • 存在「工具成功但业务侧无记录」或反之的情况,标记人工核查。

对账不需要实时,一天一次足够。它的价值在于把「偶尔重复」从用户投诉变成内部告警。工具调用重试与降级的分层设计可以参考工具调用重试与降级。

让智能体自己判断「这次该不该重试」是不可靠的。正确做法是把错误结构化返回——标注错误类型、是否可重试、建议的下一步——由编排层的代码决定重试与否,模型只负责读结果。

错误分类决定重试策略

错误类型能否重试智能体该怎么走
参数校验失败可以,但要改参数修正入参后重试,不改参数重试必然再失败
限流可以,稍后按 retry_after 等待,不要立即重试
服务暂时不可用可以,退避重试指数退避,超过上限转人工
记录不存在不可以换标识符查询,或向用户澄清
权限不足不可以直接上报,不要在权限不足时反复尝试

落地步骤


  1. 盘点全部有副作用的工具,逐个标记:创建、更新、删除、发送、支付都算写操作。

  2. 为每个写工具的入参补上 idempotency_key 字段,并在描述里说明它的作用。

  3. 实现幂等中间件:规范化入参、算哈希、查重、命中则直接返回首次结果。

  4. 给每个写工具补一个只读预检接口,写之前先查状态。

  5. 为每个写工具配补偿工具,确认补偿本身也走幂等中间件。

  6. 写操作返回结果里带上操作 ID,供后续对账与人工追溯。

  7. 建立每日对账任务,比对工具侧与业务侧的写操作数量差异。

和相邻机制的分工

幂等解决「重复执行」,不等于解决「执行失败」。失败之后怎么重试、什么时候降级、何时转人工,属于另一层设计。工具本身的命名与边界划分参考智能体工具设计实践;并行调用带来的重复风险见并行工具调用;输出需要被下游可靠解析时,用结构化输出 schema固定字段;改动之后要不要上线,交给提示词版本管理与回归测试来判断。


只读工具也需要幂等键吗
不需要。查询、检索、列表这类工具重试无害,加了反而增加复杂度。幂等保护只针对有副作用的写操作。

幂等键应该由谁生成
由调用方也就是编排层生成,工具层负责校验和查重。工具自己随机生成等于没做,因为重试时键一定不同。

加了幂等键还会有重复吗
会大幅减少但不会归零。并行竞态、跨系统一致性这类问题需要预检和补偿一起上,再加上每日对账兜底。

幂等记录要保存多久
至少覆盖业务上可能出现重复操作的时间窗,通常七天以上,涉及退款对账的场景建议更长,并设置定期清理。

结论:智能体的写操作安全不靠模型自觉,靠工具层兜底。幂等键挡住重试,预检挡住判断滞后,补偿挡住已经发生的错误,对账挡住前面三道都没拦住的漏网之鱼——四件套装上之后,重复下单才会从「迟早会发生的意外」变成可被系统吸收的常规情况。

这篇有帮助吗?
云上的幻象
云上的幻象查看主页

七彩云博客,分享 WordPress 建站实战与 AI 工具测评,覆盖服务器运维、站长工具、软件资源与电商运营干货,专注原创实用的主题插件、网站加速与安全优化教程。

989文章4评论

相关文章

评论 (0)

欢迎你,新朋友,感谢参与互动!文明发言,理性交流 · 首次评论将在审核后展示