Harness 工程
再强的模型,没有合适的工作环境,在真实工程任务上也会失败。问题不在模型,在环境。
Harness Engineering 是围绕模型构建完整工作环境的工程实践——让 AI 编码智能体在长周期、复杂任务上稳定产出可运行、可验证、可维护的结果。
The model is smart. The harness makes it reliable.
核心命题
AI 编码智能体的失败模式高度集中——而且几乎都不是模型问题:
- 任务完成率低:智能体跳过步骤、破坏测试、声称完成但实际不工作
- 上下文丢失:多会话之间无记忆,每个新会话从零开始
- 过早宣布胜利:写完代码,单元测试全绿,但集成测试没跑、端到端流程没演练
- 过度扩展:让智能体"加用户认证",它会顺手改错误处理、改目录结构、引新依赖
- 不可维护性:临时调试文件没删、测试是红的、构建失败,下个会话花 30 分钟"搞清楚上次到底干什么了"
同一款顶级模型,无 harness 跑出来的产品不工作;配齐 harness 后产出可运行游戏。模型没变,环境变了。
五个子系统
Harness 由五个相互配合的子系统组成。每个子系统解决一组特定的失败模式。
Instructions(指令)
解决:上下文丢失——智能体不靠"读心"理解项目,只能读你给它的文件。
AGENTS.md放在仓库根目录,50-200 行,是 router 不是 encyclopedia——告诉智能体"项目是什么 / 怎么跑 / 硬约束是什么",并指向专题文档- 超过 200 行的内容拆到
docs/目录,按需加载 - 硬约束单独列在入口文件首部——LLM 对长文本中间的内容利用率显著低于首尾,重要规则不能埋在中间
- 每条规则注明来源、适用条件、过期条件,定期审计删除过时约束
反面:把 600 行规则塞进一个 AGENTS.md,安全约束埋在第 300 行被忽略,三条互相矛盾的代码风格规则让智能体随机挑一条执行。
Tools(工具)
解决:工具被过度限制导致智能体什么都干不了。
- 原则:最小权限,但不是零权限。不要为了"安全"把 shell 关掉——智能体连
pip install都跑不了,怎么工作 - 工具配置记录在入口文件:"环境用 npm 而非 yarn"、"用 Makefile 而非 npx 直调"
- 工具版本固定,让智能体在哪个机器上跑都有相同环境
Environment(环境)
解决:环境不一致是隐性 bug 的最大来源——测试环境里写好代码,到生产环境跑不起来。
pyproject.toml/package.json锁依赖.nvmrc/.python-version指定运行时版本- Docker / devcontainer 让环境完全可复现
State(状态)
解决:长任务一定跨多个会话,跨会话无记忆 = 每次都从零开始。
PROGRESS.md:已完成 / 进行中 / 下一步 / 已知阻塞DECISIONS.md:重要设计决策的"为什么",避免下次重做决策- 每个逻辑操作 = 一次 git commit,失败用
git stash回滚(Atomicity) - 操作后跑验证,确保系统处于可验证状态(Consistency)
- 多智能体并发时用独立 progress 文件或 git branch 隔离(Isolation)
- 关键知识必须落盘到 git 跟踪的文件,只存在脑子里不算(Durability)
Feedback(反馈)
解决:置信度偏差是客观存在——LLM 系统性地比实际能力更自信,智能体说"完成了"不能算数。
- 列出三层验证命令——语法/静态分析、运行时行为、端到端系统级,缺一不可
- 错误消息告诉智能体怎么修:不要说"Test failed",说"POST /api/reset-password returned 500. Check that the email service config exists in environment variables."
这是回报最高的子系统——投入最低、效果最显著。
核心文件
| 文件 | 用途 |
|---|---|
| AGENTS.md / CLAUDE.md | 入口文件,承载 Instructions 子系统的核心指令 + 路由到专题文档 |
| feature_list.json | 机器可读的功能列表:每个条目是 (行为描述, 验证命令, 当前状态) 三元组 |
| init.sh | 初始化脚本:环境安装、依赖验证、健康检查 |
| PROGRESS.md | 跨会话进度持久化 |
| DECISIONS.md | 重要设计决策的"为什么" |
| docs/ | 专题文档目录,按需加载 |
| git log | 变更记录 + 回滚点 |
七个核心架构模式
WIP=1
一次只做一件事,做完端到端验证再开下一个。
智能体天然倾向多任务,"也顺便修一下"对模型零成本但对注意力是真实稀释。Little's Law:WIP 越大、Lead Time 越长、完成率越低。
例子:让智能体"加用户注册"。WIP=1 时它只做用户注册,做完跑端到端测试 100% 通过。无约束时它顺手改邮件服务、bcrypt、错误处理——6 步后每个都半成,没有端到端能跑通的。
数据:8 个功能的 REST API 项目,无约束模式 3 个会话后 5/8 完成(37.5%);WIP=1 模式 4 个会话后 7/8 完成(87.5%)。代码总量反而更少(800 行 vs 1200 行)。
Worker vs Checker 分离
生成者不自评,由独立的"挑剔"评估者打分。
LLM 系统性地比实际能力更自信——同一个模型既生成又评估,会对自己慷慨。
例子:给 app 加暗色模式,三智能体架构(planner + generator + evaluator)用 Playwright MCP 真实点击测试。evaluator 给出"按钮对比度 2.1:1 不达 WCAG AA 4.5:1 标准"——这种具体可执行的反馈,单智能体永远给不出。
数据:单智能体 $9/20 分钟产出不工作;三智能体 $200/6 小时产出可运行游戏。多花 20 倍钱、多花 18 倍时间,结果从"不可用"变"可交付"。
Feature List as Primitive
功能列表是给调度器/验证器/交接报告用的数据结构,不是给人看的备忘。
调度器要读它挑下一个任务、验证器要读它跑对应的验证命令、交接报告要读它生成状态摘要——三个组件都依赖同一个真相源。
每个条目是三元组(行为描述, 验证命令, 当前状态)。状态由 harness 控制迁移——智能体不能自说自话标"完成",只有验证命令跑过才能从 active 升到 passing。
3-Layer Termination
验证分三层,缺一不可:
| 层次 | 检查什么 | 例子 |
|---|---|---|
| 1. 语法/静态分析 | 代码写对没 | mypy --strict、ruff check |
| 2. 运行时行为 | 能跑没 | pytest tests/、应用启动 + 关键路径执行 |
| 3. 端到端系统级 | 真的对没 | 完整用户流程演练、集成测试 |
层与层之间不能跳过。单元测试系统性地漏掉组件边界缺陷——接口不匹配、状态传播错误、资源生命周期问题——这些只有端到端测试能发现。
例子:在 Electron app 加文件导出功能。单元测试全过,但点导出按钮时文件路径格式错、进度条不响应、大文件内存泄漏。5 个跨组件缺陷,单元测试一个都没抓到,端到端测试全抓到了。
Review Feedback Promotion
每次重复出现的 code review 评论 → 转成可执行检查。
人工 review 的反馈只在当下有效。如果同一类问题反复出现,每次都要人工重复——harness 应该把这些反馈沉淀下来。
例子:"renderer 不能直接 import fs"在多个项目里反复出现。转成可执行检查:
grep -r "require('fs')" src/renderer/ && exit 1 || echo "OK"
错误消息写具体修复步骤,让智能体能自纠正,不用人工每次提醒。
Sprint Contract
编码前先签"这次做啥 + 验收标准 + 不做什么"三件套。
少了这步,生成者按自己理解实现,评估者按自己理解打分,理解偏差导致大量返工。
# Sprint Contract: 暗色模式支持
## Scope
- 修改主题切换组件
- 更新全局 CSS 变量
- 添加暗色模式测试
## 验收标准
- 每个组件的视觉回归测试通过
- 主流程端到端测试通过
- 无 FOUC
## 排除项
- 不处理 print 样式
- 不处理第三方组件的暗色模式
数据:用 sprint contract 跑同一任务,评估者"感觉不对"的情况大幅减少,迭代次数从 3-4 次降到 1 次,整体时间从 45 分钟降到 15 分钟。
Clean State 5 条件
会话结束前必须留干净状态——5 项缺一不算完成:
- 构建通过(
npm run build) - 测试通过(
npm test) - Feature list 已更新
- 无调试代码残留(console.log、debugger、TODO)
- 标准启动路径可用(
npm run dev)
"清晚再清"等于从不清理,熵增是默认状态。Harness 本身也要定期简化——曾经的必要约束可以随模型升级变成不必要的负担。
数据:12 周对比,无清理策略的项目 build 通过率从 100% 掉到 68%,新会话启动时间从 5 分钟涨到 60+ 分钟;有清理策略的同期 build 通过率 97%、启动时间 9 分钟。
与 Prompt Engineering 的差异
| 维度 | 传统 Prompt Engineering | Harness Engineering |
|---|---|---|
| 焦点 | 优化提示词内容 | 构建系统环境 |
| 持久性 | 每次会话独立,无状态 | 状态持久化到磁盘 |
| 范围控制 | 无内置机制 | 通过 feature_list.json 机器可读约束 |
| 验证 | 依赖智能体主观判断 | 强制测试套件通过才算完成 |
| 会话衔接 | 每次"全新开始" | 通过 progress 文件连续交接 |
| 失败处理 | 人工清理 | 自动化 clean-state 流程 |
与本站其他内容的关系
- ReAct 模式、Plan-and-Execute 模式:讲智能体怎么"想"——决策模式
- Agent 实践:讲智能体技术栈的整体演进和模式选择
- Harness 工程(本页):讲智能体在什么"环境"里跑
类比建筑:ReAct / Plan-and-Execute 是建筑设计,Harness 是施工现场的脚手架、供电、给排水——没有这些,再漂亮的图纸也变不成可入住的房子。