我为什么要做一个有门禁的多 Agent 开发流水线

把 Codex、Claude Code 与 DeepSeek 拆成规划、实现、审查、验证、兜底五个角色,用外部状态机、独立工作区和确定性审批门禁,让模型协作产出有证据、可恢复、可控制成本的开发流程。

AI 已经会写代码了,真正让我头疼的是另一个问题:当模型参与真实开发时,怎么让它稳定、可控、低成本、可恢复?

最初我遇到几个具体问题。模型会改太多文件、悄悄扩大需求、跑一堆不必要的测试;更麻烦的是它会把“它以为完成了”和“真的完成了”混在一起——一句“已完成,测试通过”只是声明,不是证据。而且聊天记录不是状态机:任务跑到一半失败,很难判断当前状态、哪个 commit 是产物、哪些测试真的跑过、失败后能不能恢复。

三个原则:状态、验证、门禁都要外部化

多 Agent 不是让两个模型互相聊天,而是责任分离:Codex 负责规划、审查和兜底,DeepSeek 负责实现和普通修复,外部程序做裁判。每个任务在磁盘上保存 STATE.json 等一组机器可读状态,即使对话断了也能恢复;验证由外部命令的退出码和日志决定,而不是模型自述;最终能不能 push 由确定性门禁检查,而不是模型一句话。

几个关键机制:

  • 独立 worktree:每个任务在自己的分支里跑,不污染主工作区,失败产物可以留给 Codex 接管。
  • 结构化交接:DeepSeek 必须输出带 files_changed、commands_claimed 的 JSON,即使失败也一样,外部程序才知道下一步。
  • 修复次数上限:DeepSeek 最多修两次,两次失败就由 Codex 接管 worktree。真实使用里 DeepSeek 经常 max_turns 退出,但它留下的 80% 代码通常可用,Codex 补上类型、测试后提交。
  • 分层验证:开发期只跑失败相关测试,完整验证只在最终候选上跑一次,避免每轮全量测试烧额度。

从 PowerShell 脚本到 Codex Plugin

第一版用 PowerShell 快速验证流程是否成立,但它更像脚本工具而不是 Codex 能力。后来改成三层:Skill 负责触发和编排,TypeScript MCP Server 暴露 14 个结构化工具(创建任务、提交计划、查询 Job、取消、提交审查……),PowerShell 保留状态机和恢复能力。Codex 不再面对一堆命令,而是面对明确的工具边界,也不允许随便执行任意 shell。

迁移时我只把低风险、可测试的只读层逐步 TypeScript 化,而不是一次性重写控制面。因为流水线自己也是工程系统:有一次两个 PowerShell 脚本把 git diff --name-only 的多行输出当成一个路径,导致本应允许的多文件修复被错误拒绝——出错的不是 DeepSeek 的代码,而是编排层自己的边界条件没测够。

学到的

AI 编程的核心不是“让模型多写代码”,而是“让模型少乱来”;失败产物很有价值,进程失败不等于产物无用;成本控制是架构问题——不重复塞完整上下文、日志只让模型读摘要、DeepSeek 做实现 Codex 做判断;最终门禁必须是确定性的,模型可以建议批准,但不能自己批准。

模型负责建议和产出
程序负责约束和验证
用户负责最终授权

这个项目的本质不是“让一个超强模型全自动完成一切”,而是给模型明确角色、给任务明确状态、给修改明确边界、给验证明确证据、给失败明确恢复路径、给最终操作明确门禁。未来真正有用的 AI 开发工作流,不会只比谁的模型更聪明,而是比谁更会组织模型。