AI Agent 长任务的底层逻辑,还是 Plan → Dev → Test → Review

你让 AI 改一个 bug,它写几行代码,跑个测试,搞定了。

但如果你让它做一个需要改十几个文件、跨好几个模块的大任务呢?

大部分人的经验是:它要么中间跑偏了,要么做到一半 session 断了重来,要么最后说”完成了”但你自己都说不清到底完成没有。

OpenAI 今年 2 月发了一篇文章叫 Harness Engineering,讲他们怎么用 Codex 从零写了一百万行代码。Anthropic 也发了一篇,讲多个 Agent 协作跑了将近四小时,造出一个能用的数字音频工作站。Factory.ai 把类似的思路做成了产品功能叫 Missions。

我自己基于这些想法,实现了一个叫 mission 的 skill(可以理解为一套 AI Agent 的工作流程和规则),在 Claude Code 里跑。

这些东西听起来很新,名字也唬人——Harness、Mission、Orchestrator、Validator。但拆到底层,逻辑其实很熟悉:

Plan(规划)→ Dev(开发)→ Test(测试)→ Review(验收)

跟每个程序员每天做的事一模一样。区别在哪?在于执行者从人变成了 AI,每个环节加了具体的保障机制。

这是我这个系列的第三篇。第一篇讲了从 OpenAI 文章里提取出的四个 worker 级别的 skill;第二篇横向比较了 OpenAI、Anthropic、Factory 三种做法。这篇讲底层逻辑到底是什么,以及怎么用。


先说一个词:Harness

Harness 这个词最近在 AI 工程圈用得很多。你可以把它理解成”缰绳”或者”脚手架”。

OpenAI 给了一个公式:Agent = 模型 + Harness

模型是 Claude、GPT 这些大语言模型本身的能力。Harness 是模型之外的所有东西:你给它的指令、任务拆分方式、状态记录文件、测试检查、review 流程。

打个比方:模型是一个能力很强的新人,Harness 是你给这个新人定的工作流程——先看需求文档,再写代码,写完跑测试,测试过了请别人 review。没有这套流程,新人能力再强也可能自由发挥把项目搞乱。

我实现的 mission skill,它本身就是一个 Harness。它的设计文档第一行写着:

This mission skill is itself a harness.

这个 Harness 里面装的是什么?就是 Plan → Dev → Test → Review,外加一套文件来保证每一步可追溯、可恢复、可验证。


整体结构:一张图说清楚

先看全貌,后面逐步拆解:

Plan(写验收标准 → 拆任务)
│
├─ 里程碑 1
│   ├─ Dev(派 AI-A 写代码,交作业)
│   ├─ Dev(派 AI-B 写下一个功能,交作业)
│   ├─ Test(派 AI-C 做工程检查 + AI-D 做行为验证)
│   │   └─ 没过?→ 自动生成修复任务 → Dev → 重新 Test
│   └─ 里程碑封存 ✓
│
├─ 里程碑 2
│   ├─ Dev → Test → 修 → 重新 Test …
│   └─ 里程碑封存 ✓
│
└─ Review(完成门控:所有验收标准 passed 才能结束)

注意几个跟人类开发流程不同的地方:

  1. Plan 阶段先写验收标准,再拆任务——类似 TDD(测试驱动开发),先说清楚”什么叫做完了”,再想怎么做
  2. Dev 和 Test 不是同一个 AI——写代码的和验证的必须是不同的 session,防止”自己给自己打高分”
  3. Test → Fix 是自动循环——测试没过不是任务失败,是自动生成修复任务,修完只重跑没过的部分
  4. Review 是机械门控——不是人拍脑袋说”差不多了”,是所有验收标准全部 passed 才能结束,否则 session 退不了

下面逐步说每个环节怎么做到的。


Plan:先定义”完成”,再拆怎么做

人在做大任务之前会列个计划。AI 也需要,但 AI 有个人没有的问题:它记不住前面说了什么。

AI 的对话窗口是有限的。跑久了,前面说过的需求、约定、上下文会被清掉。如果计划只活在对话里,session 一断就丢了。

所以 mission 的 Plan 阶段要做两件核心的事,都落文件。

第一件:把”什么叫完成”写成验收标准

这个文件叫 validation-contract.md。不是模糊的”用户能登录”,而是具体到工具和证据:

## 用户能登录

Surface: api
Tool: curl
Evidence: status-code, json-shape, response-body

POST /api/login 带正确凭证返回 200,body 包含 token 字段。

每一条验收标准必须写清楚三件事:

你要说清楚的 例子 为什么要写
在哪验(Surface) api / ui / cli / 数据层 / 业务流程 决定了用什么工具去检查
用什么验(Tool) curl / 浏览器自动化 / 命令行 防止 AI 自己编一个”我看了一下,通过了”
要什么证据(Evidence) 状态码、响应结构、截图、交互轨迹 防止假验证——截个图说”能打开”不算通过

举几个具体的证据要求:

  • API 接口:必须有请求内容、状态码、JSON 响应结构、响应内容——不是返回 200 就算过,得验 JSON 里有没有你要的字段
  • 用户界面:必须有截图、页面结构、交互轨迹——不是截个静态页面就行,得有真实的点击操作记录
  • 业务流程:必须有操作前状态、操作后状态、副作用——得证明状态确实变了

为什么要这么细?因为后面 Test 阶段,另一个 AI 会拿着这些标准一条一条去验。标准模糊,检查就是走过场。

还有一条规则:默认用真实环境验证,不用假数据。 设计文档原文:「默认用真实集成测试。mock 只能由用户主动选择退出,不能由 AI 悄悄降级。」

第二件:把大任务拆成小任务

拆完存在 features.json 里。每个小任务写清楚:

  • 要做什么
  • 前置条件是什么(哪些任务必须先完成)
  • 做完之后应该能观察到什么行为
  • 用什么命令可以验证

注意顺序:先写验收标准,再拆任务。 这是 mission 设计文档里明确规定的:

Write validation-contract.md before features.json. This is mission-level TDD.

先定义什么叫完成,再想怎么做。这和 TDD(测试驱动开发)是同一个思路,只不过尺度从函数级别放大到了整个任务级别。

Factory.ai 的文档对 Plan 阶段说得直接:「规划阶段产生的价值最大(The biggest value we have found in Missions is in the planning phase)。」规划不好,后面 AI 就是随机漫步。


Dev:派任务给 AI,它写代码交作业

Plan 完之后,进入开发阶段。mission 会按顺序把小任务一个一个派出去。

这里有个关键设计:负责分配任务的 AI 自己不写代码。

为什么?因为 AI 的”注意力”(上下文窗口)是有限的。如果负责统筹的那个 AI 自己跑去读代码、写实现,它的上下文很快被实现细节填满了,后面还有十几个任务要协调,空间就不够了。

所以 mission 把角色分成两种:

  • 项目经理(Orchestrator):统筹调度,分配任务,看交接报告,决定下一步。自己不写代码。
  • 开发人员(Worker / Subagent):每次接一个任务,干完交作业,下次再来是一个全新的 session。

每个 Worker 干完之后要写一个”交接文件”(handoff.json),记录:改了哪些文件、跑了什么测试、测试结果是什么、有没有遗留问题。项目经理读这个文件来判断进度,不需要自己去看代码。

这跟现实中的项目管理一样——项目经理把任务分配给不同的开发人员,每个人做完提交工作汇报。

Worker 的”开工仪式”

每个 Worker 开始工作之前,有一套强制步骤——必须先读这些文件:

  1. 项目目标(mission.md)
  2. 约束边界(AGENTS.md)
  3. 系统架构(architecture.md)
  4. 环境配置(environment.md)
  5. 服务清单(services.yaml)

不读就开始改代码,很容易改出和项目风格完全不同的东西。这些文件里缺了任何一个,Worker 要在交接文件里报”卡住了”(blocked),不允许跳过。

这相当于新同事入职第一天先看技术文档、了解项目规范,而不是上来就写代码。


Test:不是自己测自己,是另一个 AI 来测

这是整个设计里最重要的一个选择,也是跟人类开发流程区别最大的地方。

人可以自己写完代码自己跑测试(虽然不建议自己 review 自己的 PR,但日常开发中经常这么做)。但 AI 不行。

Anthropic 做过实验:让 AI 审查自己写的代码,结果是——

质量明显很差,但还是自信地夸自己。(confident praise even when the quality is obviously mediocre)

跟人一样,自己 review 自己的 PR,总觉得写得挺好。但 AI 的这个问题比人更严重,因为它没有那种”我是不是哪里没想到”的自觉。

所以 mission 里有一条硬规则:写代码的 AI 和测试的 AI 必须是不同的 session。 不是建议,是代码层面的强制——如果你试图手动创建验证任务,系统会拒绝。验证任务只能由系统在里程碑边界自动生成。

两种自动验证

每完成一个里程碑(一组相关的小任务),系统自动派出两个独立的验证 AI:

工程检查(scrutiny-validator)

  • 跑项目的测试套件
  • 跑类型检查
  • 跑代码规范检查
  • 逐个 feature 做代码 review
  • 综合结论写进报告文件

行为检查(user-testing-validator)

  • 拿着 Plan 阶段写的验收标准
  • 在真实环境里一条一条地验
  • API 就真的发请求,UI 就真的打开浏览器点
  • 检查证据是否达到要求(有没有交互轨迹、有没有响应结构)

这两个验证 AI 是全新的 session,不知道写代码的那个 AI 是怎么想的、怎么实现的。它们只看行为,对着验收标准打分。

这就是日常开发里的 CI + Code Review,只不过执行者从人变成了 AI。

没过怎么办?自动修,自动重测

验证没过不等于任务失败。系统会:

  1. 看哪条验收标准没过
  2. 自动生成一个针对性的修复任务
  3. 把修复任务排到队列最前面
  4. 派一个新的 Worker 去修
  5. 修完之后重新验证,只重跑之前没过的部分

这个 Dev → Test → Fix → Re-Test 的循环是自动的,不需要人来推。直到全部通过或者碰到真的解决不了的问题才停下来。


Review:什么叫真的做完了

人做项目,容易在最后一步偷懒——“差不多了吧”。AI 更容易这样。

所以 mission 设计了一个”完成门控”(Completion Gate)。不是项目经理 AI 说”完成了”就完成了,而是必须通过一组机械检查:

  1. 之前写的每一条验收标准都 passed——一条没过都不行
  2. 项目文档在这次任务期间有更新——README 或 SKILL.md 必须改过
  3. 所有验证报告格式合法——不能有格式坏掉的报告混进来
  4. 没有残留的临时代码、存根、假数据——不能有半成品留在仓库里

第 2 条很实际:如果做了一堆改动但没更新文档,下一个接手的人(或者下一次运行的 AI)就不知道系统变成什么样了。mission 会直接卡住,不让你说”完成”。

门控没过,session 退不了——hook 会拦住。这跟 CI 卡住不让你 merge 一样:流水线是红的,你就是合不了。


把四步串起来:所有状态都存文件

你可能注意到了,每一步都在产生文件:

阶段 产生的文件 干什么用的
Plan validation-contract.md 验收标准
Plan features.json 任务列表和依赖关系
Dev assignment.json 派给 Worker 的任务说明
Dev handoff.json Worker 交回的工作汇报
Test synthesis.json 验证结论
Review validation-state.json 每条验收标准的通过/失败状态

这不是为了仪式感。这是为了解决一个实际问题:AI 的对话窗口是有限的,跑久了前面的内容会被清掉。

如果任务进度只活在对话里,session 一断就什么都没了。所以 mission 的规则是:每一个重要的事实,在 AI 继续工作之前,必须先写进文件。这样不管 session 断几次,下次启动从文件就能重建出完整状态——哪些任务做完了,当前卡在哪,下一步干什么。

OpenAI 文章里的原话是:「从 Agent 的视角来看,任何不在仓库里的信息都不存在。」不是藏起来了,是字面意义上不存在。Slack 里讨论的设计决定、对话里说过的约束,如果没有写进文件,对下一个 AI 来说跟从没发生过一样。


两种保障手段:事前引导 + 事后检查

如果你只记一个概念,记这个。

mission 对 AI 的所有控制归结为两种:

事前引导——在 AI 动手之前告诉它该怎么做:

  • 架构文档(系统长什么样)
  • 约束边界(哪些东西不能碰)
  • 服务清单(怎么跑测试、怎么启动服务)
  • 任务规格(做完应该看到什么行为)

相当于新人入职的 onboarding 文档。减少犯错的概率。

事后检查——在 AI 做完之后检查做得对不对:

  • 验收标准(每一条要验的行为)
  • 自动验证器(工程检查 + 行为检查)
  • 项目自带的 lint/test/typecheck
  • 交接文件(做了什么、结果是什么)

相当于 CI 流水线 + Code Review。拦住已经犯的错。

事前引导减少出错概率,事后检查拦住出的错。两者配合就是 Harness 的核心。

每次任务发生变化,要问自己:我需要加一个事前引导,还是一个事后检查,还是两个都要?


一个反直觉的点:规则不是越多越好

mission 的设计文档里有一句话:

每一个 prompt 补丁、验证器、脚本的存在,都是因为模型在某件事上不可靠。

你加的每一条规则,背后都有一个假设:“AI 在这件事上会出错,所以我用这条规则兜底。“

但模型在进步。去年需要的护栏,今年可能多余了。设计文档建议:长任务结束后做一次简化审查——哪些验证器真的发现过问题?哪些门控从来没拦住过任何东西?能删就删。

最好的 Harness 是刚好够用的那个,不是最复杂的那个。

护栏太多,AI 反而花大量精力在满足规则上,而不是在解决问题上。跟软件工程里的过度设计一个道理。


怎么实际用起来

第一步:给项目搭骨架(每个项目做一次)

python scripts/mission_runtime.py bootstrap-repo --repo-root .

在项目里建一个 .agents/ 目录,放好架构文档、服务清单的模板。你需要把模板填成真实内容——系统怎么启动、测试怎么跑、环境变量有哪些。

第二步:创建一个 mission

python scripts/mission_runtime.py bootstrap \
    --mission-root .agents/missions/my-task \
    --goal "你要做的事情" \
    --validation-contract contract.md \
    --features features.json \
    --repo-root .

第三步:写验收标准(先于任务拆分)

validation-contract.md 里定义每一条要验证的行为,写明用什么工具验、要什么证据。

第四步:拆任务

features.json 里把大目标拆成小任务,每个写清楚行为规格和依赖关系。

第五步:跑起来

# 检查就绪
python scripts/mission_runtime.py check-readiness \
    --mission-root .agents/missions/my-task --repo-root .

# 开跑
python scripts/mission_runtime.py autopilot-loop \
    --mission-root .agents/missions/my-task --repo-root .

autopilot-loop 自动循环:选任务 → 派 AI 去做 → 收结果 → 到里程碑自动验证 → 没过就自动修 → 直到全部完成或卡住。

随时可以中断,下次继续——状态在文件里,不会丢。

第六步:确认完成

python scripts/mission_runtime.py complete-gate \
    --mission-root .agents/missions/my-task --repo-root .

什么时候用,什么时候不用

不用: 改一个 bug、重命名一个函数、修一个 typo。直接让 AI 做就行了。

可以用:

  • 任务涉及多个文件、多个模块、有依赖顺序
  • 你需要明确的”完成标准”来防止 AI 说完成但其实没完成
  • 任务可能做到一半被中断,需要下次接着做
  • 你想让不同的 AI 互相检查代码质量

一个简单的判断方法:如果这个任务最后你会说”完成了”,但你自己也不太确定是不是真的完成了——就适合用 mission,因为完成门控会替你把这个问题回答清楚。


回到本质

Harness、Mission、Orchestrator、Validator——这些词听着像新东西,但拆开看,就是软件工程里最基本的循环:

Plan:先定义什么叫完成,再拆怎么做。
Dev:按计划一个一个做,每次做完交作业。
Test:找另一个 AI 来检查,写代码的不能自己检查自己。
Review:过完成门控,所有标准 passed 才算结束。

跟人的区别只有三个:口头约定换成了文件,凭感觉换成了机械门控,自己测自己换成了强制隔离。

OpenAI 那篇 Harness Engineering 的核心经验,一百万行代码,三个工程师,说白了就一句话:

给 AI 搭好 Plan → Dev → Test → Review 的环境,比让 AI 更聪明更管用。


参考资料: