返回文章列表

Harness Engineering:决定 Agent 成败的,是模型之外的那圈工程

June 05, 2026

Harness Engineering:决定 Agent 成败的,是模型之外的那圈工程

模型越来越聪明,为什么 Agent 还是动不动就翻车?答案不在模型里,而在模型外面那一圈工程系统——harness。本文从概念讲到实战,附带可直接照抄的检查清单。


一、先看一个反直觉的事实

同一个 Claude / Codex 模型,同一道任务,换两套"外壳",成功率能从 20% 跳到接近 100%——模型一个字没改。

这是 learn-harness-engineering 课程(见底部参考文档)里反复出现的实测结论:一个 TypeScript/React 项目,只给模型一个 README 时成功率约 20%;把"规则、状态、验证"这套外壳补齐后,成功率逼近 100%。没有换模型,只换了 harness。

OpenAI 的案例更极端(2026 年 2 月,Ryan Lopopolo):一支小队从 2025 年 8 月底的空仓库起步,约五个月里 0 行人工代码,每一行都由 Codex 生成,最终产出约 100 万行代码(含应用逻辑、基础设施、工具链与文档)、1500 个合并的 PR,团队从 3 人涨到 7 人、人均吞吐反而上升到 每人每天 3.5 个 PR。这群人几乎没碰业务代码,他们在干一件事——设计让模型可靠产出代码的环境。据他们估算,整体只花了手写代码约 1/10 的时间。

这件事现在有了名字:Harness Engineering(脚手架工程 / 框架工程)

一句话定义:

Agent = Model + Harness。 模型负责"聪明",harness 负责"可靠"。


二、什么是 Harness?

最常见的误解:以为 harness 就是一个写得好的 system prompt,或者一个 CLAUDE.md 文件。错。

各家给的定义高度一致,核心都是同一句话:

Harness = 模型权重之外,所有决定"智能能落地多少"的工程基础设施。 (LangChain 的说法:"every piece of code, configuration, and execution logic that isn't the model itself.")

它包括但远不止 prompt:工具的定义与执行、文件系统与沙箱、状态持久化、验证机制、上下文管理、子智能体编排、确定性的钩子/中间件(compaction、续跑、lint 拦截等不靠模型自觉、由代码强制执行的环节)、可观测性……

打个最贴切的比方:

把 Agent 当成一个今天入职的资深工程师。 他很聪明,但对你的代码库一无所知。他需要:项目文档、跑得起来的环境、能用的工具、知道"完成"的标准、以及交班记录。 这些东西的总和,就是 harness。你给的脚手架越完整,这个"新人"发挥出的能力就越接近他的真实水平。

关键洞察:今天 Agent 失败,多数不是"不够聪明",而是"看不到 / 跑不动 / 不知道何时算完"——这些全是 harness 问题,不是模型问题。 这就是所谓的 capability–execution gap(能力与执行的鸿沟)


三、Harness 的五个子系统

把一个完整的 harness 拆开,可以收敛成五个子系统。下面这套五分法综合自三处:WalkingLabs 的 learn-harness-engineering 课程、LangChain 的组件全景、以及 Anthropic 的长任务实践。建议按下面这张表逐项自查:

一点说明(各家划分并不完全一致)learn-harness-engineering 课程原本的五件套是 Instructions / State / Verification / Scope / Session Lifecycle——把"会话生命周期"单列为一项。本文改用更贴近 LangChain/Anthropic 的切法:把"工具与环境"(两家都重点强调,且最直接决定 Agent 能否跑得起来)提为核心一项,而把"会话生命周期"并入第四节的长任务方法(初始化/执行分离、干净重启)。子系统怎么命名、归到几项都不重要,别漏项才重要。

                ┌─ Instructions  指令:项目是什么、约束是什么
                ├─ Tools/Env     工具与环境:能做什么、跑得起来
   Harness ─────┼─ State         状态:上次进行到哪了
                ├─ Scope         边界:这次只做一件事,做到什么算完
                └─ Verification  验证:怎么自证做对了
子系统 解决的问题 典型载体 投入产出比
Instructions(指令) Agent 不知道项目背景与红线 AGENTS.md / CLAUDE.md,约 100 行
Tools / Environment(工具与环境) 能力够不够、环境跑不跑得起来 工具集、pyproject.toml/package.json.nvmrc、Docker/devcontainer
State(状态) 跨会话失忆,重复劳动 PROGRESS.md / claude-progress.txt、git 提交历史 中高
Scope(边界) Agent 一次想干太多,半途而废 机器可读的 feature list(JSON) 中高
Verification(验证) 自我感觉良好,假装做完了 测试、lint、type-check、E2E 最高

下面逐个拆。

1. Instructions:把"新人须知"写进仓库

原则不是"写得越多越好",而是 progressive disclosure(渐进式披露):一个 100 行左右的核心指令文件,说清楚项目是什么、技术栈、首次运行命令、不可违反的约束、文档入口。细节按需链接出去,而不是一次性糊一篇百科全书给模型——后者只会稀释注意力。

核心铁律:仓库即唯一事实来源(repo as the system of record)。 Agent 不能像人一样转头问同事,凡是它需要的东西,必须在仓库里看得到。

2. Tools / Environment:少给约束,多给能力

  • 工具权限遵循 最小权限,而不是一律禁掉——限制过严,Agent 就只能靠猜测。
  • 环境要自描述、可复现:依赖文件、运行时版本、容器配置都齐了,Agent 才能一键起服务。Anthropic 的实践里专门有个 init.sh 负责拉起开发环境。
  • 一个被低估的能力:给 Agent 一个能跑 bash / 执行代码的沙箱。比起预置一堆窄工具,"能自己写代码并运行"才是通用自治的关键——它能自己验证、自己排错。

3. State:像倒班工人一样交接

长任务跨越多个上下文窗口,每个新会话都是一张白纸。Anthropic 把这比作"轮班的工程师之间没有交接文档"。

解法是把状态落盘:

  • 进度文件(claude-progress.txt / PROGRESS.md)记录:做完了什么、正在做什么、卡在哪。
  • git 提交和提交信息留下可追溯的痕迹。
  • 每个会话开始先读进度和 git log,结束前更新进度

效果:有 harness 时,Agent 能精确地"从上次断点接着干";没有时,它要么重做,要么每次从头开始。

4. Scope:一次只做一件事

Agent 的通病是贪多——一次想实现过多功能,结果哪个都没做完。

Anthropic 的做法很直接:把任务拆成 200+ 条颗粒度极细的 feature list,每条标注 pass/fail,用 JSON 而不是 Markdown(JSON 结构化,模型更不容易擅自改写)。每个会话只做一个 feature,做完、测过、提交、更新进度,再进下一个。

5. Verification:把"好不好"变成"过没过"

这是投入最低、回报最高的子系统,也是最容易被忽略的。

模型有两个致命倾向:

  1. 过早宣布胜利——没测就说"做完了"。
  2. 自我表扬——让它评价自己的产出,它几乎总说"很棒",哪怕在人看来一塌糊涂。

对策:

  • 在文档里显式列出验证命令(test / lint / typecheck),让 Agent 每次都能跑。
  • 对 Web 应用,要求用浏览器自动化(如 Puppeteer MCP)做端到端验证,而不是"看起来对就行"。Anthropic 实测这一条让"功能真的可用"的准确率大幅提升。
  • 把主观质量变成可打分的客观标准。Anthropic 做前端时,把"好不好看"这种主观判断拆成四个可评维度:design quality、originality、craft、functionality,再用 few-shot 例子校准评审者。

四、长任务的进阶方法

短任务把上面五件事做好就够了。但当任务要跑几个小时、跨几十个上下文窗口时,还需要三个进阶模式。

1. 初始化 Agent 与执行 Agent 分离

Anthropic 的长任务 harness 是双角色架构:

  • Initializer Agent(初始化):第一个会话搭地基——写 init.sh、建进度文件、做首次 git 提交、生成那份 200+ 条的 feature list。
  • Coding Agent(执行):后续每个会话遵循固定流程——读进度 → 先跑 E2E 冒烟测试 → 完成一个 feature → 提交 → 更新进度,离场时必须留下可合并的干净状态

2. 生成与评估分离(Generator / Evaluator)

不要让同一个 Agent 既当运动员又当裁判。独立的生成者和评估者能破解"自我表扬"。评估者只在任务超出"单个模型独自能可靠完成"的范围时才值得加——任务很简单时,这套开销反而是浪费。

Anthropic 的经典对照实验:一句话 prompt 让做个复古游戏。

  • 单个 Agent 独自跑(solo run):$9、20 分钟,产出一个跑不起来的应用。
  • 三 Agent harness(规划+生成+评估):$200、6 小时,产出一个能玩、UI 精致的游戏。

质量差距撑得起这笔投入——前提是任务确实难。

3. 上下文重置 优于 上下文压缩

当模型感到"token 快用完了"会出现 context anxiety(上下文焦虑)——提前匆忙收尾。直觉做法是把历史**压缩(compaction)**塞进新窗口;但 Anthropic 发现,直接清空上下文、配合结构化的交接产物(progress 文件 + feature list)重新开始,效果反而更好。这也呼应 LangChain 说的 "Ralph Loop":在干净的新窗口里重新注入 prompt,对抗 context rot(上下文腐烂)


五、案例深读:OpenAI 的 100 万行代码是怎么撑住的

OpenAI 这篇《Harness Engineering: Leveraging Codex in an Agent-First World》是目前最翔实的实战记录。把它拆开看,几乎每条经验都能对应回前面的五个子系统——但有几个点足够反直觉,值得单独讲。

1. 工程师的角色变了:不写代码,造环境

早期进展比预期慢,原因不是 Codex 不行,而是环境欠规约——Agent 缺工具、缺抽象、缺内部结构。于是工程师的核心工作变成一句话:"缺了什么能力,怎么把它做得对 Agent 既可见又可强制?"

出问题时,修法几乎从不是"让模型再努力一点",而是回头补 harness。人只在更高的抽象层工作:排优先级、把用户反馈翻译成验收标准、验证结果。连修复也是让 Codex 自己写。

2. 给地图,别给一千页手册

他们一开始也试过"一个大 AGENTS.md",失败得很典型

  • 上下文是稀缺资源——大文件把任务、代码、相关文档全挤出去了;
  • 全是重点 = 没有重点——Agent 退化成局部模式匹配;
  • 瞬间腐烂——很快堆满过期规则、无人维护;
  • 难以校验——一整块大文件没法做机械检查(覆盖率、新鲜度、交叉链接)。

改法:把 AGENTS.md 当目录(table of contents),不当百科全书。 一个约 100 行的 AGENTS.md 只做"地图",真正的事实来源放在结构化的 docs/ 目录里——设计文档、执行计划(active/completed/技术债追踪)、生成的 DB schema、产品规格、*-llms.txt 参考资料等。计划是一等公民:小改动用临时轻量计划,复杂工作落成签入仓库的执行计划,带进度和决策日志。

这就是 渐进式披露:Agent 从一个小而稳的入口进入,再被"教"去哪里找下一步。而且机械强制——专门的 linter 和 CI 校验知识库是否最新、是否交叉链接;还有个**"doc-gardening"(文档园丁)Agent** 定期扫描过期文档、自动提修复 PR。

3. 一句最该记住的话:Agent 看不见的,就等于不存在

From the agent's point of view, anything it can't access in-context while running effectively doesn't exist.

那条对齐了团队架构的 Slack 讨论?如果 Agent 检索不到,它就跟"三个月后入职的新人不知道"一样不存在。结论:不断把上下文塞进仓库——代码、markdown、schema、可执行计划,这些才是 Agent 唯一看得见的东西。

由此推出一组反直觉取舍:优先选 Agent 能完全内化的依赖和抽象。所谓"无聊"的技术因为 API 稳定、可组合、在训练集里出现多,反而更好被模型建模。有时候自己重写一个子集,比绕开一个不透明的上游库更划算——他们没用通用的 p-limit,而是手写了个 map-with-concurrency,深度集成自家 OpenTelemetry、100% 覆盖、行为完全可控。

4. 让应用本身对 Agent 可读(这是吞吐的真瓶颈)

代码吞吐上来后,瓶颈变成人的 QA 能力。对策是把 UI、日志、指标直接做得对 Codex 可见

  • 每个 git worktree 能独立启动一份应用实例,一个改动配一个实例;
  • Chrome DevTools Protocol 接进 Agent 运行时,做了 DOM 快照、截图、导航的 skill——Codex 能自己复现 bug、验证修复、对 UI 行为推理;
  • 给每个 worktree 配临时的可观测性栈,Codex 用 LogQL 查日志、PromQL 查指标。于是 "保证服务启动 800ms 内完成"、"这四条关键链路里没有 span 超过 2 秒" 这种 prompt 变得可执行。

效果:单个 Codex run 经常连续干 6 小时以上(通常在人睡觉的时候)。

5. 强制不变量,而非微观管理

文档撑不住一个全自动生成的代码库的连贯性,架构约束才行。他们的口号是 "enforce invariants, not micromanage implementations"

  • 要求"在边界处解析数据形状",但不规定怎么做(模型自己爱用 Zod,没人指定);
  • 整个应用建在刚性分层架构上:每个业务域固定分层(Types → Config → Repo → Service → Runtime → UI),依赖方向严格校验,横切关注点(鉴权、连接器、遥测、特性开关)只能从单一的 Providers 接口进入;
  • 全部用 自定义 linter(当然也是 Codex 写的)和结构化测试机械强制;自定义 lint 的报错信息直接把修复指引注入 Agent 上下文

一句点睛:这种架构本来是公司几百个工程师才需要的;有了 Agent,它成了一开始就得有的前提——约束正是"快而不失序"的前提。 原则是 "中心强制边界,局部允许自治":严格守住边界、正确性、可复现;边界之内,给 Agent 充分自由。代码不总符合人类审美,只要正确、可维护、对未来的 Agent 可读,就达标。

6. 吞吐量改变了合并哲学

当 Agent 吞吐远超人的注意力时,很多传统工程规范反而有害:仓库几乎没有阻塞性的合并门禁,PR 短命,测试 flake 用"重跑一次"解决而非无限期阻塞。因为在这种系统里,纠错很便宜,等待很贵。——这在低吞吐环境下是不负责任的,在这里却往往是对的。

往深一层,这背后是整套工程实践的经济学内核:token、算力、Agent 工时都不再稀缺,唯一真正稀缺的,是"需要人同步介入"的那点注意力。 于是几乎所有工程决策都收敛到同一个目标——把人的同步注意力省到极致。合并门禁的取舍、QA 瓶颈的破解、后台自动清理,本质上都是在省这一项。看懂了这条,前面那些反直觉的取舍就都顺理成章了。

7. 熵与垃圾回收:把人的品味"编码一次,永久强制"

全自动也带来新问题:Codex 会复刻仓库里已有的模式,包括其中不好的,于是必然漂移。

他们一开始靠人手清——每周五(20% 的工时)专门清理 "AI slop",根本不 scale。 真正的解法是把 golden principles(黄金法则) 编码进仓库,配一套周期性清理流程

  • 优先用共享工具包,把不变量收敛在一处,而不是到处手写零散的 helper;
  • 不"YOLO-style"地探数据——而是在边界处校验、或用带类型的 SDK,避免 Agent 建在猜出来的数据形状上;
  • 一组后台 Codex 任务定期扫描偏差、更新质量评分、提定向重构 PR——大多能一分钟内 review 完、自动合并

这套机制像垃圾回收。技术债是高息贷款:持续小额偿还,永远好过让它复利滚大再痛苦集中还。 人的品味只需被捕捉一次,之后在每一行代码上被持续强制。

8. 自治的临界点

随着测试、验证、review、反馈处理、恢复都被编码进系统,这个仓库最近跨过了一道门槛:给一句话 prompt,Codex 能端到端地——校验当前状态 → 复现 bug → 录一段失败视频 → 实现修复 → 驱动应用验证 → 再录一段修复后的视频 → 开 PR → 回应人和 Agent 的反馈 → 检测并修复构建失败 → 只在需要判断时才升级给人 → 合并。

但他们明确提醒:这高度依赖该仓库特定的结构与工具投入,不要假设能直接泛化——至少现在还不能。

一句话收束这一节:人的纪律没有消失,只是从代码本身转移到了脚手架上


六、方案对比:到底要做到哪一档?

按投入由轻到重,分三档:

  • A. 裸 prompt —— 只给一个 README,什么都不补。
  • B. 单 Agent + 五子系统 —— 补齐第三节那五项;一个 Agent,可跨会话。
  • C. 多 Agent 全套 —— B 之上再叠第四节的进阶方法(初始化/执行分离、生成/评估分离、上下文重置)。

怎么选,看一个问题:这个任务,一个 Agent 在一个会话里能不能干完?

  • 能,且做完即弃 → A
  • 要持续迭代、跨多会话 → B(绝大多数情况)
  • 一个 Agent 独自搞不定(几小时、跨几十个窗口、质量要求高)→ C
A B C
▲ 得到
任务成功率 很高
跨会话连续性
质量可控性 很高
▼ 付出
搭建成本 几乎为零
单位任务花费
维护负担 中高
→ 选它的场景 一次性探索 默认:要持续迭代的活 超出单模型能力的硬任务

结论:

  • 绝大多数团队的最优解是 B——投入产出比最高,是性价比最佳点。不要一上来就叠加多 Agent。
  • C 只在任务"超出单个模型独自能力"时才划算:几小时以上、跨多窗口、质量要求高(如完整应用、复杂重构)。它总评不比 B 高,是因为简单任务里那套开销纯属浪费——复杂度要匹配任务难度
  • A 只适合一次性、用完即弃的探索。 任何要持续迭代的东西,停在 A 都会反复付出返工代价。

一个反复被验证的纪律:模型升级后,回头把 harness 逐件做消融测试(ablation)。 Anthropic 在 Opus 4.6 上就发现,模型变强后原来的"sprint 契约"机制可以整个删掉,质量不降、token 大降。Harness 不是只增不减——模型补上的能力,harness 就该减负。


七、照抄即用:Harness 自查清单

落地时,对着这张表勾一遍:

  • Instructions
    • 有一个 ≤100 行的 AGENTS.md / CLAUDE.md,写清项目、技术栈、首次运行命令、红线约束
    • 细节走链接,不堆成百科全书
    • Agent 需要的一切都在仓库里(repo = 唯一事实来源)
  • Tools / Environment
    • 依赖、运行时版本、容器配置齐全,可一键起环境(init.sh
    • 给了能跑 bash / 执行代码的沙箱
    • 权限按最小权限给,而不是一刀切禁
  • State
    • 有进度文件,记录"做完/在做/卡住"
    • 会话开始读进度+git log,结束前更新
    • 用 git 提交留痕
  • Scope
    • 任务拆成机器可读的 feature list(建议 JSON)
    • 每会话只做一个 feature
  • Verification
    • 文档里显式列出 test / lint / typecheck 命令
    • Web 应用有端到端验证(浏览器自动化)
    • 主观质量已拆成可打分的客观维度
  • 长任务额外项
    • 初始化与执行 Agent 分离
    • 生成与评估分离(任务够难才上)
    • 用上下文重置 + 交接产物,而非一味压缩

八、为什么这件事会长期重要

有人会问:模型不是越来越强吗,等它足够聪明,harness 不就没用了?

恰恰相反。LangChain 和 OpenAI 的判断一致:模型越强,harness 的重心只是从"打补丁填模型的坑"转向"为智能优化系统"——但它不会消失。 就像今天模型早已不傻,prompt engineering 依然重要一样。

还有一层更硬的耦合常被忽略:今天的强模型,是和 harness 一起被训练出来的。 LangChain 指出,Claude Code 这类产品在后训练阶段就把"模型 + harness"放进同一个回路联调,模型被专门优化以适配它训练时的那套外壳。这也解释了一个反直觉现象——把一个强模型塞进一个陌生的 harness,往往跑不出它的真实水平。 模型与 harness 是共同进化的关系,不是谁迟早取代谁。

OpenAI 那句话点破了行业的转向:

在 agent-first 的世界里,工程师的主要工作不再是写代码,而是设计让 Agent 可靠产出的环境。

模型是发动机,harness 是底盘、传动和仪表盘。光有发动机,跑不远,也不安全。


附:参考文档


© 2026