这段时间我一直在用 Codex 做项目,越用越明显地感觉到一个问题:Codex 的执行力很强,但它更像一个单线程的工程助手。

你给它一个明确任务,它可以读代码、改文件、跑命令、修 bug,也能在一个比较长的上下文里持续工作。小项目或者小需求里,这种体验已经很好。但项目一复杂,问题就会变得混在一起:前端体验、产品收束、测试复现、文档维护、Git 提交、Skill 设计、开发规范,都会挤在同一个上下文里。

这时候 Codex 不是不会做,而是缺少一种“团队工作”的结构。它可以完成任务,但它没有天然的 agent team;它可以被提示成某个角色,但这个角色往往只存在于当前对话里;它可以发现问题,但发现的问题如果没有稳定的交接方式,很容易变成一句聊天记录。

我后来做了一件很简单的事:把 agent team 的协作方式写进项目本身。

从 Claude Code 的 Agent Teams 说起

Claude Code 的 agent team 思路给了我很多启发。它不只是“多开几个 AI”,而是把不同职责的 agent 拆出来,让主 agent 可以把具体问题交给更适合的队友。

比如一个 agent 专门做代码审查,一个 agent 专门写测试,一个 agent 专门处理前端实现,一个 agent 专门做文档或研究。主 agent 不需要什么都亲自干,它更像一个 lead:判断问题、分配任务、接收结果、继续推进。

我之前专门写过一篇介绍这个思路的文章,叫《Agent Teams — 一个搞不定,组队来》。那篇更偏原理,讲的是 MessageBus、队友线程和 inbox 注入这些机制。这一篇更偏我自己的 Codex 实践:Codex 没有现成的 agent team,我就尝试把类似的协作协议写进项目文件里。

我真正想借鉴的是什么

我借鉴的不是某个具体实现,而是这几个点。

第一,职责要拆开。复杂项目里的问题本来就不是同一种问题。UI 还原不准、接口状态不对、测试缺失、构建报错、文档过期,它们需要的判断方式不一样。全都塞给一个 agent,它很容易一边修 bug,一边顺手改别的东西,最后上下文越来越乱。

第二,agent 之间要能交接。一个 agent 在做 A 的时候,经常会发现 B。比如测试 agent 复现问题时发现移动端布局有 bug,但这个问题应该交给设计或开发;开发 agent 改组件时发现设计规范缺失,这应该交给设计规范专家;项目经理整理提交时发现变更说明不清楚,这可能要回到开发或产品那里补信息。

第三,交接要留下记录。人类团队里会有 issue、owner、状态、复现步骤和处理结果。AI agent 也需要类似的东西,只是对 Codex 来说,不一定要接入很重的项目管理系统。Markdown 文件就够用了。

Codex 缺的不是写代码能力,是交接层

我一开始用 Codex 的方式很直接:把需求丢进去,让它自己跑。明确的小任务确实很舒服,比如改一个组件、补一个脚本、修一个构建错误。Codex 能快速读项目,也能直接动手。

但只要任务变复杂,就会遇到一个很微妙的情况:它在做 A 的时候发现了 B。

如果这些发现只留在对话里,就很容易丢。更麻烦的是,有些 agent 会“顺手修一下”。顺手修看起来很高效,但项目一大就会变成风险:职责边界不清楚,修改范围变大,验证也跟不上。

所以我后来真正想补的,是一个稳定的交接层。Codex 会写代码,但它需要一个地方把“谁发现的、该交给谁、怎么复现、修完没有”这些信息接住。

我的做法是两件事:

AGENTS.md      负责写规则和角色分工
agent-report/ 负责放跨 agent 的问题交接

这两个东西结合起来,就相当于把一个轻量的 agent team 协议放进项目里。Codex 每次进入项目,不只读代码,也读协作方式。

如何执行

第一层:AGENTS.md 写清楚谁负责什么

AGENTS.md 是我放项目规则的地方。它不只是写“怎么构建”“怎么测试”,还要写 agent 在这个项目里应该怎么协作。

我会在里面写清楚哪些问题可以直接处理,哪些问题应该写 report;哪个角色负责产品收束,哪个角色负责设计体验,哪个角色负责开发规范,哪个角色负责测试验证。这样主 agent 扫到一个问题时,不需要重新猜“这件事该谁管”。

每个项目不一定完全一样,但我自己比较常见的一套分工是这样的:

- 产品:负责收束功能,规划架构;
- 设计:负责交互和体验审查;
- 设计规范专家:负责维护 design.md;
- 开发:负责开发代码和执行实现;
- 开发规范专家:负责维护 AGENTS.md 文档;
- 测试:负责测试用例,并使用 computer use 做真实操作测试;
- 客服:负责撰写中英文 README 文档;
- 项目经理:负责 git 规范、提交日志梳理和提交;
- Skill 专家:负责撰写、架构和审查 skill。

这套角色不是为了模拟一家公司,而是为了让 Codex 有判断入口。体验问题优先交给设计,工程规则问题交给开发规范专家,文档问题交给客服,测试复现问题交给测试,Skill 的问题交给 Skill 专家。

角色定义清楚以后,AGENTS.md里还要写一条关键规则:如果发现的问题不属于当前 agent 的职责范围,不要直接顺手改,先写 report。report 放到agent-report/open/,由主 agent 判断要交给谁。

第二层:agent-report 放所有跨角色问题

agent-report/ 是我在项目里维护的交接区。它看起来像一个普通文件夹,但用途很明确:专门放 agent 之间需要交接的问题。

一个 agent 遇到不属于自己职责的问题,就写一个 Markdown report 放进去。这个 report 要写清楚提交 agent、建议交接 agent、问题描述、复现方式、影响范围、相关文件、期望结果和当前状态。

主 agent 负责看这些 report,把它们交给对应的 agent。对应 agent 处理完以后,再回到同一个 report 里写处理结果、修改文件、验证方式和后续风险。

这样一个问题就不会只停留在“我发现了一个问题”。它会变成一条可以被分配、被处理、被验证、被归档的记录。

用目录表达状态

我一般会把目录拆成这样:

agent-report/
  open/
  assigned/
  resolved/
  archived/

open里放刚发现、还没分配的问题;assigned里放已经交给某个 agent 的问题;resolved里放已经修完并写了验证结果的问题;archived 里放确认关闭后的历史记录。

这个结构很土,但好用。Codex 不需要猜一堆散落的 Markdown 哪个是待办、哪个已经修了,文件夹本身就表达了状态。

用 frontmatter 补充结构化信息

目录能表达流转阶段,但单个 report 里最好也有结构化信息。比如:

---
status: open
owner: frontend-agent
created_by: qa-agent
priority: medium
created_at: 2026-07-05
---

这样以后不管是人读,还是让 Codex 扫描,都能很快知道这个问题现在归谁、谁提的、优先级是什么。

第三层:report 必须固定模板

这个地方我踩过坑。如果只是告诉 agent “发现问题就写个 md”,最后一定会变成一堆风格不同的散文。有的只有一句话,有的没有复现步骤,有的没有相关文件,有的修完以后没有结果。主 agent 再回来看,还是要重新理解一遍。

所以我给 report 做了固定模板。

---
status: open
owner: frontend-agent
created_by: qa-agent
priority: medium
created_at: 2026-07-05
---
# 问题标题
## 提交 Agent
qa-agent
## 建议交接 Agent
frontend-agent
## 问题描述
这里写清楚问题是什么,在哪个页面、模块或流程中出现。
## 复现方式
1. 打开某个页面或执行某个命令。
2. 进行某个操作。
3. 观察到某个异常结果。
## 影响范围
说明这个问题影响哪些功能、用户路径、组件、接口或测试。
## 相关文件
- src/xxx.tsx
- components/xxx.tsx
## 期望结果
描述修复后应该达到的状态。
## 当前状态
open
## 处理结果
待处理
## 修改文件
待处理
## 验证方式
待处理
## 后续风险
待处理

这里真正关键的地方不在字段名,而在于模板从一开始就预留了“处理结果”。很多问题管理只做了前半段:有人提问题,有人接问题。但 AI 协作里更容易断在后半段。agent 改完代码以后,如果不回写,它可能在对话里说“已修复”,但下一次主 agent 再接手时,并不知道具体改了哪里、怎么验证的、有没有风险。

所以解决问题的 agent 必须回填这几块:

## 处理结果
已修复。移动端卡片底部增加安全间距,完成按钮不再被固定底栏遮挡。
## 修改文件
- src/components/RequirementCard.tsx
- src/styles/layout.css
## 验证方式
- npm run lint
- npm run build
- 390px、430px、768px 视口手动复现通过
## 后续风险
如果后续底栏高度变化,需要同步检查卡片底部 safe-area 间距。

这几行会让整个交接质量完全不一样。它把一句模糊的“我修了”,变成了“我修了什么、动了哪里、怎么确认、还要注意什么”。

第四层:状态让事情真的闭环

我一开始也觉得状态可以省略,反正都是 Markdown。但用了一段时间以后发现,状态一定要有。

没有状态的 report 很快会变成一堆没人敢动的文件。你不知道它是刚提出,还是已经有人接了;不知道它是修完了没归档,还是修到一半卡住了。AI 更依赖明确结构,如果结构模糊,它就会反复重新判断。

所以我现在至少会保留这四个状态:

open -> assigned -> resolved -> archived

刚发现的问题放open。主 agent 看过以后,移动到assigned,并确认 owner。处理 agent 修完并回写验证结果,再移动到resolved。最后主 agent 或 QA agent 复验通过,移动到archived

这套状态不复杂,但它让 Codex 可以像读一个小型任务系统一样读项目。它不需要额外数据库,也不需要开 Jira。文件夹、frontmatter、Markdown 模板加起来,已经够支撑很多项目里的 agent 协作。

一个真实工作流大概是这样

假设测试 agent 在测试需求画布时发现一个问题:移动端下,需求卡片底部的完成按钮被固定底栏遮住了。

它先不去改前端样式,而是在agent-report/open/ 新建一个 report。里面写清楚复现方式:启动项目,打开需求画布,把浏览器切到 390px 宽度,滚动到卡片底部,观察完成按钮是否被遮挡。它还会写影响范围:移动端用户无法稳定完成需求卡片。

主 agent 扫到这个 report 后,判断这是前端布局问题,于是把文件移动到agent-report/assigned/,owner 改成开发或设计,具体看问题更偏实现还是体验。

对应 agent 接手以后,按 report 里的复现方式检查问题,修改相关组件和样式。修完以后,它不能只在对话里说完成了,而要回到 report 里写:

## 处理结果
已修复。移动端卡片底部增加安全间距,并调整固定底栏层级,完成按钮不再被遮挡。
## 修改文件
- src/components/RequirementCard.tsx
- src/styles/layout.css
## 验证方式
- npm run lint
- npm run build
- 390px、430px、768px 视口手动复现通过
## 后续风险
如果后续底栏高度变化,需要同步检查卡片底部 safe-area 间距。

然后它把状态改成resolved。主 agent 或测试 agent 再做一次复验,确认没问题以后归档。这就是我想要的闭环。

最小版本怎么做

如果要在一个项目里试这套方法,我会先做三件事。

第一,在根目录写一个AGENTS.md。不用一开始写得很复杂,先把项目常用命令、基本规范、几个 agent 角色和交接规则写清楚。

第二,建一个agent-report/ 文件夹:

agent-report/
  open/
  assigned/
  resolved/
  archived/

第三,放一个agent-report/TEMPLATE.md。模板里一定要有提交 agent、建议交接 agent、问题描述、复现方式、影响范围、相关文件、期望结果、当前状态、处理结果、修改文件、验证方式和后续风险。

只要这三件事有了,Codex 就不再只是围着当前对话转。它会开始围着项目里的协作协议转。

总结

收益

这套方法最直接的收益,是我不用一直把所有细节都抓在自己手里。

以前我用 Codex 做复杂项目,经常需要在脑子里记着很多事:这个问题是谁发现的,刚才哪个文件动过,测试有没有跑,文档有没有补,设计规范是不是又落后了。现在这些东西会被拆到不同 agent 的职责里,再通过agent-report 留下来。主 agent 不需要每次都从零理解,它可以顺着 report 往下分配和收口。

第二个收益是速度。这里的速度不是单次代码生成更快,而是项目推进更稳。一个 agent 在做开发,另一个 agent 可以专门补测试思路,设计规范专家可以维护design.md,开发规范专家可以维护AGENTS.md,项目经理可以最后整理提交日志。很多过去要我自己来回切换的事情,现在可以变成“让对应角色去处理”。

第三个收益是更容易解放双手。以前我经常担心 Codex 做着做着跑偏,因为所有事情都在同一个上下文里。现在我会更敢把一类任务交出去,因为我知道它发现跨职责问题时,不应该乱改,而应该写 report。这个规则降低了我盯过程的成本。

还有一个意外的好处是,项目本身会留下更多过程资产。AGENTS.md记录了这个项目的工作方式,design.md记录了设计规范,agent-report 记录了问题发现和解决过程。这些东西在项目越做越久以后很有价值,因为下一次 Codex 或人类接手时,不需要只靠聊天历史恢复上下文。

代价

它也不是没有缺点。

最明显的是 token 用量会上升。角色定义、交接规则、report 模板、历史 report,都会进入 Codex 的阅读范围。你让 agent 先读规则、再读 report、再处理问题,肯定比直接说“帮我改一下这个 bug”更重。对于很小的任务,这套流程甚至会显得有点笨。

第二个代价是维护成本。AGENTS.md需要更新,design.md需要维护,report 状态需要移动,解决后还要回写结果。如果没有主 agent 或项目经理 agent 定期收口,agent-report 也可能重新变成一个堆满 Markdown 的垃圾箱。

第三个问题是,它不能真正替代内置 agent team。Claude Code 那种队友线程、消息收件箱、权限冒泡和实时通信,是系统层面的能力。我现在这套做法更像是用文件系统模拟了一层协作协议。它透明、简单、可控,但没有那么自动化,也不一定适合所有项目。

还有一个风险是过度角色化。有时候一个问题很简单,开发 agent 直接改掉就行。如果为了遵守流程,硬要拆成产品、设计、开发、测试几轮,反而会拖慢节奏。所以我现在会把它当作复杂项目的协作机制,而不是每一个小需求都必须走的流程。

我的反思

这段时间用下来,我最大的感受是:AI 编程的难点正在从“让 AI 写代码”,慢慢变成“让 AI 在项目里持续正确地工作”。

单次生成代码的能力当然重要,但项目真正复杂以后,问题不只是代码本身。它还包括需求如何收束、设计规范如何延续、测试如何复现、文档如何同步、提交如何整理、历史决策如何保留下来。人类团队解决这些问题靠流程和协作,agent 其实也一样。

所以我现在不太把 Vibe Coding 理解成“随便说一句,让 AI 自己发挥”。我更愿意把它理解成一种新的项目组织方式:人负责判断方向和定义协议,agent 负责在协议里执行、发现问题、交接问题、回写结果。

这套AGENTS.md + agent-report的方法不复杂,也不完美,但它让我看到一个方向:与其一直期待模型一次性更聪明,不如先给它一个更适合长期工作的环境。AGENTS.md是规则,agent-report 是交接,状态目录是流转,回写结果是闭环。