← cd ../posts

Harness Coding:与其调教模型,不如设计模型的工作环境

2026-05-21

Harness Coding:与其调教模型,不如设计模型的工作环境

过去半年我换了三次 AI coding agent,从 Cursor 到 Claude Code 再到自己拼的 编排器。结论很反直觉——真正影响产出质量的从来不是换更强的模型,而是模型 周围那一层我一开始压根没意识到存在的东西

这层东西有个名字:Harness

一、Agent = Model + Harness

业界这两年逐渐形成一个共识公式:

Agent = Model + Harness

模型(GPT / Claude / Gemini …)只是 Agent 的一部分。模型之外的所有东西—— 工具集、规则文件、反馈机制、工作流编排、上下文组装策略、CI 门禁—— 统称为 Harness

Addy Osmani 引过一个挺震撼的数据点:在 Terminal Bench 2.0 上,同一个 Claude Opus 4.6,套在某通用 CLI 里只能排到 Top 30,套到一个精心设计的定制 harness 里能跳到 Top 5。模型一字没改,只换了它工作的"环境"。

口号:

一个体面的模型 + 出色的 harness,能打败出色的模型 + 糟糕的 harness。

这意味着,当你抱怨"AI 写的代码不行"的时候,大概率不是模型不行,是你给它的 环境不行——这件事现在叫 Harness Engineering(或 Harness Coding)。

二、三大支柱:约束 / 反馈 / 门禁

一个完整的 harness 大致三层:

┌────────────────────────────────────────────────┐
│  ① Feed-forward Constraints(前馈约束)          │
│  在代码生成前缩小解空间                            │
│  → AGENTS.md / Cursor Rules / 类型系统 / 架构图    │
├────────────────────────────────────────────────┤
│  ② Feedback Loops(反馈循环 / Sensors)          │
│  让 agent 在你看之前自己发现问题并自我纠正           │
│  → Linter / 类型检查 / 测试 / Hook                 │
├────────────────────────────────────────────────┤
│  ③ Quality Gates(质量门禁)                      │
│  阻止不合格代码进入主干                            │
│  → CI / pre-commit / Required Reviews              │
└────────────────────────────────────────────────┘

这三层的本质差别是约束生效的时机

  • 前馈是"开始写之前先告诉它规矩"
  • 反馈是"写完之后立刻让它知道错了"
  • 门禁是"错了的不许合"

很多人只做了第一层(写 prompt / 写 rules 文件),结果发现"AI 老是不听话"。 原因是只有前馈、没有反馈和门禁——LLM 是概率模型,告诉它"请遵守 X", 它大概率会遵守,剩下那 5% 就是你的事故来源。

Prompt 里说 vs Lint 里卡

举个最经典的对照:

告诉 agent:「请遵守我们的编码规范」     ← 概率性合规
写一条 linter 规则,违规直接 fail PR       ← 确定性合规

这两件事是根本不同的东西。Harness 思维就是:能用确定性手段卡住的, 绝不留给概率性手段。

三、把 AGENTS.md 当代码维护

AGENTS.md(OpenAI / Cursor / Claude Code 都认这个文件名,逐渐成为跨工具 标准)是 harness 最常被忽视的入口。常见的几条反模式:

600 行的风格指南——LLM 实际上读不完,注意力会被稀释 ❌ "请尽量"、"建议"、"考虑"这种软措辞——概率性表达,不可执行 ❌ 没有人维护,半年没更新——和代码漂移之后越用越坑 ❌ 每条规则都是凭空写的——没有来源,没人记得为什么有这条

正确的几条原则:

保持在 60 行以内——超过这个数说明该拆成 lint 规则了 ✅ 每条规则可以追溯到一个具体失败事件("棘轮原则",下一节细讲) ✅ 用三级边界:必须做 / 先请示 / 禁止做——别让 LLM 自己拿捏 ✅ 把 AGENTS.md 当代码:进 PR、过 review、定期重构

口诀:AGENTS.md is code, treat it like code.

四、棘轮原则(Ratchet Principle)

这是 harness engineering 最重要的一条操作方法论

每一次失败都应该被转化为一条永久规则。

每一条 AGENTS.md 的规则都应该可以追溯到一个具体的失败事件。

为什么叫"棘轮"——棘轮只能向一个方向转。你的 harness 应该是单调收紧的: 出过的错不能再出第二次。

实操循环:

1. Agent 出了一个错(比如建了个我不想要的 helper class)
2. 别只在当前 PR 里改掉,问自己:这个错该怎么"在源头"防住?
3. 三个选项,按强度排序:
   a) 加一条 AGENTS.md 规则(最弱,前馈)
   b) 加一条 linter / 类型规则(中等,反馈)
   c) 加一条 CI 门禁(最强,门禁)
4. 选能用的最强那一档,提交进 harness 仓库
5. 下次同样的错不会再发生

这个循环跑顺了,你的 agent 就会随着时间越来越好用,而不是反过来。

五、让错误信息本身成为 prompt

Harness 的反馈层有个非常容易被忽视的细节:报错文案要写给 LLM 读

对照:

# 普通 lint 错误(写给人看)
error: max-complexity exceeded (12 > 10)

# 写给 agent 看的 lint 错误
error: Function complexity is 12 (limit: 10).
       Refactor by extracting the early-return validation block into
       a separate `validateInput(...)` helper, or by collapsing the
       nested switch into a lookup table.
       See: docs/complexity.md#how-to-fix

第二种写法里,错误信息就是修复指南。Agent 拿到这条 lint 输出,下一轮 就有 70% 概率能自己改对。

这件事的转变是:Linter / 类型检查器 / 测试报错文案,从给 reviewer 看的 工件,变成给 agent 看的反馈接口。 这是 harness 时代的新职业素养。

附带一条相关的反模式:

禁止 agent 使用 inline disable// eslint-disable-next-line 一类)。

不然 agent 会把"违规"压成"抑制违规"——表面看 lint 过了,本质上规则被 绕过去了。Harness 必须堵死这个口子。

六、Plan → Execute → Verify

别让 agent 一口气把多步任务做完。强制走 PEV:

Plan       — 先输出明确的 step list,人/工具过一下
Execute    — 按 plan 走,每一步独立可观察
Verify     — 跑测试 / 对照 plan / 跑 sensor,确认对了再下一步

每个转换点(plan → execute / execute → verify)都是一个插入约束的 机会——是写"必须先 plan 再写代码"的 hook、还是写"verify 不过就回退到 plan 重做"的循环,看你的场景。

经验:把 PEV 写进 harness 之后,最大的好处不是 agent 写得更对,而是 你能在 plan 阶段截停——省下一堆"已经写了 200 行才发现方向错了"的痛苦。

七、工具集:10 个比 50 个好

很多人给 agent 接 MCP 接到 50 个工具,觉得"能力越多越好"。实测反过来—— 工具菜单太长,LLM 选错工具的概率显著上升

经验法则:

  • 同类工具不要超过 2 个("读文件"不要既有 Read 又有 Cat 又有 FileGet
  • 每个工具的 description 必须和别的工具有明确区分
  • 危险工具(删除 / 推送 / 调外部 API)单独放一组,加确认
  • 周期性 audit:看 trace 里哪些工具 90 天没被调用过,删掉

口诀:10 个聚焦工具 > 50 个重叠工具

八、长任务:双层 agent + 进度文件

跨多个上下文窗口的长任务(比如让 agent 跑两周建一个项目),单 agent 跑不动。 Anthropic 推荐的双层架构:

Init Agent     — 只跑一次,搭骨架:
                 - 生成 init.sh(一键起开发环境)
                 - 生成 features.json(200+ 任务清单 + 状态)
                 - 建初始 git 仓库 + 第一条进度记录

Coding Agent   — 每次 session 跑一轮:
                 1. 读 git log + progress.md → 知道上次到哪
                 2. 从 features.json 挑一个未完成的最高优先级项
                 3. 跑 init.sh 起环境 + 冒烟测试
                 4. 做这一项 → 测试 → commit → 更新 progress
                 5. 退出

关键设计:

  • 进度文件是 agent 的"持久记忆"——不依赖上下文窗口
  • 一次 session 只做一个 feature——防止"宣告完成幻觉"
  • 会话开始先验证环境——防止"在脏环境里写代码"
  • 会话结束必须 commit——防止下次 session 看到不一致状态

把这套搬到非 coding 场景也成立——研究 / 数据建模 / 写作,都能用同一套 "init agent + work agent + 进度文件"模式跑。

九、度量你的 harness

Harness 是软件,软件就该有指标。几个 Augment Code 在用的:

指标 怎么测 为什么有用
任务解决率 自动化测试通过率 Harness 整体健康度
代码变更率 两周内被重写的代码 % 衡量"agent 写的代码站不站得住"
验证开销 审计时间 / 首次提交时间差 衡量人工 review 负担
缺陷逃逸率 上线后按 commit 来源标记的 bug 终极指标

没有指标的 harness 优化,约等于凭感觉调 prompt。

十、心智模型转变

我感觉 harness coding 真正难的地方是心智模型的转变

旧思路 新思路
我在让 AI 写代码 我在设计让 AI 写代码的环境
Prompt 没写好,再调 prompt Prompt 一次性的,规则要进 harness
Agent 又出错了,骂它一顿 Agent 又出错了,问 harness 哪里漏了
模型不行,等下一代 模型够用,harness 还差很多
写代码 写 harness

最后一行我觉得最重要——未来工程师的核心产出,从代码本身,逐渐转移到 "约束代码生成过程的那套系统"。代码是 agent 在 harness 边界内的副产品。


怎么开始

如果你完全没动过 harness,从最便宜的三步开始:

  1. 审计最近 5 个 agent 写的 PR——找重复出问题的模式
  2. 挑 3 条模式编码成 lint / type 规则——记得报错文案要写给 agent 看
  3. 在 CI 里硬卡这 3 条——并记录修改前后的"人工 review 时长"

跑两周。如果 review 时间下降,恭喜,你已经在做 harness engineering 了。

剩下的事情就是把"棘轮"持续转下去。


相关阅读

  • Effective harnesses for long-running agents — Anthropic
  • Agent Harness Engineering — Addy Osmani
  • Harness Engineering for AI Coding Agents — Augment Code
  • Harness engineering for coding agent users — Martin Fowler