深度· 4 分钟阅读

Agent 扇出与 git worktree:并行修改代码,互不冲突

并行很容易承诺,却很难做得安全。Muse Code 的答案是把一项古老、朴实的 git 技术用到恰到好处。

#worktrees#parallel-agents#git#multi-agent

模式:一个父 agent,多个可写的子 agent

Muse Code 围绕一条简单规则构建:当一项工作可以拆成几个相互独立的任务时,这些任务会自动扇出(fan out)给不同的 agent。父 agent 为每个任务各生成一个具有写权限的子 agent。你不需要为此做任何配置,也不需要调用什么特殊的并行模式——只要工作量大到值得拆分,任务分解与分发就是默认行为。

一个显而易见的问题随之而来:如果多个 agent 可以同时在同一个仓库里写代码,为什么最后不会陷入满屏的合并冲突和被互相覆盖的文件?

Muse Code 会话任务表:一个打砖块游戏的六个任务,四个已完成、两个进行中,任务 4 和 6 的隔离 worktree 仍在 /.muse/worktrees/ 下活跃

一次真实的扇出会话:同一个游戏上的六个任务,四个已合并,两个仍在运行——每个都在 .muse/worktrees/ 下自己的 worktree 里,主工作区完全不受影响。

Worktree:git 原生的隔离方式

每个子 agent 都会得到自己的 git worktree——一份独立检出的仓库副本,与你的主副本共享历史,但拥有自己的工作目录和自己的分支。两个子 agent 可以在各自的 worktree 里编辑同一个文件,过程中完全看不到对方的改动。从结构上说,冲突根本不可能发生。

同样重要的是:你自己的工作副本始终保持干净。你在编辑器里打开的目录,永远不是 agent 正在改动的那个目录。没有东西会在你的光标下面自己动,没有写到一半的 agent 改动会混进你的 diff,放弃某个 agent 的工作也只需要丢掉它的 worktree,成本几乎为零。只有当工作完成并经过审查后,改动才会进入你的分支。

为什么不直接用分支?或者容器?

普通分支共享同一个工作目录——任务进行到一半切换分支,等于从正在运行的 agent 脚下抽走地毯。完整的容器或仓库克隆当然可行,但太重了:对象库重复存储、启动慢、合并别扭。Worktree 正好落在最佳平衡点上:创建几乎是瞬时的,底层共享同一个 git 对象数据库,而把子 agent 完成的分支合并回来就是普通的 git 操作——没有需要你信任的自定义同步层,也没有需要调试的私有状态。

六个功能同时开发,有实例为证

发布时的演示重度依赖这套机制:在游戏开发的例子里,Muse Code 同时构建了六个游戏功能,每个 agent 都在自己的 worktree 里,最终每条分支都干净合并。这就是它的实际收益——一个多功能冲刺的墙钟时间,会坍缩到接近其中最长单个任务的时长,而不是所有任务时长之和。

试试这份配方

Agent 扇出是 Meta 在 cookbook 中提供配方的三种模式之一——把一个大任务拆给多个 subagent,让任何环节都不会中途相撞。cookbook 里有可以直接运行的版本。而且,扇出的工作恰恰是你日后最想审计的那类工作:每个子 agent 的生成、工具调用和合并都会被记录在事件日志里——不会因为是并行发生的,就变成了没有记录的暗箱操作。

继续阅读