两个 AI agent 可以编辑同一个文件,两者都收到了“成功”确认,但最终只有一个人的修改得以保留。在一个包含五个并发 agent 的简单测试中,五次写入中有四次消失了,且没有任何错误或日志记录——这是一个典型的“丢失更新”(lost-update)异常,白白浪费了为那些消失的工作所支付的 token。

为什么这个问题很重要

当 AI agent 写回结果时,底层服务会按生成的 token 进行计费。如果写入被静默覆盖,服务商仍会针对产生被丢弃输出的计算过程进行计费。在多 agent 流水线中——无论是 agent 集群(agent swarms)、并行数据清洗工作流,还是任何多个机器人共享计划文件或草稿本的系统——这些隐性损失都可能演变成巨大的成本漏洞。此外,该异常还会威胁数据完整性:下游步骤可能会基于不完整或过时的信息进行操作,从而导致连锁错误。

异常是如何发生的

根本原因是竞态条件(race condition):

  1. 两个(或更多)agent 读取了资源的同一个版本,例如一个 JSON 计划文件。
  2. 每个 agent 根据该快照执行各自的推理或转换。
  3. 两个 agent 都向共享存储发起写入操作。
  4. 存储系统接受了第二次写入,在没有任何冲突检测的情况下覆盖了第一次写入。
  5. 两个 agent 都收到了确认写入成功的“ACK”,尽管第一次的贡献已经丢失了。

存储系统的确认仅证明了写入动作已发生,并不保证该写入相对于其他并发更新是安全的。通常被视为保障手段的“仅追加日志”(append-only log)也存在同样的问题:它记录了写入动作的发生,但无法阻止后来的写入覆盖先前的写入。

Compare-and-set (CAS) 闸门的作用

Compare-and-set (CAS) 闸门在写入被接受之前增加了一个版本检查:

  • 读取 (Read):agent 获取文件的当前版本号(或哈希值)。
  • 计算 (Compute):agent 执行其工作,生成文件的新版本。
  • 写入 (Write):agent 将新内容连同其最初读取的版本号一起发送。
  • 验证 (Validate):存储层将提供的版本号与当前版本进行比较。如果两者不同,写入将被拒绝;否则,写入将继续进行并递增版本号。

如果版本已更改,agent 就会知道其视图已过时,必须使用新版本重新尝试整个循环——读取、计算、写入。这把不可见的覆盖变成了可以记录、重试并进行核算的显式失败。

安全的代价

CAS 闸门并非免费。在同样的五个 agent 模拟实验中:

场景 尝试写入次数 成功的贡献 Token 成本
无 CAS 闸门 5 1 5 个单位
有 CAS 闸门 5 5 (重试后) 9 个单位

对于遇到版本冲突的 agent,闸门会增加额外的“读取-计算-写入”循环,从而提高 token 消耗。权衡很明显:没有闸门,你会静默地丢失数据;有了闸门,你只需支付少量的额外成本,就能获得对每一次冲突的可见性。

这种失败有多常见?

即使只有两个 agent,测试也显示有 75% 的概率会丢失其中一次写入。当使用五个 agent 时,丢失率接近 100%。这些数据表明,对于任何生产级的多 agent 工作流来说,“通常没问题”是一个危险的假设。

反方观点:何时可以跳过闸门

如果系统为每个资源只运行单个 agent,或者在更高层级强制执行严格的串行化,那么额外的 CAS 检查可能是不必要的。然而,风险计算必须包含重新运行失败工作所带来的隐性成本,以及数据缺失可能对下游产生的影响。

后续关注点

  • 工具支持:寻找能够直接提供版本号或 ETag,并原生支持原子 CAS 操作的存储 API。
  • 指标:为你的 agent 配置监控,记录因版本不匹配而被拒绝写入的频率。冲突率上升预示着你需要扩展资源或重新设计工作流。
  • 重试策略:简单的指数退避(exponential back-off)效果良好,但要注意重复重试会增加 token 消耗。需在重试限制与可接受的数据丢失之间取得平衡。
  • 混合方案:一些团队将用于审计的“仅追加日志”与用于一致性的 CAS 闸门相结合,既能记录发生过什么,又能防止覆盖。

总结

丢失更新异常会将 Token 驱动的 AI 流水线变成漏钱的黑洞。引入一种 Compare-and-set 版本门控机制会增加少量的 Token 开销,但它能将静默的数据丢失转化为可见且可重试的事件。对于任何存在多个智能体共享状态的系统——无论是数据库、计划文件还是临时存储区——在写入前嵌入版本检查,是防止隐藏成本和工作流损坏的最廉价保险。