我在 Zed 里给三个 AI Agent 分了工,这次终于没把项目搞乱

204 阅读14分钟

image.png 这套流程的起点,其实不是一个多么宏大的“多 Agent 架构”。

单纯是因为我受够了返工。

我在做一个体量不算小的个人项目,开发时间拉得比较长,模块和测试也越来越多。刚开始,我会把一个需求从头到尾丢给同一个 Agent:先让它分析,再让它设计,然后写代码、跑测试,最后顺便做个总结。

小需求这么干很舒服。需求一复杂,问题就来了。

Agent 前面刚说某个接口不能破坏,写到一半发现不好实现,后面就悄悄换了一套接口;测试有一个失败,它可能解释成“与本次修改无关”,然后告诉我整体完成;换个会话继续时,新 Agent 又得重新读一遍仓库,很多之前讨论过的取舍也丢了。

最麻烦的是,我很难判断它到底是“代码写完了”,还是“这件事真的做完了”。

于是我开始给不同的 Agent 分工。现在我的组合是:

  • Codex + GPT-5.6:做架构、拆父任务、排优先级,最后回来验收;
  • OpenCode + MiMo 2.5 Pro:继续往下拆,把父任务写成可以直接施工的子任务;
  • Claude Code + MiniMax M3:按顺序执行子任务,写代码、跑测试、记录结果。

平时我主要在 Zed 的 External Agents 里使用它们。当然,直接用各家的 CLI 也完全没问题。流程能不能跑起来,关键不在编辑器,而在仓库里有没有一套大家都认的规则。

这篇文章就是我现在这套做法的开发记录。它还在迭代,不敢说是什么标准答案,但至少已经让我少返了不少工。

我为什么没有让最强的模型包办一切

一开始我也想过:既然架构模型更强,干脆从头到尾都交给它,不就省掉交接了吗?

实际用下来,不太划算。

个人开发很难不考虑成本。这里的成本也不只是账单上的模型费用,还包括等待时间、反复读取上下文、失败后的返工,以及我自己盯着 Agent 防止它跑偏的精力。

架构判断很贵,因为一旦错了,后面五六个任务都可能跟着错。改一个明确的类型文件、补几条测试,则是另一种工作。它需要认真,但未必需要每一步都动用最重的推理。

所以我的思路很朴素:贵的能力用在刀刃上。

Codex 负责少量但影响很大的决定

我自己的体验是,Codex + GPT-5.6 更适合处理全局问题。比如:

  • 这个需求会不会破坏现有分层;
  • 新模块应该放在哪里;
  • 哪些接口需要先冻结;
  • 几个任务之间到底是什么依赖关系;
  • 所有代码合起来后,有没有偏离最初目标。

这些事情出现的频率不高,但判断错一次会很贵。所以我让 Codex 站在流程两头:开头设计,结尾验收。

它不负责一直埋头写实现。这样既能用上它的全局推理,又不用让高成本模型去做大量机械修改。

OpenCode + MiMo 负责把“想法”变成“施工图”

架构任务通常还是太粗。

比如“增加一个可配置的规则模块”,听起来已经很具体了,但真正动手时还有一堆问题:类型放在哪个文件?注册表长什么样?错误在加载时还是运行时抛?先写执行器还是先写校验?哪些兼容行为必须保留?

这部分我交给 OpenCode + MiMo 2.5 Pro。

它会读取父任务、架构文档和实际代码,然后拆成一组有先后顺序的子任务。我的感受是,这个组合很适合做代码阅读和结构化拆解,成本与效果也比较平衡。

它不决定产品方向,也不直接改生产代码。它只负责把模糊空间尽量消掉,让下一位拿到的不是一句需求,而是一张施工图。

这个中间角色非常重要。没有它,架构模型直接写到底会贵;执行模型自己边设计边写,又很容易返工。

Claude Code + MiniMax M3 负责高频执行

真正占用轮次最多的还是写代码、补测试、看错误、再修正。

当子任务已经明确到文件、接口、步骤和预期结果之后,我会交给 Claude Code + MiniMax M3。这个组合在我的流程里更像实施工程师:按设计施工,遇到范围外的问题就记录,不自行扩大任务。

高频阶段对速度和成本比较敏感。提前做详细设计之后,执行模型不需要每次都重新理解整个项目,也不需要临场做大的架构选择。

不过我加了一条限制:它写完以后,只能说“已实现,等待验证”,不能说“已完成”。

代码写出来和任务真正完成,中间还差一次整体检查。

这三个角色不是固定绑定某个模型。以后模型能力和价格变了,我可能会换组合。但“架构、详细规划、执行、最终验收”这几个职责,我大概率会保留。

顺便安利一下 Zed

我现在主要通过 Zed 的 External Agents 跑这套流程。

先声明,这套方法并不依赖 Zed。Codex、OpenCode、Claude Code 都可以直接通过 CLI 使用。只要它们进入同一个仓库,能读取同一套任务和状态文件,流程就成立。

但从个人体验来说,Zed 是我目前觉得最适合 AI 编程时代的编辑器。

我喜欢它,不是因为它又做了一个聊天框,而是因为代码、Diff、终端和 Agent 会话都在一个很干净的环境里。切换 Agent 时,我没有离开当前仓库,也不用在网页聊天和 IDE 之间来回复制上下文。

External Agents 对我尤其合适。我可以保留不同 Agent 各自的能力和习惯,同时把 Zed 当成统一操作台。今天用 Codex 看架构,接着让 OpenCode 拆任务,再让 Claude Code 实现,面对的始终是同一份工作区。

Zed 本身也足够轻快,界面比较克制。AI 功能在旁边,但不会把正常的代码阅读挤到角落里。这一点很对我的胃口。

如果你更喜欢终端,继续用 CLI 就好;如果正在找一个适合多 Agent 协作的编辑器,我确实很推荐试试 Zed。

Agent 之间不传话,它们读仓库

刚开始做多 Agent 协作时,我下意识会写很多交接提示词:

上一个 Agent 已经完成了 A,现在请你继续 B。注意它改了这些文件,测试还有一个旧错误……

写几次之后就会发现,这和人工写周报没什么区别,而且很容易漏。

现在我把仓库本身当成共享记忆。大致目录如下:

docs/
├── architecture/       # 系统结构和边界
├── decisions/          # 关键决策记录
├── roadmap/            # 优先级和执行顺序
├── epics/              # 一组相关目标
├── tasks/              # 父任务
├── subtasks/           # 可以直接实施的子任务
├── implementation/     # 实际做了什么、测试结果如何
├── reviews/            # 父任务的最终验证
└── risks/              # 仍然存在的风险

这些文档不是为了让目录看起来专业,而是各自负责回答一个问题。

  • Architecture 和 ADR:为什么这么设计;
  • Roadmap:现在先做什么;
  • Task:这件事最终要交付什么;
  • Subtask:具体怎么做;
  • Implementation Report:实际上做了什么;
  • Review Report:整体是不是真的通过了。

聊天只负责发指令,事实必须写回仓库。

如果 Agent 在聊天里说“做完了”,但任务状态、测试结果和实施报告都没有变化,那么在这套流程里,它就没有做完。

三个 Agent,四个工作阶段

Codex 在开头和结尾各出现一次,所以三个 Agent 实际组成了四个阶段。

第一段:Codex 拆父任务

我通常只需要说:

基于现有架构和方案做任务拆分。

Codex 会先检查需求是否符合现有架构。如果需要改变系统边界,它应该先写 ADR,而不是一边实现一边改设计。

然后它会创建父任务,写清楚目标、范围、非目标、验收标准、依赖和优先级。

父任务不需要规定每一个方法签名。它更像一份工程合同,解决“要做什么”和“做到什么程度”。

例如:

TASK-014:可配置规则模块

目标:支持版本化配置、注册和可解释执行结果。
依赖:现有领域接口和输入白名单。
验收:非法引用和越界输入必须在进入运行前被拒绝。
状态:待拆分。

第二段:OpenCode 拆子任务

接下来我对 OpenCode 说:

拆分子任务。

它会从 Roadmap 里找到优先级最高、依赖已经满足的父任务,然后去读真实代码。

拆完以后,目录可能像这样:

docs/subtasks/TASK-014/
├── TASK-014-ST-01-config-contracts.md
├── TASK-014-ST-02-registry.md
├── TASK-014-ST-03-executor.md
├── TASK-014-ST-04-validation.md
└── TASK-014-ST-05-tests.md

这里最重要的不是拆成了五份,而是每一份都能单独实现和检查。

一个合格的子任务应该写清:

  • 哪些文件和符号要改;
  • 接口、类型或配置长什么样;
  • 按什么顺序改;
  • 哪些事情这次明确不做;
  • 测试放在哪里,输入和预期是什么;
  • 完成后要留下哪些证据。

“修改相关文件并增加合适的测试”这种话,我现在看到就会要求重写。它看起来像计划,实际上所有难题都还留着。

第三段:Claude Code 一次执行一个子任务

然后我对 Claude Code 说:

执行任务。

它会读取当前状态,自己选择最高优先级的 Ready 子任务。开始改代码前,先把状态写成“进行中”。

我默认一次只让它做一个子任务。这样会话上下文比较小,出问题时也容易定位,不会改到后面才发现第一步接口就错了。

完成后,它需要生成一份实施报告:

docs/implementation/TASK-014-ST-01.md

里面记录修改文件、实际运行的命令、测试结果、设计偏差、旧失败和剩余风险。

子任务此时的状态是:

已实现(待回流验证)

不是“已完成”。

第四段:Codex 回来做一次整体检查

当父任务下所有子任务都实现后,我再对 Codex 说:

回流验证。

这时它看的不是最后一个文件,而是整个父任务的累计 Diff。它会重新对照最初的验收标准,检查子任务组合之后有没有接口冲突、兼容问题、遗漏的数据迁移或者新的测试失败。

验证结果可以是通过、带条件通过或者退回。

如果退回,不是把整个任务推倒重来,而是重新打开最小的失败子任务。这样返工范围比较可控。

我最后用了一个很简单的状态机

以前我会写“完成 60%”“基本完成”。后来发现,不同 Agent 对“基本”的理解差异太大。

现在父任务只有这几个状态:

待拆分 → 待执行 → 进行中 → 待回流验证 → 已完成

子任务则是:

待执行 → 进行中 → 已实现(待回流验证) → 已完成

只有最后负责回流验证的 Codex 可以写“已完成”。

每次改状态时,相关文档要一起更新:子任务、父任务、Roadmap,以及实施或验证报告。这样下一个 Agent 不用相信上一段聊天,只需要相信仓库。

阻塞状态也不能只写“遇到问题”。要写清楚缺什么、失败命令是什么、需要谁做决定。

把这套规则写成 Skill

如果每次开会话都重新解释上述流程,很快又会出现不同版本。

所以我把它写成仓库级 Skill:

.agents/skills/orchestrate-agent-development/
├── SKILL.md
├── agents/openai.yaml
└── references/
    ├── repository-control-plane.md
    └── artifact-contracts.md

主 Skill 负责根据短指令选择角色:拆父任务、拆子任务、执行任务或回流验证。详细的目录规则和文档模板放在 references 中。

Claude Code 通过 .claude/skills/ 下的入口读取同一份规范,OpenCode 和 Codex 则读取 .agents/skills/。另外,我也在 AGENTS.md 和 CLAUDE.md 里留下了入口说明。

这样,我不需要每次贴一大段提示词。说一句“拆分子任务”,Agent 就知道去哪里找父任务、该产出什么,以及完成后要改哪些状态。

更重要的是,流程本身也进入了版本管理。哪条规则不好用,可以像改代码一样审查和调整。

目前我觉得最有用的几条经验

优先级高,不代表现在就能做

P0 可能依赖另一个 P0。Agent 应该先看优先级,再看依赖是否满足。两个条件都满足,才算 Ready。

子任务按“可验证结果”切,不按文件切

“修改三个文件”不是一个好的边界。“建立配置契约,并让非法输入测试通过”才是。

旧失败必须老老实实记录

如果任务开始前测试就有失败,不要偷偷算到本次头上,也不要顺手扩大范围去修。实施报告里记录清楚,最终验证时再判断它是否阻塞。

共享 dirty worktree 时,陌生改动默认属于别人

每个 Agent 开始前都先看 git status 和重叠 Diff。不理解的修改不要 reset,更不要用 checkout 清掉。

如果两个子任务会碰同一个核心接口,就算理论上能并行,我也更愿意让它们串行。

最终验证一定要看累计 Diff

每个子任务各自通过,不代表它们组合起来也正确。接口语义、数据迁移、兼容路径、表现层和核心层的职责,都可能在组合时出问题。

这也是为什么我没有让执行 Agent 自己宣布完成。

它适合什么,不适合什么

如果只是改一句文案、调一个局部样式,走完整套流程肯定太重。

我一般在这些情况下使用它:跨多个文件、会影响核心接口、涉及数据迁移、业务规则复杂,或者这个功能之后还会继续扩展。

简单修改仍然直接做。流程是为了减少复杂工作的混乱,不是为了给每次提交增加仪式感。

还没解决的问题

目前很多状态更新仍然靠 Agent 自觉写文档。我准备继续补一些小工具:

  • 自动检查父任务和子任务状态是否一致;
  • 自动找出下一个 Ready 子任务;
  • 检查实施报告有没有真实命令结果;
  • 根据文件重叠提醒哪些任务不适合并行;
  • 把回流验证结果变成机器可读的质量门禁。

不过我暂时不想马上做一个复杂的编排平台。先把规则跑顺,比先做一个漂亮的控制台更重要。

最后

这段时间最大的体会是,多 Agent 开发并不是让几个模型互相聊天。

真正有用的是让它们各自做擅长的事,并且把交接写进仓库:架构有出处,任务有状态,实现有证据,完成有验收。

对我来说,这套流程最终解决的是三件事:

  • 效率:少重复理解,少来回试错;
  • 效果:关键设计和最终质量由更适合的模型把关;
  • 成本:强模型用于高杠杆判断,高频实现交给成本更合适的组合。

现在我可以在 Zed 里对 OpenCode 说一句“拆分子任务”,再对 Claude Code 说一句“执行任务”。我仍然会看设计和 Diff,但不再需要亲自搬运每一段上下文。

这才是我想要的 AI 编程:不是少写几行代码,而是一个人也能把开发过程组织得更像一支小团队。