所有内容以 Anthropic 官方 Agent 设计指南、Claude Code 实际行为(
--verbose可观察)及 Claude Code 内置CLAUDE.md行为约束为依据。
一、一句话理解 Harness 工程
提示词工程管"怎么说",上下文工程管"给什么",Harness 工程管"怎么跑"。
它是套在 AI Agent 外面的那层管理框架,决定 Agent 如何被约束、如何运转、如何交付结果。
二、必要组件
组件 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 又规划又执行又评审,它会对自己的作品过度宽容。把"规划者""运动员""裁判"彻底分开。
三个 Agent 的职责边界:
| Agent | 阶段 | 核心职责 | 不做什么 |
|---|---|---|---|
| Orchestrator | Plan | 读规范、探索、拆任务、输出 plan.md | ❌ 不写业务代码 |
| Generator | Execute | 按 TODO 执行、工具调用、轻量自检 | ❌ 不评审质量 |
| Evaluator | Verify | 对照需求评审、跑 CI | ❌ 不修改代码 |
注意:Evaluator 不是必须一直存在的。任务简单时是多余的开销,超出模型能力边界时才真正有价值。模型升级后要重新判断是否还需要它。
组件 2:AGENTS.md(给 Agent 的地图)
不是手册,是索引。控制在 100-200 行,告诉 Agent 去哪找规范,而不是把所有规范都堆在里面。
markdown
# 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 应该被清空"
markdown
## 功能:用户登录
验收标准:
- [ ] 输入正确账号密码后,localStorage 中存在 auth_token
- [ ] 输入错误密码后,页面显示文字"密码错误,请重试"
- [ ] 登录成功后,URL 跳转到 /dashboard
- [ ] token 过期后访问 /dashboard,自动跳转回 /login
## 功能:删除商品
验收标准:
- [ ] 点击删除按钮,调用 DELETE /api/products/:id
- [ ] 删除成功后,列表中该商品消失
- [ ] selectedProductId 状态被清空
组件 4:Linter 架构守卫
把不能违反的架构规范写成 Linter 规则,让 Agent 读到报错就知道怎么改。
javascript
// 自定义 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 完整三阶段流转图
3.2 Plan 阶段:只读,不写业务代码
Claude Code 在 Plan 阶段的实际行为(--verbose 可观察):
markdown
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 的上下文,产物必须写入文件才能传递。
markdown
# 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 完整协作时序
3.5 上下文重置机制(长任务关键)
plan.md 进度更新格式:
markdown
# 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 无报错
四、需要做的具体工作清单
| 工作项 | 做什么 | 判断是否需要 |
|---|---|---|
| 裸跑观察 | 直接把任务给 Agent,读日志找失败点 | 永远先做这步 |
| AGENTS.md | 写 100-200 行的项目索引 | 任何项目都需要 |
| 规范文档目录 | 按需建立 /docs 下的具体规范 | 项目复杂度超过一般时 |
| 验收标准 | 把功能需求翻译成可验证的行为 | 有功能性任务时 |
| Linter 规则 | 把架构约束编码进 CI | 有反复出现的错误模式时 |
| plan.md 机制 | Orchestrator 输出计划文件 | 任务预计超过 30 分钟时 |
| 上下文重置 | plan.md 记录进度 + 新 Agent 接力 | 任务预计超过 1 小时时 |
| Evaluator Agent | 加评审层 | 任务超出单 Agent 能力边界时 |
| 三 Agent 架构 | Orchestrator + Generator + Evaluator | 任务非常复杂时才值得开销 |
五、一个完整的真实示例串联全流程
任务:给用户列表页加"按注册时间排序"功能
markdown
════════════════════════════════════════
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 的每个组件应该针对真实观察到的失败模式,而不是理论上的风险。
七、常见误区与解法
依据:Anthropic 官方指南 ------ "Mistakes in agentic contexts may be difficult to reverse, and could have downstream consequences within the same pipeline."
八、快速参考卡片
判断用哪种架构
三阶段检查清单
markdown
════════════════════════════════════
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?
文件结构参考
markdown
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/
九、全文总结
最后一句话:Harness 工程的本质不是给 Agent 加更多限制,而是给它一套可靠的运转轨道,让它在正确的时间做正确的事,出错时能被发现,能被纠正,能被接力。