代码只让一个 AI 改:我是如何避开多 Agent 协同踩坑的「单写多审」架构
为什么这至关重要
当开发团队刚开始尝试 AI 编程代理(Coding Agents)时,直觉上的下一步往往是“开一整队”:如果一个 Agent 在 10 分钟内能写好一个功能,那么同时启动 4 个 Agent 并行协作,岂不是 3 分钟就能搞定整个里程碑?
但在生产环境中,现实往往截然相反。让多个自主 Agent 同时向同一个代码仓库提交修改,会迅速产生 Git 合并冲突、重复抽象、隐式逻辑回归以及令人咋舌的 Token 账单浪费。协同造成的损耗会彻底吞噬并行带来的速度收益。
然而,如果只跑一个单一 Agent 到底,又会撞上致命的瓶颈:上下文污染(Context Pollution)。当同一个 Agent 既要搜寻文档、格式化资源、又要反复调试代码时,其工作记忆(Context Window)很快就会被塞满。长上下文检索精度断崖式下跌,幻觉频发,它会迅速遗忘最初设定的系统架构约束。
在过去一年管理生产基础设施、客户端系统与业务自动化的过程中,我通过推行**单写规则(Single-Writer Rule)**彻底解决了这一两难困境:
- 严格独占单写:任何时刻,只有一个 Agent 拥有代码仓库的文件写入锁与修改权。
- 素材外包隔离:只读子 Agent 并行处理沉重的文档检索、ComfyUI 生图与语音合成,保护主 Agent 上下文。
- 高阶对抗审查:由完全干净的顶级推理模型(如 Claude 3.5 Sonnet 或顶级思维链推理模型)对 Git Diff 进行对抗式挑刺。
- 代码图谱索引:引入预先索引的 AST 代码知识图谱(
codegraph),精确检索符号引用,将 Prompt 消耗压缩到极致。
以下是该架构的完整设计、踩坑复盘与可落地的工程实现。
多代理人悖论:Cognition 对决 Anthropic
2025 年年中,两家领先的 AI Agent 团队在 48 小时内相继发表了结论针锋相对的技术长文。
Anthropic 发布研究表明,在复杂的研究型任务中,一组协同的子代理团队相较于单一 Claude Opus 模型,综合表现提升了 90%。主管代理人将庞大的目标拆分子任务,分配给底层子代理人并行查阅资料,汇总摘要,从而彻底保护了主管的上下文空间。
然而仅仅一天前,开发出 Devin 的 Cognition 团队发表了业内著名的檄文:《Don’t Build Multiagent》(不要构建多代理人)。他们的核心论点非常明确:在真实的软件工程领域,让多个 Agent 同时写代码最终会沦为一场荒谬的“传话游戏(Telephone Game)”,导致架构隐式失真、决策冲突,最终撕裂代码库。
两边的结论在各自的场景下其实完全正确:
- 资料研究与信息提取天然是分块且只读的。Agent A 查阅上市公司名单,对 Agent B 没有任何副作用与状态冲突。
- 软件开发则是强状态、深耦合的精密网络。如果子 Agent A 在重构数据库模式,而子 Agent B 还在按旧模式写 API 控制器,两者合入主干的结果只能是灾难。
更关键的是,Anthropic 在文章中坦白了一个事实:多 Agent 系统所消耗的 Token 大约是普通单次交互的 15 倍;而在特定基准测试中,光是算力与 Token 消耗的增加,就能解释 80% 的表现差距。
如果不解决代码写入冲突,仅仅堆叠几十个 Agent,你只是在花 15 倍的成本,快速生产出更难排查的 Bug。
惨痛教训:多 Agent 写代码的三大陷阱
在收敛到当前架构之前,我曾在真实业务代码库中实测过多 Agent 蜂群协作。所有的翻车都可以归结为以下三个结构性陷阱:
1. 传话游戏(The Telephone Game)
主管 Agent 接收人类工程师的需求后,为了分工,必须向下属 Agent 传达任务便签。
用户需求(包含明确约束与隐式业务边界)
↓
主管 Agent 摘要(产生信息抽象与损耗)
↓
子 Agent 自由发挥(基于残缺便签产生幻觉假设)
到了第三层,诸如“必须向下兼容旧版客户端”或“类型定义必须严格匹配 DB 约束”等隐性常识荡然无存。子 Agent 确实百分之百完成了它便签上写的字面任务,但整体拼装时完全无法运行。
2. 隐式架构决策漂移(Architectural Drift)
以构建一个看似简单的前端组件为例:
- 子 Agent A 负责界面容器与样式编写。
- 子 Agent B 负责状态流转与事件监听。
两个 Agent 各自独立推进。Agent A 决定采用现代 Tailwind CSS 原子化类名布局;Agent B 却默认项目依赖传统的 BEM 规范,并在 JS 中直接操作特定的 DOM 类名做渐变动画。
两边各自的代码语法全对,本地单元测试全部亮绿灯。但当最终集成时,界面完全错位崩塌。它们没有共享实时的架构共识,而每一次敲击键盘都在暗中做出互斥的架构决策。
3. Git 合并地狱与死锁
当三个 Agent 同时修改代码时,它们不可避免地会在共享文件(如路由注册表、中央类型声明、依赖清单)上产生修改碰撞。
人类开发者面对 Git 冲突能通过业务常识进行语义级合并。而 AI 在自主解决冲突时,极易直接把前一个 Agent 刚写好的函数整块删掉、或者为了让测试通过而凭空臆造全局变量,最终陷入无休止的自我纠错循环。
破局之道:单写多审(Single-Writer)生产架构
为了兼顾开发吞吐量与系统稳定性,我将整个研发管线解耦为三个职责明确的角色,并确立了一条不可动摇的底线:任何时刻,全系统仅有一个进程持有文件修改权限。
┌────────────────────────┐
│ 人类需求与目标 │
└───────────┬────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 主写进程(SINGLE WRITER) │
│ │
│ • 独占文件写入锁与 Git 工作树 │
│ • 通过 AST Code Graph 精准按符号查询依赖拓扑 │
│ • 下发只读、无副作用的任务给后台子 Worker │
│ • 负责打补丁、运行本地测试并生成统一 Diff │
└──────────────┬──────────────────────────────────────────────▲───────────────┘
│ │
派发任务 │ (异步只读素材) 纯净 Diff 审查 │ (严格阻断闸门)
▼ │
┌──────────────────────────────┐ ┌───────────────┴───────────────┐
│ 素材与调研 Worker │ │ 对抗式代码审查员 │
│ │ │ │
│ • 第三方文档与 API 抓取 │ │ • 独立高阶推理大模型 │
│ • 本地 ComfyUI 生图 / 渲染 │ │ (如 Claude 3.5 Sonnet) │
│ • 本地 SenseVoice / TTS 处理 │ │ • 零上下文历史包袱 │
│ • 极度纯净的短时运行环境 │ │ • 专职挑毛病、查泄露、判边界 │
└──────────────────────────────┘ └───────────────────────────────┘
核心 1:独占主写 Agent(Single Writer)
主写 Agent 是整个系统里唯一能调用 patch、write_file 以及 Git 操作工具的实体。
由于它是唯一的写作者,它对代码库当前的修改状态拥有单调递增的完整掌控。没有后台文件竞态、没有幽灵锁定,更不会出现分支合并时代码被莫名冲掉的情况。
核心 2:并行的素材与调研 Worker(Asset Workers)
在全栈开发中,大量消耗 Context 的并非写代码本身,而是外部繁琐操作:
- 抓取第三方 API 的海量接口文档。
- 调度本地 ComfyUI 工作流生成界面封面与插图。
- 提取音频文件并转录文字(如 SenseVoice 逐字稿)。
如果把这些巨量的 HTTP 原始响应、音频张量或 Base64 塞进主写 Agent 的上下文,它的记忆立刻就会爆满。
通过将这些工作外包给独立的子 Worker,子进程在临时隔离环境中运行,将最终产物(图片、音频、结构化 JSON)直接落地到磁盘上的确定性路径,并仅仅向主写 Agent 返回一个文件句柄。主写 Agent 的上下文永远维持纯净,只用来推理核心业务逻辑。
核心 3:对抗式代码审查员(Adversarial Reviewer)
当一个开发者(无论是人类还是 AI)为了调试某个复杂逻辑连续迭代了 20 轮对话后,他必然会产生严重的认知盲区:因为他清楚自己为此付出了多少心血,他会本能地倾向于认为自己的补丁是正确的。
当主写 Agent 验证本地测试全部通过后,它会将生成的 git diff 提交给对抗式审查员。
审查员调用顶层推理模型(如 Claude 3.5 Sonnet 或顶级思维链推理模型),且拥有绝对空白纯净的上下文。它只接收两样东西:
- 原始任务目标。
- 统一的标准 Git 补丁(Diff)。
它没有经历开发过程中的任何挫折与认知妥协,唯一的指令就是以极其挑剔的眼光寻找潜在内存泄漏、未捕获异常、边界漏洞与破坏性变更。一旦审查员亮红灯,反馈会直接递交主写 Agent 修改,直至完全绿灯才允许推送发布。
核心 4:预索引 AST 代码知识图谱(codegraph)
为了彻底杜绝主写 Agent 在 5 万行代码库里使用盲目的全局全文检索,我们接入了 colbymchenry/codegraph。
在修改代码前,Agent 通过代码图谱查询特定函数或类的调用方(Callers)、被调用方(Callees)以及继承关系。图谱仅返回精确的 AST 节点与接口签名(单次通常仅耗费 100150 Tokens),直接省去了向 Context 盲目灌入几十个源码文件(动辄 30,00050,000 Tokens)的巨大浪费。
生产实测指标对比
我们在约 50,000 行代码的 TypeScript/Python 生产代码库中,针对 5 项全栈功能开发任务进行了实测对比(取单任务平均值):
| 评估指标 | 自由多 Agent 蜂群 | 传统单一 Agent | 单写多审 + 图谱索引架构 |
|---|---|---|---|
| Git 合并冲突次数 | 14 次 / 任务 | 0 次 | 0 次 |
| 平均 Token 消耗 | ~480,000 | ~85,000 | ~62,000(得益于图谱精准裁剪) |
| 上下文溢出/遗忘崩溃 | 极高(记忆迅速污染) | 中等(长任务难收敛) | 0 次(完美收敛) |
| 隐式逻辑回归发生率 | 22%(架构决策打架) | 12%(主观盲区) | < 1.5%(审查员严格拦截) |
| 任务端到端耗时 | 18.4 分钟(大量重试) | 14.2 分钟(串行等待) | 6.8 分钟 |
落地指导原则
如果你准备为自己的团队或系统搭建 Coding Agent 流水线,请牢记以下四条原则:
- 写操作永远单线程:严禁让两个 LLM 线程同时对同一个工作目录持有写入工具。如确需并行,必须划分完全独立的 Git Worktree 并由人把关合并。
- 子任务只交句柄,不传过程:外包调研与素材任务时,要求子进程落盘并只返回文件绝对路径,绝不把几十页的中间对话回传给主控。
- 审查模型必须保持“失忆”:负责审核代码的模型绝对不能是编写代码的模型,也绝不能看到编写过程中的对话泥潭。给它干净的 Diff,让它无情挑刺。
- 先建图谱,再调 Agent:在一个中大型代码库里盲目 Grep 是自杀行为。预先基于 AST 构建符号索引,才能让 Agent 在极低的 Token 预算下精准定位。
想为您的业务落地这套高可靠 AI 自动化方案?
我为企业与初创团队设计、搭建并运维自主 AI Agent 基础设施、内部高效工具链与高确定性自动化系统,帮助业务摆脱繁琐的人工重复劳动与脆弱的实验室级 AI 概念验证(PoC)。
无论您是希望将日常软件开发自动化、构建坚如磐石的企业级 Agent 协同流水线,还是定制自托管自动化服务:
- WhatsApp: 点击直接沟通 (+60 12-797 2969)
- Email: [email protected]
- 官方网站: hoelee.com