返回博客

如何防止多个编码代理相互覆盖

2026-05-035 min read

在单个代码库上运行一个 AI 编码代理就像结对编程。在同一个代码库上运行三个或五个代理可能会变成一个合并冲突工厂,如果它们共享同一个检出。一个代理切换分支,另一个编辑同一个文件,第三个运行清理命令,突然之间没有人知道哪个 diff 属于哪个任务。

解决方案不是更大的提示。解决方案是工作流。我将代理视为拥有 shell 访问权限的快速初级开发人员:有用,但需要界限。

简而言之

  • 为每个代理使用一个 Git worktree。
  • 为每个任务使用一个分支。
  • 为每个代理指定清晰的文件或模块所有权边界。
  • 将共享的代码库规则放在 AGENTS.mdCLAUDE.md 或两者兼有(通过符号链接)中。
  • 阻止破坏性的 Git 命令,除非有人类批准。
  • 通过带有 CI 和分支保护的拉取请求进行合并。

这对于大多数并行代理工作来说已经足够了。

为什么共享检出会失效

正常的 Git 检出只有一个工作树、一个索引和一个当前分支。这对于一个开发人员或一个代理来说是没问题的。当多个代理同时操作时,它就会变得混乱。

如果代理 A 正在进行一半的身份验证重构,而代理 B 运行 git checkout main,那么代理 A 的工作区就会在它脚下发生变化。如果代理 C 运行 git reset --hard,未提交的工作可能会丢失。即使是像 git stash pop 这样无害的命令也可能将不相关的更改混合在一起。

你可以告诉代理不要做这些事情,而且你应该这样做。但文件系统隔离比信任更强大。

使用 Git worktrees 进行隔离

Git worktrees 允许一个存储库拥有多个附加到相同历史记录的工作目录。每个目录都可以有自己的分支,同时共享相同的对象数据库。你可以避免克隆存储库五次的成本和混乱,但每个代理仍然拥有自己的文件。

git fetch origin
git worktree add ../site-auth -b agent/auth-refactor origin/main
git worktree add ../site-billing -b agent/billing-fix origin/main
git worktree add ../site-tests -b agent/test-coverage origin/main
git worktree list

然后,在每个目录中启动一个代理。代理 A 在 ../site-auth 中工作。代理 B 在 ../site-billing 中工作。代理 C 在 ../site-tests 中工作。它们可以运行测试、编辑文件和创建提交,而不会改变彼此的检出。

这也是 Claude Code 为并行会话记录的模式:单独的工作树、单独的分支和隔离的编辑。Anthropic 的帮助文档更进一步,将基于 worktree 的并行会话描述为同时运行多个 Claude 会话的常用高级用户工作流。

为每个代理分配所有权范围

Worktrees 解决了文件级别的冲突。它们不能解决产品级别的冲突。如果任务含糊不清,两个代理仍然可以做出不兼容的决定。

在我并行启动代理之前,我会按所有权划分工作。不仅仅是按文件名,而是按职责。

你负责 src/auth/** 和 tests/auth/**。
不要编辑该范围之外的文件。
在停止之前不要更改公共 API 形状。
在报告完成之前运行身份验证测试。
使用简洁的摘要打开一个 PR。

这个提示很无聊,这正是它有效的原因。代理比巧妙的措辞更需要无聊的界限。

最好的划分是沿着自然模块线:身份验证、计费、搜索、文档、UI 组件、迁移、测试。最糟糕的划分是给两个代理重叠的服务所有权,然后希望 Git 以后能弄清楚。

使用 AGENTS.md 和 CLAUDE.md 作为共享规则

代码库说明应该放在代码库中,而不仅仅是在聊天窗口中。CLAUDE.md 是 Claude Code 读取的约定。AGENTS.md 是编码代理更通用的约定。如果你同时使用这两个工具,请保持一个事实来源,并将另一个名称链接到它。

ln -s CLAUDE.md AGENTS.md

该文件应包含代码库的构建命令、测试命令、部署说明、样式规则以及任何硬性限制。例如:不要编辑生成的文件,未经批准不要触碰迁移,在交接前使用 npm run lint,或者将博客代码块保留在单行 HTML 中,并使用 <br/> 标签。

要点很简单:每个代理都应该从相同的本地上下文开始。

明确危险的 Git 命令

我不允许代理使用破坏性的 Git 命令进行即兴创作。这些命令在人类控制的终端中很有用,但在自主工作中存在风险:

git reset --hard
git checkout .
git clean -fd
git push --force
git stash pop

我的默认规则是:自由读取,狭窄写入,并在执行破坏性 Git 操作前询问。代理可以运行 git statusgit diffgit log 和正常提交。除非任务明确要求,否则它们不应丢弃工作、强制推送或移动其他分支。

使用拉取请求作为交接点

不要通过在文件夹之间复制文件来合并代理工作。让每个代理生成一个分支和一个拉取请求。

git status
git diff
npm test
git add src/auth tests/auth
git commit -m auth-refactor
git push origin agent/auth-refactor
gh pr create

在 GitHub 上,分支保护规则可以要求拉取请求审查、状态检查、线性历史和合并队列。当代理可以快速生成代码时,这些控件就更加重要了。速度只有在 main 保持可信时才有用。

我喜欢小的代理 PR。一个集中的 200 行 diff 是可以审查的。一个 4000 行的混合重构是隐藏 bug 的地方。

按依赖顺序合并

如果代理 A 更改了一个 API,而代理 B 使用了该 API,则先合并 A。然后将 B 变基到更新的基础分支上,让 B 自己解决冲突。

git fetch origin
git rebase origin/main
npm test

这保持了心智模型的清晰。拥有依赖工作的代理负责适应新的基础。人类审查者一次看到一个连贯的 PR。

我明天会使用的工作流

  1. 更新 main
  2. 为每个代理任务创建一个工作树和分支。
  3. 在每个工作树中启动每个代理。
  4. 为每个代理提供书面的所有权边界。
  5. 让每个代理运行相关测试。
  6. 推送每个分支并打开一个 PR。
  7. 按依赖顺序审查、合并,然后删除已完成的工作树。
git worktree remove ../site-auth
git branch -d agent/auth-refactor

多个编码代理可以处理同一个代码库。它们只是不应该在同一个检出中工作。使用 Git 进行隔离,使用拉取请求进行审查,并使用代码库级别的说明文件进行共享规则。这样你就可以获得并行速度,而不会将代码库变成一堆神秘的 diff。

延伸阅读

保持更新

将最新文章和见解发送到您的收件箱。

Unsubscribe anytime. No spam, ever.