Harness Engineering:让 Agent 不再散架
来源:受 rari(@0xwhrrari)的 X 长文 Harness Engineering: How to Build AI Agents That Don’t Fall Apart 启发,结合本站知识图谱与吴恩达 2026 年关于 agentic loop 的几封 The Batch 来信重新组织。不是逐句翻译,观点归属在文中逐一标注。
一句话结论
Agent 反复失败时,先别改 prompt 里的形容词,先看模型周围那套系统。
模型负责推理和提议下一步;Harness 负责决定模型看到什么、能碰什么、什么能跨会话留下来、什么算证据、什么时候必须停。
MODEL 推理,提议动作
HARNESS 选上下文 · 暴露工具 · 存状态 · 管权限 · 验结果 · 留痕迹 · 做恢复同一个模型,放进聊天框只会答题;放进一个有终端、测试、浏览器、项目记忆、隔离 worktree 和评审回路的仓库里,就能交付软件。权重没变,变的是 harness。
1. 在本站知识图谱里的位置
本站 Loop Engineering 一文把 AI 编程分成 Prompt / Context / Harness / Loop 四层。rari 原文最后多给了一层 Graph。合起来是一条逐层外扩的线:
| 层 | 管什么 | 本站对应文章 |
|---|---|---|
| Prompt | 一条指令怎么写 | 提示词工程框架 |
| Context | 模型此刻看见什么 | MCP 心智模型、深入理解 LlamaIndex |
| Harness | 模型在什么世界里行动 | 本文 |
| Loop | 单个任务怎么自我迭代到完成 | Loop Engineering、用测试约束 AI |
| Graph | 多个 loop、多个 agent、多个人怎么协作 | 见第 6 节 |
还有两篇容易混淆的:
- AI Eval Harness 里的 harness 是评测台架:固定输入、跑任务、打分,用来比较 prompt 和模型。
- 本文的 harness 是运行时台架:agent 真正干活的那套环境。两者共享同一批零件(任务契约、验证器、trace),eval harness 可以看作运行时 harness 的离线回放版。
- 为什么说大部分 Skill 都是没用的垃圾 的结论——“不能验证行为改变的 skill 就是垃圾”——正是 harness 思维在 skill 上的应用。
2. 为什么是环境问题,不是智力问题
rari 引了两个一手来源:
- OpenAI 在用 Codex 搭建 agent-first 代码库时发现,早期进展慢是因为环境描述不足,不是模型能力不够。他们的对策不是让 agent “更努力”,而是追问缺了什么能力,再把这个能力做得既可读又可强制。
- Anthropic 在长时运行 agent 的工作里得出类似结论:用结构化产物跨会话保持连续性,再用一个独立的评估者给构建者具体反馈,而不是让它自己批准自己。
吴恩达在 2026 年 7 月的来信 Make All Your Tokens (and Your Brainwork) Count 里从另一个角度说了同一件事:机器 token 便宜,人的注意力才是稀缺资源。Agent 忘了人说过的决定、让人重复一遍,浪费的是最贵的那种 token;所以要让 agent 把关键决定和停止条件写进 SPEC.md、写进测试。这其实就是在要求 harness 负责记忆。
3. Harness 的七项职责
3.1 先把请求变成契约
动手之前,把一句模糊的需求变成有边界的对象:目标、输入、产出、约束、完成条件。
goal: 给订单列表加导出功能
output: 可评审的 PR
constraints: [不改表结构, 不破坏公开 API]
done_when: [单测通过, 截图核对通过, 评审通过]没有契约,agent 可以悄悄换掉任务定义,做完另一件事然后宣布成功。
3.2 给地图,不给百科
根目录的 AGENTS.md 只做索引:架构在哪、测试怎么跑、业务规则和安全规则去哪查。细节放在它所约束的代码、工具、流程旁边,任务需要时再加载。地图省上下文,巨型手册吃上下文。
3.3 工具要有契约和边界
工具不是一排按钮,是模型和真实世界之间的接口。每个工具都要有清楚的用途、可预期的输出、明确的失败状态和权限边界。默认可读;沙箱内可跑测试、可写工作区;网络按任务开放;部署和删数据必须审批。好工具在模型推理出错之前就消除了歧义。
3.4 记忆外置成持久状态
对话不是系统的档案。决定、产物、失败、未决风险都存在上下文窗口之外。下一个会话继承的是工作状态,而不是一段有损的聊天复述——这样 agent 才扛得住上下文重置、崩溃和交接。本站 Agent Session 和第三方消息平台 讨论的 session 分层,就是这件事在平台架构上的样子。
3.5 先装传感器,再给自主权
Agent 看不见的东西就改不了。测试、类型检查、lint、截图、日志、schema 校验,把“质量好不好”变成证据:
代码 → 测试 + 类型 + lint
UI → 渲染 + 截图 + 目检
调研 → 来源核对 + 矛盾检查
数据 → schema + 取值范围 + 新鲜度模型产出物,环境产出证据,harness 判断证据够不够继续。
3.6 权限在模型之外执行
模型只能建议,harness 负责授权:模型提议 → 策略检查 → 工具执行。动作越贵、越不可逆、越涉及他人,越不能让同一个概率系统既定计划、又批风险、又执行副作用。这和支付系统里“发起、审批、记账”三权分离是同一个道理(参见 支付账务架构)。
3.7 留痕,局部恢复
每次运行留下可读的轨迹:请求、选用的上下文、工具调用、状态变化、验证结果、重试、成本、最终产物、回滚点。没有 trace,失败是谜;有 trace,失败是下一次改进 harness 的输入。
4. 把指令变成基础设施
大部分团队把重要规则写成散文,agent 读了,然后迟早会漏掉一条。更稳的做法是每条关键规则写两遍:
- 一遍是给 agent 读的说明,讲清原因,比如“UI 层不能直接查库”;
- 一遍是它绕不过去的机械检查,比如 UI 引用 repository 层时 lint 直接失败。
说明负责解释,检查负责强制。一次事故就此变成永久的系统改进,下一个 agent 不需要记得那次事故,harness 替它记着。
失败也按同样思路修类,不修例:
| 失败现象 | Harness 改动 |
|---|---|
| 缺上下文 | 补地图或检索规则 |
| 用错工具 | 改工具描述或路由 |
| 输出不合格 | 加校验器或收紧契约 |
| 原地打转 | 加重试上限和升级路径 |
| 危险动作 | 加权限闸门 |
| 决定丢了 | 写进持久状态 |
| 不明失败 | 加 trace 和证据采集 |
修这一次输出只救一次运行;改 harness 改善之后每一次运行。这是复利。
5. Loop 归 harness 管
“一直试到成功为止”不是控制系统。有用的循环要有证据、有上限、有预算、有升级路径:
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
const artifact = await build(state)
const evidence = await verify(artifact)
if (evidence.pass) return artifact
state.failures.push(evidence.gap)
}
return escalateToHuman(state)分工很清楚:模型决定怎么修眼前的缺口,harness 决定还允不允许再试一次。
6. 从 Loop 到 Graph:吴恩达的三层回路
rari 在结尾把 Graph 定义为“协调层”。网上流传着不少“吴恩达 Graph Engineering 手册”,但我们没能在 The Batch 或 DeepLearning.AI 找到对应的原文,这里不引用。能核实的是他 2026 年 6 月的来信 Three Key Loops for Building Great Software,它恰好给出了 Graph 层最朴素的样子——不同时间尺度的回路嵌套在一起:
外部反馈回路 小时~天 真实用户、内测、上线数据 → 修正产品愿景
└ 开发者回路 分钟~小时 人看产品、定优先级、调方向 → 改 spec
└ Agent 编码回路 分钟 写代码、跑测试、迭代到满足条件他的几个判断和 harness 视角正好互补:
- Agent 回路已经能自测,人不必再做 QA。前提是 harness 给了它测试、eval 数据和停止条件——也就是第 3.5 节的传感器和第 5 节的有界循环。
- 开发者回路里,人的价值是“上下文优势”:比 AI 更了解用户和业务约束。Harness 要做的,是把这些人类判断沉淀进 spec、测试和状态文件,而不是每次靠人重复口述。
- 外部回路回来的信息最终要流回 spec 和 agent 指令。这条回流边如果不存在,内层回路跑得再快也只是在原地打磨错误的东西。
所以在本站的分层里:
- Loop 是一个节点内部的有界迭代;
- Graph 是多个回路之间的边——谁的输出成为谁的输入、哪条边需要人审批、哪里并行、哪里汇合;
- Harness 是让每个节点可观察、每条边可追溯的那层基础设施。没有 harness,graph 只是一张画在白板上的流程图。
7. 脑、手、历史分开
一个可靠的 agent 由三部分组成,最好彼此独立:
- 脑:负责推理的模型;
- 手:负责执行的沙箱和工具;
- 历史:只追加的运行记录。
沙箱挂了,历史还在;换了模型,工具和策略依然可审计;任务恢复时,新会话能从产物和 trace 重建状态。Anthropic 的 Managed Agents 用 session / harness / sandbox 三分把这件事做成了产品,但重点不在厂商,在架构:推理引擎不该同时兼任文件系统、权限系统、记忆库和审计日志。本站 浏览器 Agent 和 Cloudflare Workers / Containers 两篇里的隔离执行,属于“手”这一侧。
每次运行结束,除了最终产物,再留一张变更回执:用了哪些上下文来源、哪个策略版本、走的模型路由、调用的工具、测试结果、人工修正次数、重试次数、花费、被接受的产物、回滚点。有了它,模型升级可以横向比较,回归可以归因,审计有据可查,最终答案也藏不住一个坏掉的过程。
8. 从最小 harness 开始
Harness engineering 不是先建平台再干活。先搭能“观察、验证、恢复”的最小系统,任务值得了再升级:
| 级别 | 组成 | 适用 |
|---|---|---|
| L0 | prompt + 模型 | 一次性问答 |
| L1 | 项目指南 + 工具 | 短小、低风险的改动 |
| L2 | 结构化状态 + 测试 + 有界循环 | 多步、需要验证的任务 |
| L3 | 权限 + trace + 恢复 + 人工闸门 | 能改文件、联网、开 PR 的长时任务 |
原则:harness 应该比它要控制的失败面更小。
9. 上线前检查清单
把真实工作交给 agent 之前,逐项问:
- 执行前是否定义了成功标准?
- Agent 能否不加载全部文档就找到需要的项目知识?
- 每个工具是否有清晰契约和失败状态?
- 执行环境是否与生产隔离?
- 重要决定是否存在对话之外?
- 每个有风险的状态转换是否有证据?
- 不可逆动作是否有审批?
- 每个循环是否有重试上限和预算?
- 中断后能否恢复?
- 每次工具调用和状态变化能否解释?
- 失败是否会更新指南、测试、工具或策略?
- 最终产物能否回滚?
如果好几项答“否”,换更强的模型也不会让系统可靠,只会让失败更贵。
最终总结
Prompt → 指令
Context → 视野
Harness → 操作系统
Loop → 局部改进
Graph → 协调模型下个月可能就换了;工具、测试、状态、策略和 trace 却可以持续变好。持久的优势正在从 prompt 里搬出来,搬进模型周围的系统。该问的不只是“哪个模型最聪明”,而是“哪个环境能让这份聪明变得可靠”。
参考
- rari,Harness Engineering: How to Build AI Agents That Don’t Fall Apart(X Article)
- OpenAI,Harness engineering: leveraging Codex in an agent-first world
- Anthropic,Harness design for long-running application development
- 吴恩达,Three Key Loops for Building Great Software(The Batch,2026-06-26)
- 吴恩达,Make All Your Tokens (and Your Brainwork) Count(The Batch,2026-07-10)