所有内容以 Anthropic 官方 Agent 设计指南、Claude Code 实际行为(
--verbose可观察)及 Claude Code 内置CLAUDE.md行为约束为依据。
一、一句话理解 Harness 工程
提示词工程管"怎么说",上下文工程管"给什么",Harness 工程管"怎么跑"。
它是套在 AI Agent 外面的那层管理框架,决定 Agent 如何被约束、如何运转、如何交付结果。
graph TD
A[AI 工程体系] --> B[提示词工程\nPrompt Engineering]
A --> C[上下文工程\nContext Engineering]
A --> D[Harness 工程\nHarness Engineering]
B --> B1["关注:怎么说话\n写出好的指令让模型理解"]
C --> C1["关注:给什么信息\n管理放入窗口的内容"]
D --> D1["关注:怎么运转\n构建驱动模型的整套框架"]
style D fill:#f9a,stroke:#c66
style D1 fill:#ffd,stroke:#c66
二、必要组件
graph TD
A[Harness 工程] --> B[1 多 Agent 架构]
A --> C[2 AGENTS.md]
A --> D[3 可测试的验收标准]
A --> E[4 Linter 架构守卫]
B --> B1["Orchestrator 规划\nGenerator 执行\nEvaluator 评审\n三者职责分离"]
C --> C1["Agent 的地图\n100-200行作为索引\n指向具体规范文档"]
D --> D1["每个功能写成\n可被工具验证的行为\n而不是模糊描述"]
E --> E1["架构规范编码进 Linter\n报错信息包含修复指令\nCI 强制执行"]
组件 1:多 Agent 架构
依据:Anthropic 官方指南 —— "In agentic contexts, Claude will sometimes act as an orchestrator of multi-agent pipelines and sometimes as a subagent within those pipelines, and sometimes as both."
核心思想:让同一个 Agent 又规划又执行又评审,它会对自己的作品过度宽容。把"规划者""运动员""裁判"彻底分开。
flowchart TD
User[用户任务] --> Orch
subgraph Orchestrator Agent 编排层
Orch[接收任务]
Orch --> P1[读取 AGENTS.md]
P1 --> P2[探索代码库\n只读不写]
P2 --> P3[拆解子任务\n写入 plan.md]
P3 --> P4[识别风险点\n确定验收标准]
end
subgraph Generator Agent 执行层
P4 -->|下发 plan.md| G1[读取 plan.md]
G1 --> G2[按 TODO 执行]
G2 --> G3[Edit / Bash 工具调用]
G3 --> G4[每步轻量自检\nnpx tsc]
G4 -->|局部有误| G3
G4 -->|计划有误\n回报 Orchestrator| P3
end
subgraph Evaluator Agent 评审层
G4 -->|子任务完成| E1[读取 plan.md\n对照验收标准]
E1 --> E2[跑测试 + Linter]
E2 --> E3{是否通过?}
E3 -->|通过| Done[ PR Ready]
E3 -->|不通过 + 原因| P3
end
三个 Agent 的职责边界:
| Agent | 阶段 | 核心职责 | 不做什么 |
|---|---|---|---|
| Orchestrator | Plan | 读规范、探索、拆任务、输出 plan.md | ❌ 不写业务代码 |
| Generator | Execute | 按 TODO 执行、工具调用、轻量自检 | ❌ 不评审质量 |
| Evaluator | Verify | 对照需求评审、跑 CI | ❌ 不修改代码 |
注意:Evaluator 不是必须一直存在的。任务简单时是多余的开销,超出模型能力边界时才真正有价值。模型升级后要重新判断是否还需要它。
组件 2:AGENTS.md(给 Agent 的地图)
不是手册,是索引。控制在 100-200 行,告诉 Agent 去哪找规范,而不是把所有规范都堆在里面。
# AGENTS.md 结构示例
## 项目概览
这是一个 React + TypeScript 的电商项目
## 核心规范(按需读取)
- 组件规范 → /docs/components.md
- API 规范 → /docs/api-conventions.md
- 测试规范 → /docs/testing.md
## 架构约束(必须遵守)
- 禁止在组件内直接调用 API,必须通过 hooks 层
- 状态管理统一使用 Zustand,禁止 Redux
## 常见错误(血泪教训)
- 修改 auth 相关代码前先读 /docs/auth-flow.md
- 环境变量不要硬编码,统一在 /config/env.ts 管理
关键原则:只存在于口头、聊天记录、脑子里的决定,对 Agent 来说不存在。
组件 3:可测试的验收标准
错误示范 → "界面要好用"
正确示范 → "点击删除按钮后,selectedEntityId 应该被清空"
## 功能:用户登录
验收标准:
- [ ] 输入正确账号密码后,localStorage 中存在 auth_token
- [ ] 输入错误密码后,页面显示文字"密码错误,请重试"
- [ ] 登录成功后,URL 跳转到 /dashboard
- [ ] token 过期后访问 /dashboard,自动跳转回 /login
## 功能:删除商品
验收标准:
- [ ] 点击删除按钮,调用 DELETE /api/products/:id
- [ ] 删除成功后,列表中该商品消失
- [ ] selectedProductId 状态被清空
组件 4:Linter 架构守卫
把不能违反的架构规范写成 Linter 规则,让 Agent 读到报错就知道怎么改。
// 自定义 ESLint 规则:禁止在组件里直接 fetch
module.exports = {
rules: {
'no-fetch-in-component': {
create(context) {
return {
CallExpression(node) {
if (node.callee.name === 'fetch') {
context.report({
node,
message: `
❌ 不允许在组件中直接调用 fetch
✅ 修复方法:将请求逻辑移至 src/hooks/ 目录下
📖 参考规范:/docs/api-conventions.md#hooks-pattern
`
})
}
}
}
}
}
}
}
三、Coding 中的任务流转:Plan → Execute → Verify
依据:Anthropic 官方指南 —— "For complex tasks, invest in upfront planning. Have the model explore and understand before acting."
3.1 完整三阶段流转图
flowchart TD
Input["用户任务"] --> P1
subgraph plan["Plan 阶段"]
P1["读取 AGENTS.md + 相关规范"]
P2["探索代码库结构\n只读 不修改任何文件"]
P3["拆解子任务\n写入 plan.md"]
P4["识别风险点\n写入验收标准"]
P1 --> P2 --> P3 --> P4
end
subgraph execute["Execute 阶段"]
E1["读取 plan.md"]
E2["按 TODO 顺序执行"]
E3["Edit / Bash 工具调用"]
E4["每步轻量自检\nnpx tsc"]
E1 --> E2 --> E3 --> E4
E4 -->|"局部有误"| E3
end
subgraph verify["Verify 阶段"]
V1["层1:自动化\nnpm test + tsc + eslint"]
V2["层2:验收标准核对\n逐项检查 plan.md 中的标准"]
V3["层3:Evaluator Agent\n独立评审逻辑与架构合规"]
V4["层4:人工确认\nReview PR + 关注风险点"]
V1 --> V2 --> V3 --> V4
end
P4 --> E1
E4 -->|"计划有误"| P3
E4 -->|"所有任务完成"| V1
V4 -->|"不通过 + 原因"| P3
V4 -->|"通过"| Done["PR Ready"]
3.2 Plan 阶段:只读,不写业务代码
Claude Code 在 Plan 阶段的实际行为(--verbose 可观察):
Phase: PLAN
─────────────────────────────────────────
→ read_file: AGENTS.md ✓
→ read_file: /docs/api-conventions.md ✓
→ glob: src/**/*.ts ✓ (探索结构)
→ grep: "UserService" ✓ (找依赖)
→ read_file: src/services/user.ts ✓
输出 plan.md:
TODO:
[ ] 1. 拆分 UserService → AuthService + ProfileService
[ ] 2. 更新 src/controllers/ 下的 import(共 4 个文件)
[ ] 3. 补充 AuthService 单元测试
[ ] 4. 跑 npm test 验证无回归
⚠️ 风险点:ProfileService 依赖 legacy UserDAO,需要兼容层
─────────────────────────────────────────
Plan 阶段工作清单:
| 工作 | 工具 | 目的 |
|---|---|---|
| 读 AGENTS.md | read_file | 加载项目约束 |
| 探索目录结构 | glob / ls | 理解全局,防止遗漏 |
| 查找依赖关系 | grep | 知道改哪里会影响哪里 |
| 写 plan.md | write_file | 外置状态,供后续 Agent 读取 |
| 标注风险项 | 写入 plan.md | 让 Verify 阶段重点检查 |
3.3 Plan 产物必须外置到文件
原因:Generator 和 Evaluator 是独立的新 Agent,无法读取 Orchestrator 的上下文,产物必须写入文件才能传递。
# plan.md(Orchestrator 写,Generator 和 Evaluator 读)
## 任务目标
给用户列表页加"按注册时间排序"功能
## 代码探索结果
- 入口:src/pages/UserListPage.tsx
- Hook 层:src/hooks/useUserList.ts
- API 层:src/api/users.ts
- 约束:状态管理用 Zustand,禁止组件内直接调 API
## 执行 TODO
[ ] 1. api/users.ts 加 sortBy 参数
[ ] 2. hooks/useUserList.ts 加排序状态
[ ] 3. UserListPage.tsx 加排序按钮 UI
## 风险点(Evaluator 重点检查)
- API 是否真实支持 sortBy,需要 bash 确认
- Zustand store 命名是否符合规范
## 验收标准
- [ ] 点击排序按钮,列表顺序变化
- [ ] 不刷新页面,排序状态保持
3.4 三 Agent 完整协作时序
sequenceDiagram
participant User as 👤 用户
participant O as 🎯 Orchestrator
participant F as 📁 文件系统
participant G as ⚒️ Generator
participant E as 🔍 Evaluator
User->>O: 下达任务
Note over O: PLAN 阶段
O->>F: read AGENTS.md
O->>F: glob / grep 探索代码库
O->>F: write plan.md
O->>G: 启动,传入 plan.md 路径
Note over G: EXECUTE 阶段
G->>F: read plan.md
G->>F: Edit / write 执行变更
G->>G: npx tsc 轻量自检
G->>F: 更新 plan.md 进度
G->>E: 启动,传入 plan.md 路径
Note over E: VERIFY 阶段
E->>F: read plan.md
E->>G: bash npm test
E->>G: bash eslint
alt 验证不通过
E->>O: 返回失败原因
O->>F: 更新 plan.md
O->>G: 重新执行
else 验证通过
E->>User: ✅ PR Ready
end
3.5 上下文重置机制(长任务关键)
sequenceDiagram
participant O as Orchestrator
participant A1 as Generator 第1轮
participant F as 文件系统
participant A2 as Generator 第2轮
O->>F: 写入 plan.md(完整计划)
O->>A1: 启动,传入 plan.md
A1->>F: 执行子任务 1、2、3
A1->>F: 更新 plan.md 进度
Note over A1: ⚠️ 上下文即将满
A1->>F: 写入当前状态\n已完成:1、2、3\n下一步:4
A1-->>O: 上下文重置,需要新 Agent
O->>A2: 启动新 Agent
A2->>F: read plan.md
Note over A2: 知道了:已完成1-3\n接下来做4、5
A2->>F: 继续执行子任务 4、5
plan.md 进度更新格式:
# plan.md(执行中持续更新)
## 任务目标
重构用户模块
## 执行 TODO
[x] 1. 拆分 UserService → AuthService + ProfileService
[x] 2. 更新 src/controllers/ 下的 import 路径
[x] 3. 补充 AuthService 单元测试
[ ] 4. 补充 ProfileService 单元测试 ← 当前位置
[ ] 5. 更新 API 文档
## 遇到的问题(新 Agent 接力时必读)
- ProfileService 依赖 legacy UserDAO
- 已在 src/services/compat/user-dao-adapter.ts 建立兼容层
- 新 Agent 继续时不要删除这个文件
## 验收标准
- [ ] npm test 全部通过
- [ ] npx tsc 无报错
四、需要做的具体工作清单
graph LR
Step1["第一步\n裸跑 Agent\n观察失败点"]
--> Step2["第二步\n写 AGENTS.md\n建立基础索引"]
--> Step3["第三步\n把验收标准\n写成可测试行为"]
--> Step4["第四步\n加 Linter 规则\n守住架构边界"]
--> Step5["第五步\n视复杂度\n引入多 Agent"]
--> Step6["第六步\n模型升级后\n重新审视每个组件"]
| 工作项 | 做什么 | 判断是否需要 |
|---|---|---|
| 裸跑观察 | 直接把任务给 Agent,读日志找失败点 | 永远先做这步 |
| AGENTS.md | 写 100-200 行的项目索引 | 任何项目都需要 |
| 规范文档目录 | 按需建立 /docs 下的具体规范 | 项目复杂度超过一般时 |
| 验收标准 | 把功能需求翻译成可验证的行为 | 有功能性任务时 |
| Linter 规则 | 把架构约束编码进 CI | 有反复出现的错误模式时 |
| plan.md 机制 | Orchestrator 输出计划文件 | 任务预计超过 30 分钟时 |
| 上下文重置 | plan.md 记录进度 + 新 Agent 接力 | 任务预计超过 1 小时时 |
| Evaluator Agent | 加评审层 | 任务超出单 Agent 能力边界时 |
| 三 Agent 架构 | Orchestrator + Generator + Evaluator | 任务非常复杂时才值得开销 |
五、一个完整的真实示例串联全流程
任务:给用户列表页加"按注册时间排序"功能
════════════════════════════════════════
PLAN 阶段(Orchestrator 执行)
════════════════════════════════════════
→ read_file: AGENTS.md
发现约束:状态管理用 Zustand,禁止组件内直接调 API
→ glob: src/**/*.ts
→ grep: "UserList"
找到:
- src/pages/UserListPage.tsx ← UI 入口
- src/hooks/useUserList.ts ← Hook 层
- src/api/users.ts ← API 层
→ write_file: plan.md
内容:
TODO:
[ ] 1. api/users.ts 加 sortBy 参数
[ ] 2. hooks/useUserList.ts 加排序状态
[ ] 3. UserListPage.tsx 加排序按钮 UI
风险点:API 是否支持 sortBy,需 bash 确认
验收标准:
[ ] 点击排序按钮,列表顺序变化
[ ] 不刷新页面,排序状态保持
════════════════════════════════════════
EXECUTE 阶段(Generator 执行)
════════════════════════════════════════
→ read_file: plan.md
→ bash: curl -s /api/docs | grep sortBy
确认 API 支持 sortBy 参数 ✓
→ edit: src/api/users.ts
old: getUsers()
new: getUsers(sortBy?: 'createdAt')
→ npx tsc --noEmit ← 轻量自检
通过 ✓,更新 plan.md: [x] 1
→ edit: src/hooks/useUserList.ts
加入 sortBy 状态和传参逻辑
→ npx tsc --noEmit
通过 ✓,更新 plan.md: [x] 2
→ edit: src/pages/UserListPage.tsx
加入排序按钮,调用 hook
→ npx tsc --noEmit
通过 ✓,更新 plan.md: [x] 3
════════════════════════════════════════
VERIFY 阶段(Evaluator 执行)
════════════════════════════════════════
→ read_file: plan.md (读取验收标准)
层1 自动化验证:
→ bash: npm test
✓ 32 passed
→ bash: npx eslint src/
✓ 无报错(Linter 守卫通过)
层2 验收标准核对:
→ 点击排序按钮列表顺序变化?
read_file: UserListPage.tsx
确认 onClick 正确绑定 ✓
→ 不刷新页面排序状态保持?
read_file: useUserList.ts
确认状态存入 Zustand store ✓
层3 架构合规:
→ 组件内是否有直接 fetch 调用?
grep: "fetch" src/pages/UserListPage.tsx
无结果 ✓(符合 Linter 规则)
结论:全部通过 → ✅ PR Ready
六、最重要的一条原则
依据:Anthropic 官方指南 —— "Invest in the right amount of scaffolding. More structure is not always better."
先跑裸 Agent,再决定加什么。
Harness 的每个组件应该针对真实观察到的失败模式,而不是理论上的风险。
graph LR
A["🟢 裸跑\n观察失败"] -->|发现问题再加| B["🟡 最小 Harness\nAGENTS.md + 验收标准"]
B -->|发现问题再加| C["🔴 完整 Harness\n多 Agent + Linter + plan.md"]
A -. 不要跳过 .-> C
七、常见误区与解法
依据:Anthropic 官方指南 —— "Mistakes in agentic contexts may be difficult to reverse, and could have downstream consequences within the same pipeline."
graph TD
subgraph 常见误区
M1[Plan 和 Execute 混在一起\n边想边改]
M2[验收标准写得模糊\n无法被工具验证]
M3[plan.md 只存在于上下文\n没有写入文件]
M4[Evaluator 和 Generator\n用同一个 Agent]
M5[一上来就搭三 Agent 架构\n任务其实很简单]
end
subgraph 正确做法
S1[Plan 阶段严格只读\nExecute 阶段才动文件]
S2[验收标准写成\n工具可执行的检查项]
S3[所有状态外置到文件\n新 Agent 能独立接力]
S4[两个独立 Agent\n职责完全分离]
S5[先裸跑\n发现真实失败点再加组件]
end
M1 --> S1
M2 --> S2
M3 --> S3
M4 --> S4
M5 --> S5
八、快速参考卡片
判断用哪种架构
flowchart TD
Start[新任务来了] --> Q1{任务能在\n10分钟内完成?}
Q1 -->|是| A1[ 单 Agent 裸跑\n无需 Harness]
Q1 -->|否| Q2{任务有明确的\n可验证验收标准?}
Q2 -->|否| A2[先把验收标准\n写清楚再开始]
Q2 -->|是| Q3{预计超过\n30 分钟?}
Q3 -->|否| A3[ 单 Agent\n+ AGENTS.md\n+ 验收标准]
Q3 -->|是| Q4{预计超过\n1 小时?}
Q4 -->|否| A4[ 单 Agent\n+ plan.md\n+ 上下文重置机制]
Q4 -->|是| Q5{任务超出\n单 Agent 能力?}
Q5 -->|否| A5[ 单 Agent\n+ plan.md 接力]
Q5 -->|是| A6[ 三 Agent 架构\nOrchestrator\n+ Generator\n+ Evaluator]
三阶段检查清单
════════════════════════════════════
PLAN 阶段 检查清单
════════════════════════════════════
□ 读取了 AGENTS.md?
□ 用 glob/grep 探索了代码库?
□ TODO 列表写入了 plan.md?
□ 风险点标注了?
□ 验收标准写成了可验证的行为?
□ 本阶段没有修改任何业务文件?
════════════════════════════════════
EXECUTE 阶段 检查清单
════════════════════════════════════
□ 读取了 plan.md?
□ 按 TODO 顺序执行,没有跳步?
□ 优先用 Edit 而非整文件 Write?
□ 每个子任务后跑了 npx tsc?
□ plan.md 进度实时更新了?
□ 发现计划有误时回到 Plan 重规划?
════════════════════════════════════
VERIFY 阶段 检查清单
════════════════════════════════════
□ 层1:npm test 全部通过?
□ 层1:npx tsc 无报错?
□ 层1:eslint 无报错?
□ 层2:plan.md 验收标准逐项核对?
□ 层3:Evaluator 独立评审通过?
□ 层4:风险点已告知人工 Review?
文件结构参考
project/
├── AGENTS.md ← Agent 的地图(100-200行)
├── docs/
│ ├── components.md ← 组件规范(AGENTS.md 指向)
│ ├── api-conventions.md ← API 规范(AGENTS.md 指向)
│ └── testing.md ← 测试规范(AGENTS.md 指向)
├── .eslintrc.js ← 含自定义架构守卫规则
├── plan.md ← 当前任务计划(任务结束后删除)
└── src/
九、全文总结
graph TD
A[Harness 工程] --> B[四个组件]
A --> C[三个阶段]
A --> D[一条原则]
B --> B1[多 Agent 架构\nOrchestrator+Generator+Evaluator]
B --> B2[AGENTS.md\n项目地图索引]
B --> B3[可测试验收标准\n行为可被工具验证]
B --> B4[Linter 架构守卫\n错误信息含修复指令]
C --> C1[Plan\n只读探索 输出plan.md]
C --> C2[Execute\n按TODO执行 实时更新进度]
C --> C3[Verify\n四层验证 不通过回到Plan]
D --> D1[先裸跑观察真实失败点\n再决定加哪个组件\n不要过度设计]
style D fill:#ffd,stroke:#c66
style D1 fill:#ffd,stroke:#c66
最后一句话:Harness 工程的本质不是给 Agent 加更多限制,而是给它一套可靠的运转轨道,让它在正确的时间做正确的事,出错时能被发现,能被纠正,能被接力。