Why NextWhy Next
返回列表
💻 开发阅读约 4 分钟

把多个 AI 智能体放进同一个仓库之后发生的事

原以为并行开几个智能体会话,生产力就能翻倍。实际上一周之内真事故接连不断:分支劫持、落在别人分支上的提交、靠 reflog 捞回来的孤儿提交,还有同一个功能的重复实现。这是共享一个检出的并行智能体所制造的事故类型学,以及一路踩坑后立下的规则。

核心摘要

并行智能体会话真正的敌人不是模型的水平,而是共享的工作目录。HEAD 是所有人的全局变量,一个会话切换分支,就会把另一个会话的提交安到错误的地方。一周里经历的四种事故类型和恢复记,以及 worktree 隔离、提交前重新确认分支、验证关卡范围收窄这三道防线。

目录

和 AI 智能体干活久了,人自然会起贪心。一个会话在修 bug 的时候,另一个会话去做重构,再开一个去调查 issue,不行吗?模型能开好几个,生产力不也该跟着翻倍。

我也是这么开始的。然后一周之内就明白了:并行智能体真正的敌人不是模型的水平,而是它们共享的那个工作目录。

HEAD 是全局变量

原因一句话就能概括:多个会话共享同一个 git 检出,“当前分支”这个状态就成了所有人的全局变量。

想象两个人用同一台电脑同时干活,哪里不对劲一眼就能看出来。可启动智能体的时候,我没往这方面想。每个终端标签页里跑着一个会话,看上去彼此隔离。但文件系统只有一个,HEAD 也只有一个。一个会话执行 git checkout 的瞬间,其余所有会话脚下的地面都变了。

那一周里爆出来的事故,类型非常清晰。

分支劫持。 会话 A 在主题分支上干活,会话 B 为了做自己的事切换了分支。A 毫不知情地提交,提交落在了 B 的分支上。反方向的也有:A 正要提交时,分支已经换到了 develop,多亏拦截保护分支直接提交的钩子挡了下来,才免于事故。要是没那个钩子,就直接进去了。

孤儿提交。 会话 A 的主题分支,被会话 B 在做清理时删掉了。A 的提交成了不属于任何分支的孤儿,翻 reflog 找到提交哈希,用 cherry-pick 捞了回来。捞回来算走运,要是 reflog 过期了或者没找到,一整段工作就凭空蒸发了。

暂存区污染。 会话 A 生成提交的时刻,会话 B 暂存好的文件删除也一起躺在暂存区里。要是就那么提交,B 的删除就混进了 A 的提交。扫 diff 时看见陌生的变更才筛了出来,如果智能体提交前没看 diff,就无从知晓。

重复实现。 最让人泄气的类型。两个会话在互不知情的情况下,各自实现了同一个功能。两边都做得认真扎实,其中一边只能整个扔掉。并行省下的时间,就这么原数奉还。

连验证关卡都在互相踩

出问题的不只是文件和分支。我们的工具链里有一道关卡:会话结束前要跑整个仓库的静态分析和测试,不允许在破损状态下收工。单会话时,这是极好的装置。

到了并行会话,它成了互相绊脚的陷阱。会话 A 只动了文档,却因为会话 B 正改到一半的文件有编译错误,A 的关卡失败了。A 得花掉回合去证明“这不是我的变更”,糟糕的日子里要等 B 收拾完,一等就是三十分钟。最恶劣的一次,是某个会话为了通过关卡,把另一个会话正在改的代码给改了。关卡反而成了对别人的工作下手的诱因。

检查本身没有错。错的是检查的范围是“整个仓库”这一点,在仓库不再属于一个人的那一刻,它就成了错。

三道防线

把事故按类型都经历了一遍之后,我立了三层防线。

  1. worktree 隔离设为默认。git worktree 给每个会话一个独立的工作目录,HEAD 就不再是共享变量。分支劫持、孤儿提交、暂存区污染从根源上消失,上面四种事故类型里的三种,这一手就没了。不过它不是免费的:monorepo 的话,每个 worktree 都得重装依赖、重跑代码生成;用 git-crypt 这类和 worktree 八字不合的工具的仓库,也难以强制推行。我们也有一个仓库因为这条限制维持着共享检出,所以才需要剩下两道防线。
  2. 提交前重新确认分支。 会话开工时记下“我在这个分支上干活”,提交前和当前 HEAD 比对。不一致就停下提交,先搞清状况。规则简单到近乎无聊,可分支劫持事故全都出自“提交那一刻的 HEAD 不是我认知里的 HEAD”。换成人,提示符上挂着分支名总能察觉;智能体不明确要求,就不会去确认。
  3. 验证关卡收窄到自己的变更。 会话结束关卡的检查范围,从整个仓库缩小到这个会话实际修改过的文件。自己的收工被别人的 WIP 卡住的事没了,为过关卡去碰别人代码的诱因也没了。仓库整体的健康,反正 CI 会以提交后的状态为准再看一遍,会话关卡没必要看全局。

在这之上,再加了一条运营规则:启动会话之前,扫一眼当前打开的分支和 PR,看有没有重叠的范围。重复实现不是 git 能拦下的问题,是排班的问题,只能靠习惯而不是工具去防。

并发问题原来不只属于数据库

整理下来发现是熟悉的画面:共享资源、无锁的并发访问、竞态条件,还有隔离级别。我们在数据库和多线程代码上学了几十年的那个问题,在工作目录上原样重演了。

和一个智能体干活时,这个问题不存在。人和智能体轮流干活时,人也在暗中充当协调者。问题从智能体变成多个、人放开协调的那一刻开始。从那个时间点起,工作目录就是需要并发控制的共享资源,不加隔离地跑,就会像数据库那样,必然丢数据。

这不是叫你放弃并行智能体。我现在也每天开好几个会话。变的只有一件事:我再也不把它们关进同一个房间了。

相关文章

0 条评论