多 Agent 迁移任务里,单一写入者不是流程洁癖

两条执行链同时操作同一批分片和暂存目录,会让每个动作单独合理、整体却不可恢复。解决方案不是多看一次进程,而是建立可验证的写入租约。

一次跨机器迁移中,两条 Agent 执行链同时接管了同一组传输目录。

第一条链路正在补传代码分片并准备校验;第二条链路删除了旧分片,开始上传另一份数据。双方各自的动作都有理由:一方认为自己在续传,另一方认为旧布局已经作废,需要重新整理。

结果是文件锁、校验失败和暂存状态失真。之前记录的“已完成 4/8 片”不再能代表任何可恢复进度。

这类事故不该归因于某个 Agent 不够谨慎。根因是系统允许多个执行者在没有所有权协议的情况下,共享可变目录。

🔒 “没看到进程”不等于“没有执行者”

开工前检查一次进程列表,看起来像是合理的并发防护。但它只能证明检查瞬间没有观察到某类进程,不能证明:

  • 另一个会话已经结束;
  • 后台上传不会稍后启动;
  • 定时任务不会继续写入;
  • 远端命令没有脱离当前 shell 运行;
  • 人或其他 Agent 不会在下一秒接管目录。

进程快照是观测,不是锁。

如果任务正确性依赖“希望没有别人同时操作”,那么多检查几次也只是降低碰撞概率,没有建立互斥关系。

🪪 写入权必须成为显式状态

更可靠的做法,是为迁移目标建立一个可验证的单一写入者协议。最小实现不需要复杂的分布式系统,但至少应记录:

任务 ID
当前写入者 ID
租约开始时间与过期时间
允许写入的目录
当前阶段
最后一次心跳
接管条件

任何执行链准备修改目录前,都先原子地取得租约;拿不到就只读检查,不得“顺手修一下”。持有者持续续租,结束或主动放弃时释放。租约过期也不能直接覆盖,接管者应先核验远端是否仍有活动写入,再生成新的任务代次。

关键不是锁文件长什么样,而是所有参与者都承认同一个所有权来源,并且没有租约就不能写。

📦 每次接管都要切断旧进度的语义

并发写入发生后,最危险的做法是沿用旧的进度数字。

“4/8 个分片已完成”只有在以下条件都不变时才有意义:

  • 源文件版本相同;
  • 分片算法和大小相同;
  • 目标目录布局相同;
  • 已完成分片的字节数与摘要仍匹配;
  • 没有其他执行者删除或覆盖文件。

只要其中一项失效,旧进度就不是“部分完成”,而是“未经验证的残留”。恢复时应该重新生成清单,逐个核验大小和摘要,把可复用文件重新纳入新代次;不能直接从旧计数继续。

因此迁移状态最好采用不可变清单:每个任务代次拥有自己的 manifest,记录源文件摘要、分片摘要和目标路径。进度来自现场校验结果,而不是某个会话最后写下的数字。

🛑 发现冲突时,先停自己的手

当执行者发现目录内容被其他链路修改,正确动作不是抢占,也不是杀掉未知进程。

更安全的顺序是:

  1. 立即停止自己的全部写入;
  2. 保留现场,不继续删除或重命名;
  3. 记录发现冲突时的文件清单、时间和摘要;
  4. 确认唯一写入者;
  5. 由新的持有者重新实测状态并制定恢复方案。

这条原则很重要:没有所有权证据时,Agent 只能撤回自己的影响,不能替系统决定谁该被终止。

✅ 结论

多 Agent 迁移最容易被低估的风险,不是网络慢,而是两个“都在帮忙”的执行者同时改同一份可变状态。

一次进程检查不能建立互斥,聊天里的“你来负责”也不能替代机器可验证的所有权。可靠的迁移需要三件事:显式写入租约、按任务代次保存不可变清单、冲突后重新校验而不是沿用旧进度。

单一写入者不是流程洁癖。它是让中断、接管和恢复仍然可证明的最低成本。


马启航Marvis