ACDL研发流程08:让多个Agent在不同worktree工作
ACDL研发流程系列第8篇,共15篇。
多Agent不等于把同一个任务切成多份
Agent可以很快地读取代码和生成实现,所以多个Agent同时工作看上去是最直接的加速方式。但如果它们正在等待同一个未定稿接口,修改同一批文件,或者各自理解了不同的产品结果,并行只会把返工也同时放大。
当前项目并行的基本单位不是Agent,而是第7章已经拆好的独立任务。每项任务有自己的工作来源、ACL、目标、非目标、起点和验证结果,然后再交给一个主要Agent。不把数据库、接口、页面和测试分给几个Agent,让它们在同一项尚未定稿的改变中相互等待。
如果当前只有一项端到端任务,一个Agent保持完整上下文通常更快。只有出现两项或更多能够真正独立推进的工作时,才需要组织并行开发。
第一步:先确认这些任务能否并行
可以独立验证是并行的第一个条件,但还不够。Director和Agent还要看任务之间的依赖、文件交叉和外部资源。
两项任务通常适合并行,需要同时满足以下条件:
- 它们不需要等待对方的未定稿结论,已知依赖要么已经完成,要么已经确认接口和数据格式在并行期间不会变化;
- 它们的主要修改范围能够分开,少量共同文件也能预先说明谁先改、谁在集成时适配;
- 它们可以使用不同的测试数据库、端口、容器、账号或证据目录,不会互相改写外部状态;
- 需要隔离文件修改时,每项工作都能在自己的worktree中实施、测试、提交和记录;
- Director已经知道谁负责最终集成,以及几项结果以什么顺序进入主线。
上一章把收藏会话拆成“保存收藏状态”和“筛选收藏内容”两个结果,但第二项依赖第一项,它们仍然需要串行。假如当前还有一项Runtime恢复缺陷和一项文档检查工具优化,而它们分别有自己的工作来源和验证方法,就可以与收藏会话同时开展:
1 | 同一个已确认起点 |
这里同时推进的是三项工作,不是三个Agent共同完成收藏会话。
如果两项工作同时改动一个核心契约,共用一个无法分离的真实环境,或者第二项的验证结果完全取决于第一项的实现,就先保持串行。不需要为了让Agent都有事做而制造并行任务。
第二步:需要文件隔离时,一项任务使用一个worktree
worktree是Git在同一个仓库上同时保留多个工作目录的方式。每个worktree检出自己的分支,Agent可以在其中查看、修改和测试文件,不会把未提交差异混到其它任务的目录里。
存在文件冲突风险时,推荐使用以下对应关系:
1 | 一项独立任务 |
分支、worktree和Pull Request都按实际需要使用。只做只读调查、修改范围完全不相交,或者当前Harness已经提供其它可靠隔离时,不为了形式机械创建。需要隔离文件差异时,主工作树保留共同起点,每个并行任务在独立worktree中开展。
分支名称可以由小写ACL编号和简短主题组成,例如acl-000039-conversation-favorites。分支跟踪的是工作而不是Agent身份,不要使用模型名或Agent名命名。
建立worktree前,先根据当前运行时确认是哪一种Harness。Orca、Codex或其它Harness已经提供原生worktree能力时,优先使用它的创建和交付入口;原生能力不可用或不适合当前任务时,才用Git命令作为后备,并选择稳定、可识别的非临时目录。无论由哪种工具创建,都先记下完整起点提交、分支和目录。
不同任务可以从同一个已确认提交开始,也可以根据已知依赖从不同提交开始。无论怎样选择,每轮ACL的启动方案都保存自己的分支、明确的起点提交和worktree路径,不用“从最新代码开始”这种无法复现的说法。
同一任务需要多个Agent时,可以串行接棒
并行规则解决的是多项独立任务怎样同时推进。另一种常见情况是,同一项任务先由ChatGPT整理需求或设计候选,再由本地Agent实施和验证,最后交给ChatGPT或其它Agent评审。它们处理的是同一轮工作,不需要为了参与者不同而拆成多个ACL,适合按阶段串行接棒。
本机Agent通常使用worktree取得完整文件、依赖和验证反馈;通过GitHub参与的远端Agent通常使用远端分支、提交和Draft Pull Request取得隔离空间。远端Agent是否能够写入,取决于连接器和仓库权限:能够写入时可以直接准备候选,只有读取能力时则提交分析或评审意见,由当前写入者落地。工具能力不同,不改变仓库事实源和Director确认边界。
同一分支由多个Agent接力时,推荐采用以下约定:
1.任一时刻只指定一个当前写入者,其他Agent只读或评审;
2.交接前提交并推送候选变化,记录完整HEAD提交;
3.接棒者先核对远端分支仍指向交接提交,再开始修改;
4.已经交接的共享分支不强制推送、不改写交接历史;
5.两个Agent要探索不同方案时使用不同分支,不在同一分支互相覆盖;
6.共同决定写回REQ、设计、ADR或Loop记录,Pull Request只保存差异讨论和交接摘要。
这些约定用于降低远端与本机协作中的竞态,不表示每项工作都必须创建Pull Request。只有一名Agent、没有远端评审或无需隔离时,继续使用原来的短路径即可。
需要反复交接时,可以在Draft Pull Request顶部维护一段简短的当前状态:
1 | ## 协作状态 |
每次正式交接再用Pull Request评论保留固定快照,至少说明基线、当前候选、正式依据、本轮目标和非目标、实际修改、已运行与未运行的验证、剩余风险和下一步。新会话先读取这段交接、正式文档和固定提交,不依赖上一段聊天记录恢复现场。
第三步:把代码之外的资源也分开
worktree隔离了文件目录、当前分支和未提交差异,但它们仍然属于同一个Git仓库,也仍然在同一台机器或同一套基础设施上工作。它不会自动分开:
- Git的共享引用和对象;
- 测试数据库及其中的数据;
- 本机端口、进程、容器、网络和数据卷;
- 开发或真实环境;
- 测试账号、外部系统和限额;
- 日志、截图、检查结果和其它证据目录。
因此,Director在启动并行任务时,为每轮ACL分配不会冲突的外部资源。例如,每项数据库测试使用独立的专用测试库,每个本地服务使用不同端口,每轮验证写入自己的证据目录。只有一套的真实环境默认串行更新,不让两个Agent同时发布并相互覆盖结果。
这些分配写入各自启动方案。如果无法把一项关键外部资源分配成互不影响的独立资源,就把需要它的步骤排成明确的串行顺序,不用“小心一点”代替隔离。
第四步:为每个Agent准备独立上下文
每个主要Agent只需要读取完成自己任务所需的上下文,不需要理解所有并行任务的实施细节。交付一个worktree时,至少让Agent知道:
- 它负责的ACL编号、工作来源和启动方案;
- 需要遵守的REQ、Accepted设计和ADR;
- worktree路径、当前分支和明确的起点提交;
- 可以修改的范围、已经分配的外部资源和不可执行的高风险动作;
- 任务与其它ACL的已知依赖、预计集成顺序和交付方式;
- 完成前需要运行的定点验证和需要保留的证据。
不需要把Director与其它Agent的全部聊天记录同步到每个worktree。共同决定写回REQ、设计或启动方案,当前进展写入各自实施记录的“当前摘要”。任务在新会话中继续时,Agent重新读取这些内容并核对当前Git差异,不从记忆中猜测上一次做到了哪里。
第五步:让每个Agent交付一个可以独立验证的完整结果
并行开始以后,每个Agent在自己的worktree中推进完整任务。它可以修改前端、接口、领域逻辑、数据和测试中真正受影响的部分,不被“你只是前端Agent”之类的职能划分限制。完成时留下的是一个能被验证的结果,不是一批等别人收尾的文件。
并行开发不需要让Agent之间持续互相播报每个实施细节。他们只需要告知会影响其它任务的变化:稳定契约改变、共享资源冲突、起点被修正,或者原定依赖不再成立。Director根据这些事实决定调整集成顺序、暂停某项工作,或者回到设计重新确认。
如果一个Agent发现需要改动另一项ACL的范围,它不直接进入对方worktree修改。它先记录新事实和影响,由Director判断这是可以在集成时处理的局部适配,还是原来的任务拆分已经不再成立。如果会改变已确认的产品行为或技术边界,就暂停受影响的实施并回到设计。
第六步:主线依次接收并行结果
多项任务可以同时开发,但不能同时改写主线。每个Agent先在自己的分支上完成范围内的代码、文档、定点验证和实施记录,并把修改整理成容易理解、目的单一的提交。Director或当次指定的集成Agent根据依赖和风险决定接收顺序。
第一项结果进入主线以后,下一项先取得最新的main,处理它与当前main的差异,再重新运行受影响的定点验证。希望保持线性历史时,任务分支可以先同步当前主线:
1 | git rebase main |
确认冲突已经解决且相关验证仍然通过后,再在主工作树中接收该分支:
1 | git merge --ff-only acl-000039-conversation-favorites |
代码冲突有两种。一种只是同一文件不同位置的机械冲突,集成Agent根据两边已确认的结果处理并重新测试。另一种暴露了两项任务对对象、状态、接口或权限的理解不同,这不是选择哪边代码更好合并的问题,而是设计矛盾。Director与Agent需要先回到相关设计统一答案。
每项结果进入主线时做受影响的验证,全部接收后再做跨任务的整体验证。分支能够合并只证明Git接受了这些差异,不证明几项工作组合后的系统能够工作。
第七步:完成交付后再清理worktree
一项分支进入主线,不表示它的ACL已经结束。实际修改、验证、失败和跳过项、剩余问题、Director的结论确认以及实际合入提交仍要完整保留。ACL只有在这些事实齐全后才能进入Completed。
确认分支结果已进入主线、所有需要的记录和证据已经交付,而且没有Agent继续使用该目录后,才移除worktree和对应短期分支。未合并结果、失败现场、待复核差异和其它Agent仍在使用的worktree都需要保留,不为了目录整洁而提前删除。
并行数量取决于Director能够评审和合并多少结果
可用Agent数量不是并行数量的上限判断。Director还要看有多少真正独立的任务,外部资源能分成几份,以及自己能否及时处理歧义、评审结果和组织集成。
如果五个Agent同时完成五个分支,但主线一次只能安全接收一个,其它分支就会迅速过期,后续时间都用在重新同步、解决冲突和补做验证上。少量稳定的并行通常比一次启动尽可能多的Agent更快。
回头检查这条路径
1 | 多项已启动的独立ACL |
并行开发的目标是同时推进多项独立结果,不是让更多Agent出现在同一项任务中。worktree把各项任务的文件和未提交修改分开,启动方案和实施记录把上下文分开,外部资源分配和主线集成则让这些结果能够安全重新组合。
同一任务的多Agent协作采用另一条按需路径:
1 | 一项已启动的ACL |
两条路径可以同时存在:不同任务之间并行,同一任务内部串行。关键是每个时刻都能回答谁在写、正在修改哪个固定候选、下一步由谁接棒,以及哪些结论已经写回仓库。