别让你的 Coding Agent 瞎忙活,你最缺的可能是这套 Harness 规则
团队把 Claude Code、Codex、Cursor 这类工具接进日常开发后,最先暴露出的瓶颈通常在协作环节。
一个简单的 bug fix 任务,agent 可能会扩出十几个文件的改动。
跑了一行测试,它就已经在回消息里写下"问题已修复"。
仓库里原本就很乱的模块,它会毫无顾忌地顺着旧写法继续往下堆叠。
这类情况多了,大家最近开始频繁提到 Harness Engineering。这个词讲的事情很具体:项目要主动给 agent 准备一套能工作的配套环境。入口、规则、验证和反馈,都在里面。
什么是 Harness Engineering?
"Harness" 的字面本义是马具和缰绳。如果把大模型比作一匹能日行千里的马,那 Harness 就是配套的马鞍和缰绳体系。
在传统软件开发中,这个词多数时候对应测试脚手架(Test Harness),是一套用来自动化跑输入、约束运行边界、验证结果的包裹环境。
当 AI 接手项目里具体的编码任务时,Harness Engineering 指的就是给 Agent 搭建的这层项目"外包围"结构。
模型不管多聪明,直接扔进一个有历史包袱的业务仓库里都很容易踩坑。为了让它踏实干活,项目必须给它套上一层确定的工作环境:
- 明确指路,告诉它该去哪找上下文,哪些老旧文件动不得;
- 备好现成的验证脚本,让它依靠真实的运行报错来改代码,避免盲猜;
- 划定动作边界,强制它在跨模块大改前必须停下来重新确认。
Prompt 负责让大模型听懂你的意图,Harness 负责让 Agent 在你的代码库里把事干对。
先看一个极其常见的场景
假设产品提了个小改动:
text
设置页里切换语言后,顶部标题不会刷新
很多 agent 接到这个任务后,会做出这样的提交内容:
- 改了语言切换逻辑
- 顺手调整了
settingsStore.ts - 更换了
i18n.ts里的旧接口 - 再顺手把两个相关组件的 props 命名做了一遍统一规范
最后看 diff,一共改了 9 个文件。
最麻烦的地方在于任务边界完全发散了,你已经没法把它当成一个普通 bugfix 来做 code review。
想管住这种发散靠口头嘱咐通常没用,规则必须以具体形式落进项目里。最常见的做法是在 AGENTS.md 中写好:
md
For bug fixes:
- Keep changes within the reported feature boundary.
- Do not refactor nearby modules unless asked.
- If you need more than 3 files, stop and explain why first.
- Run:
- pnpm test --filter settings
- pnpm lint
- pnpm typecheck
这层设定非常具体,上来就直接收住了 agent 的发散手脚。
Harness 管的就是这些事
项目全面引入 agent 后,底下这几个环节就不该再依赖口头传达:
- 它该先查阅哪份指导文档
- 平时高频跑的几个测试和检查命令是什么
- 什么时候要先给计划再写代码
- 提交完成前保底要过掉哪些检查
- 仓库里哪些祖传代码目录绝不能碰
- 触发什么条件必须直接停下等人类介入
- 最终的验证结果依赖哪些指标,不听凭它的主观回答
仓库里这些要素越散,agent 自由度越高,猜错的几率也越大。
规则只要能归拢到一个固定入口,最终产出的可用度都会稳当很多。
顶级团队已经靠它跑出了惊人产能
如果觉得搭建这些环境太繁琐,可以看看头部团队的真实数据。
OpenAI 的研发团队在 2026 年初交出了一张靠 Harness 跑通的极端验证答卷:他们花 5 个月构建出了一个包含内部工具和测试环节的商业应用,总代码量级达到 100 万行,但全组工程师没有手写过 1 行真正的逻辑代码。
他们仅安排了 3 到 7 个工程师,平均每人每天能吃下 3.5 个 Pull Request 的合并量。这种吞吐量的核心,就是人类工程师完全调转了职能------大家不再当"语法打字员",而是全部转岗变成了"给 Agent 搭场子的人"。
用他们的话说,只要把环境切分、自动化跑测跟验收机制(也就是 Harness)架设得足够牢固,Agent 便能在里面极其稳定地输出大体量代码。
为什么大家开始认真聊这个
前一波关于 AI 编程的探讨,大部分围绕 prompt、context、RAG 和 memory。这些非常核心,解决的是如何把上下文准确喂进模型里的问题。
但现在的 agent 已经能处理很综合的操作:
- 读取和分析项目结构
- 修改多个耦合模块
- 调用外部接口
- 自己跑测试验证
- 接管一条独立的完整需求
在这些复合动作下,项目的本地环境直接决定了产出好坏。
让同一个模型去改两个配置不同的仓库,表现往往天差地别。
差异通常出在这几个维度:
- 一边命令入口极其统一,另一边靠 README、口头传达和碎块化的约定拼起来
- 一边测试报错直观透明,另一边遇到校验必须靠人工亲自去点页面测试
- 一边明确了目录和模块的进出许可,另一边连人类开发者都摸不清依赖关系
遇到后面那种仓库,不管大模型能力多强,也只能依靠生猜。
常见的三个坑
1. 小任务扩成大重构
你可能只提了一句简单的:
text
修一下订单页 total price 计算错误
它交回来的作业却像在做全局重构:
- 修复了价格计算逻辑
- 把格式化代码抽了出来变成
formatPrice - 批量换了几个变量的混乱命名
- 顺便清理了一些老旧的单测文件
看起来每一步都很有道理,但这一连串动作已经彻底脱离了最初的任务边界。
对应的管束手段就是直接写死通用规则:
md
Bugfix tasks should prefer the smallest working change.
Avoid refactoring unless the user asks for it.
If the change grows, stop and summarize before continuing.
这种硬性限制极其抗造,对喜欢"过度重构"的 agent 非常管用。
2. 谎报测试通过
凡是用过 agent 的人都面对过它的"虚空汇报":
- 已修复报错
- 后端验证已通过
- 界面调整完成
但你一跑起来,原来的问题照旧躺在原地。
这通常是因为它的检查范围过于局限:
- 它只跑过了核心计算的单测,并没顾及整体代码流程的集成问题
- 它观测到调用响应是 200,就笃定这块没问题
- 彻底忽视了异常分支、容错处理和移动端的布局等边界情况
项目里必须给它设定确切的完成指标:
bash
pnpm test --filter orders
pnpm playwright test e2e/orders-total-price.spec.ts
然后附加一条铁纪律:
md
Do not report completion until the targeted test passes.
If you cannot run the browser flow, say so explicitly.
压缩幻觉空间,避免含糊其辞。
3. 原样复刻老毛病
很多工程师一开始没留意这个盲点:agent 吸纳当前代码风格的学习能力极强。
如果当前的模块充满了不规范设计,它会原封不动地照着样子走:
- 随处粘贴复制的工具方法
- 各自为营的新旧接口混用
- 类型定义满仓库随机散落
- 不具备统一结构的底层依赖继续堆叠
Agent 很少并在这种时候跳出框外反问:"是不是应该先把这些依赖规范?"
顺着烂摊子继续添砖加瓦就是它的默认机制。
项目的基本面越乱,agent 制造技术债的规模效应越惊人。
优先补齐五件事
引入 Harness 不需要搞大而全的方法论,先落地最务实的几步。
1. 设立固定的引导文档
至少保证项目起步有这份清单:
- 一份
AGENTS.md或者CLAUDE.md索引 - 一套用着顺手的执行指令
- 一个极其简单的开发工作流步骤
这里的条款越少越精准越好,只涵盖:
- 项目依赖及跑库跑通需要过哪些关
- 测试或校验命令对应哪些快捷调用
- 代码修改严厉禁止越线的那些深水区
- 当大架构可能产生波及时,要有什么申请动作
示例:
md
Start:
- pnpm install
- pnpm dev
Checks:
- pnpm lint
- pnpm typecheck
- pnpm test
Rules:
- Do not edit /generated
- Ask before changing shared schema
- For UI bugs, run the related Playwright spec before reporting done
这份核心指引确立了 agent 干活不可动摇的下限。
2. 把常规嘱咐转换成硬 CI
很多团队乐于把这些话大面积写进配置里:
- 注意考虑上下文兼容
- 建议照顾代码命名的一致性
- 多考虑补充相关的验证模块
这类虚话对自动化修改的约束力极低。不如把口语要求转化成会亮红灯的 CI 校验命令:
json
{
"scripts": {
"check": "pnpm lint && pnpm typecheck && pnpm test",
"check:settings": "pnpm test --filter settings && pnpm playwright test e2e/settings.spec.ts"
}
}
然后在对应的规范里只要求:
md
Before reporting completion, run the relevant check script.
用强制的命令替代松散的话语。
3. 及时透传运行反馈
光看静态文件排查 bug 很容易歪曲原意。
下面这些动态结果才是调试代码的核心依据:
- Web UI 测试工具跑出来的验证过程
- DOM 组件报错对应的页面报错截图
- 测试框架捕获抛出的 console error
- 各类复杂的全链路后台日志表现
解决渲染 bug,别只让它死心眼地跟单测耗着。直观地喂一条看到效果的测试命令:
bash
pnpm playwright test e2e/settings-language.spec.ts --reporter=line
让它真正借助反馈去打补丁,输出水平能立刻上来。
4. 用工具彻底截断重蹈覆辙
一旦同一个 agent 在处理类似问题上接连踩空三四回,别指望它自己变聪明。
习惯性错引包地址、忘记类型同步排查、瞎改那些底层配置文件。这些情况就是固化防御规则的好时机。
常见抓手包括:
- 设置严防死守的 pre-commit 勾子
- 做强阻断的包限制权限
- 收拢高频组合出来的集成 wrapper
- 让跑飞的代码执行触发 fail-fast 尽早失败截停
以常见的多包管理 monorepo 为例,它非常容易跑在最上层直接发起耗时极长的全库校验。通过收拢命令去掐死这种无差别动作:
bash
pnpm check:orders
阻断它毫无意义的探索尝试,自然就能降低后续不必要的人工盘查时间。
5. 设立定期的"后台清道夫"
面对 AI 极易产生的代码发散(比如不知不觉间写乱的工具包、冗余的旧逻辑),最前沿的解法是用魔法打败魔法:建立后台 Garbage Collection(垃圾回收)机制。
与其让工程师天天跟在 Agent 屁股后面修补烂代码,不如直接专门起一个跑在后台的重构 Agent。只要明确了黄金规则,给它设定固定的扫描频次,让它专门拉分支去按节奏清理散落各处的偏离规范代码,小步快跑地持续清还技术债。
防范 Agent 制造屎山的最优解,就是再给它套一个专门重整基建的 Harness。
无法逃避的基建隐形成本
做这些整顿并不能像交付一个光鲜功能那样收获快感,主要心智都花在解决原有腐化问题上。
补齐测试边界缺口、收敛零散冗长的代码脚手架、理顺那些年久失修的错误机制响应,样样都是苦茬。
但凡避开了这层基底,隐形成本会快速体现在更长远的维护周期里。由于 agent 出库节奏远远大于人工打字,连带带回的将是由它放大的批量返工排雷。
退一万步讲,Harness 工具仅仅是帮你管住了做事流程不失控。实际功能正不正确还得由具体的用例覆盖程度来最终买单。测试脚本测不到的长尾边缘问题,agent 也一样会漏进线上系统。
适用的边界
如果业务场景对应以下画像,Harness 工程基建越快铺完越舒服:
- 项目将会有大批日常小维护单扔给 agent 去扫尾
- 内部存在高度重叠与密集的研发交互协作节点
- 严格配备着严谨审核要求与完备流程闭环规范的仓库
- 失误带来的代价极其敏感沉重的系统代码模块
- 尝试通过这些智能机器去消化大量长周期宽边界的繁杂开发
相对的,仅仅是随手写验证脚本的实验文件、没有长臂约束的一波流独立原型小应用。不需要生搬硬套挂设枷锁。体量过小,一两个人花三五分钟手动看两眼反而还更容易。
现汇的一个检验办法
单纯地跟跑一两个测试数据集模型的准确率百分比,说服力已经严重贬损了。
当各家公司接连让 AI 接管真正的产线任务,业务包里遗留的标准、命令统一的集中度、校验反馈链的通畅率甚至是极其基础的代码整洁程度,已经实质上决定了你能通过智能获得什么水平的回报率。大白话讲这依然是场实打实的传统软件防跑偏工作。
如果你的业务仓库已经接连透出这样的危险信号:
- 处理一个小调整,被发散拉扯到了多条核心主线链路变动
- 界面上的回复永远光彩照人,下个场直接启动测试立卡成麻
- 代码评审时面对它发散过头的提交比起人工写出的错误更感觉心力交瘁
- 仓库内过去沉淀下来的不良祖传规范成了它大规模复制的标尺
那其实就在表明这套代码环境已经包不住 agent 干活的负外溢了。赶紧先把项目的 Harness 篱笆扎起来吧。