AI Agent 研发工作流的设计与实现

最近用 Agent 处理需求时,我慢慢养成了一套习惯。

实际使用时,我不会一上来就让 Agent 改代码,而是先让它读原始需求、翻相关代码,再整理一份实现方案。方案出来后,我会开一个新会话,交给另一个 Agent 做 Review。确认没什么明显遗漏,才进入开发。

这样做确实比“把需求扔给一个 Agent,然后等它交作业”稳一些。但重复几次以后,我发现 Agent 在干活,我也没闲着。

我得选择下一个 Agent,把前面的结果复制过去,补上缺少的上下文,再告诉它现在要做什么。Review 提出问题后,我还要把意见送回原来的会话。一项任务来回几轮,剪贴板里全是 Prompt 和 Markdown。

有一次我在几个窗口之间切来切去,突然觉得有点好笑:Agent 没有取代我的工作,我只是成了它们之间的消息队列。

为什么我会用两个 Agent

最开始拆成两个 Agent,并不是为了追求“多 Agent 架构”。我只是发现,让同一个 Agent 检查自己的方案,效果经常不好。

第一轮一旦定下方向,即使再提醒它“仔细检查”,它也很容易顺着原来的思路继续走。换一个没有参与前面讨论的 Agent,反而更容易问出一些直接的问题:这个改动会不会破坏兼容性?失败时怎么处理?测试覆盖了什么?

于是,我把两件事分开了。

第一个 Agent 负责理解需求,找代码,列出影响范围和验收条件。第二个 Agent 只拿原始需求、项目约束和最终方案,从头检查。如果发现问题,方案就退回去修改。


flowchart TD
    I["收到需求"] --> A["需求分析"]
    A --> R["独立 Review"]
    R -->|需要修改| A
    R -->|通过| H["我来确认"]
    H -->|调整方案| A
    H -->|开始开发| D["开发"]
    D --> C["代码 Review"]
    C -->|存在问题| D
    C -->|通过| V["验证与交付"]

这套做法能起作用,关键在于两个 Agent 看到的信息不同,分工也不同。一个提出方案,另一个专门挑问题。

有些决定我还是希望自己来做。比如要不要改变现有交互,值不值得承担兼容成本,或者要不要顺手扩大需求范围。这些问题没有唯一正确答案,知道更多代码也不一定能替我决定。

所以图里的“我来确认”并不是自动化没做完,而是我特意留下来的停顿。Agent 先把事实和风险摊开,我做选择,然后再让流程继续。

问题其实不在 Prompt

一开始,我只想把常用 Prompt 保存下来:需求分析一份,方案 Review 一份,开发实现一份。需要时选一个模板,总比每次重新写方便。

后来我发现,真正麻烦的是那些藏在文字外面的判断:

  • 现在应该调用哪个 Agent;
  • 它需要看到哪些内容;
  • 上一步要交付什么结果;
  • Review 没通过时应该回到哪里;
  • 哪一步必须停下来等我确认;
  • 执行中断以后是继续,还是从头再来。

Prompt 能告诉 Agent 这一步要做什么,却不会替我管理整项任务。真正反复发生的,是阶段之间的流转。

我开始把这件事当成一条普通的工作流来处理:每一步都有输入和产物,也有进入下一步的条件。Agent 只管眼前的任务,不必知道后面还会调用谁。

流程有了,还得有个地方保存整项任务的信息。我把一项从需求理解走到开发交付的任务叫作 Issue。它不一定对应 GitHub Issue,也不是 Agent 自带的概念,只是这套工作流中的一次任务。

原始需求、当前阶段、每轮产物和执行状态都放在同一个 Issue 里。Agent 不必理解这个概念;工作流会取出当前阶段需要的信息,再把结果存回去。

有了这个载体,流程配置大概可以写成这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
stages:
- id: requirement-analysis
agent: requirement-agent
next: requirement-review

- id: requirement-review
agent: review-agent
approved: human-confirmation
revision_required: requirement-analysis

- id: human-confirmation
type: manual-gate

- id: implementation
agent: development-agent

这份配置并不复杂,却明确写出了每个阶段的去向。流程不再由 Prompt 末尾的一段话临时指挥,而是按照外部状态和规则运行。

我可以换掉某个 Agent,也可以调整 Review 标准,不用重新编排整段对话。Prompt 只需要服务当前阶段,不再承担整个流程。

Agent 之间应该传什么

手工操作时,最顺手的办法是复制上一段聊天记录。看起来信息最完整,也不需要额外整理。

但聊天记录里有太多过程:试过又放弃的方案、还没证实的猜测、工具输出,以及中途被推翻的结论。下一个 Agent 虽然看到了全部内容,却不一定知道最后该信哪一段。

我后来更倾向于让每个阶段交付一份“成品”。

需求分析的结果应该写清楚要解决什么、不做什么、会影响哪里、有什么风险、最后怎么验收。Review 的结果则要明确给出通过或退回;如果退回,还要指出问题和下一轮必须补齐的内容。

这样做以后,前后两个 Agent 不需要共享完整对话。后一个 Agent 只读取原始问题和上一阶段确认过的结果,工作流也能根据 Review 的结论决定继续还是返回修改。

同一个方案改了几轮,也不必互相覆盖。每轮产物都可以单独保存。回头看时,我能知道某个决定是什么时候加进去的,而不是在一条很长的聊天记录里猜。

我现在会用一个很简单的问题判断产物是否合格:如果关掉当前会话,只看它提交的结果,我还能不能接着往下做?如果不能,那它交付的多半还只是聊天过程。

让 Agent 真正进入仓库

流程只处理文档时,事情还比较简单。等开发 Agent 开始修改代码,目录和进程也得一起管起来。

从技术上说,只读的分析任务可以共享代码目录。但我最后还是为每次 Agent 执行准备了独立的 Git worktree。这样分析和 Review 面对的是确定的代码状态,开发任务也不会碰到我当前目录里的未提交修改。

worktree 共享原仓库的 Git 对象,不需要重新 clone 一份代码,但每次执行都有自己的工作目录、索引和分支状态。

1
2
3
4
5
6
主仓库
├── 我正在使用的目录
└── Agent Worktrees
├── issue-101-analysis
├── issue-101-development
└── issue-102-development

目录隔离以后,还有进程的问题。我用的 Agent 是长时间运行的交互式命令行程序,不能让它的生命周期跟着浏览器连接一起结束。

现在的实现用 tmux 托管 Agent 进程。浏览器断开后,Agent 仍然可以继续运行;我回来时可以重新接上终端查看输出,必要时也能自己接管。

把这几部分接起来后,我发现一次阶段任务至少包含四类状态:


flowchart TB
    J["阶段任务"] --> S["任务状态
现在进行到哪一步"] J --> G["Git Worktree
代码改成了什么样"] J --> T["tmux 会话
进程是否还在运行"] J --> E["Agent 会话
它记得哪些上下文"]

这几类状态会各自变化,不能混成一个笼统的“运行中”。代码还在,tmux 进程可能已经退出;Agent 上下文能够恢复,也不代表原来的 worktree 还能继续使用。

即使进程正常结束,阶段也可能没有完成。因此,开发 Agent 结束前要提交结构化结果,写明修改了哪些文件、做过哪些验证、测试是否通过,以及还有什么问题没有解决。进程退出码只能说明程序已经结束,不能代替阶段结论。

目前先做到这里

现在,需求分析、独立 Review、worktree 隔离、tmux 托管和结构化结果都已经接进了流程。一项需求可以从分析走到开发,不再需要我守着几个窗口来回转发消息。

做到这里,我才更清楚地看到:worktree 和 tmux 能让 Agent 稳定执行,却解决不了阶段之间的流转。如果仍然靠人复制内容,后台进程运行得再稳,我还是那个负责转发消息的人。

还有一些问题没有处理,比如中断以后怎样恢复,任务结束后什么时候清理环境。目前我只有初步设计,不想在这篇文章里把它们写成已经验证过的结论。

回头看,整件事是从“少复制几次 Prompt”开始的。Prompt 可以换,Agent 也可以换,我想固定下来的是几个步骤之间的关系:先分析,再独立 Review,遇到取舍时停下来,确认以后再继续。

只要下一次处理需求时,我不用再充当 Agent 之间的消息队列,这套工作流就已经解决了一个很具体的问题。

延伸阅读


AI Agent 研发工作流的设计与实现
https://blog.phlin.cn/2026/08/09/ai-agent-workflow/
作者
phlin
发布于
2026年8月9日
许可协议