Harness Engineering 的介绍与实践

同样是用 AI 编程,有的团队已经能让 Agent 稳定改代码、跑测试、收敛结果;有的团队却还停留在“写得挺像,但一跑就炸”。差距往往出在模型外面那套工程系统,也就是让 AI 能安全干活的 Harness。
为什么会有 Harness Engineering
这两年 AI 编程工具变化很快。
最早大家更多是在“问模型”:解释代码、生成函数、补一段脚本。这个阶段最重要的是 Prompt Engineering,也就是把需求讲清楚,减少模型理解偏差。
后来大家发现,只会写提示词还不够。模型如果不知道项目目录、接口约定、历史设计和运行方式,就很容易一本正经地瞎猜。于是 Context Engineering 开始被反复提起:该给模型哪些文件、日志、文档和规则,才能让它少幻觉。
但当 AI 真的开始改文件、跑命令、修测试,问题又变了。
这时最让人头疼的,开始变成这些事:
- 改错文件;
- 破坏已有结构;
- 不按既定文档开发;
- 规避失败,假装成功;
- 顺着错误假设越修越远;
- 长任务做着做着忘了原目标;
- 执行高风险命令却没有人工确认。
这些问题,光加一句“请谨慎操作”没什么用。你需要一套外部机制,让 AI 的行为有边界、有反馈、能收敛。这套机制,就是 Harness。
一个很好记的公式是:
Agent = Model + Harness
模型负责推理和生成,Harness 负责环境、工具、约束、状态和反馈。没有 Harness,模型更像一个会说话的大脑;有了 Harness,它才更像一个能在工程环境里干活的代理。
Harness 到底在管什么
如果一定要找个中文说法,我更愿意把 Harness 理解成:护栏 + 工具链 + 运行框架。
别把它理解成某个单独工具,也别理解成一个提示词模板。更准确地说,它是一层围着模型搭起来的工程控制系统。
落到 AI 编程场景,Harness 一般要把几件事管起来:
- 上下文管理:让代理知道项目结构、任务目标、相关文件和编码约束;
- 工具接口:让它能读文件、搜代码、跑测试、打补丁,少靠猜;
- 执行沙盒:让命令运行在受限环境里,出错也别伤到真实环境;
- 规则约束:用 lint、类型检查、架构规则和权限边界限制越界动作;
- 验证循环:把测试失败、构建报错、审查意见重新喂回去,让它继续修;
- 人工闸门:删文件、改生产配置、发版部署这类动作,必须有人点头。
所以我现在更倾向于把 Harness Engineering 看成一件工程活。它要解决的是环境问题:就算模型犯错,错误也尽量落在可控范围内。即:用流程与规范来约束模型。
它和 Prompt、Context 的关系
这三者可以按顺序叠起来看。

| 阶段 | 主要问题 | 关注点 | 常见手段 |
|---|---|---|---|
| Prompt Engineering | 任务没说清 | 怎么表达 | 角色、步骤、示例、输出格式 |
| Context Engineering | 模型不知道事实 | 给什么信息 | 检索文件、注入文档、压缩上下文 |
| Harness Engineering | 行为不可控 | 怎么执行和验收 | 沙盒、工具、验证、审批 |
Prompt 做得好,模型更容易听懂。
Context 给得对,模型更不容易瞎编。
Harness 搭得稳,模型就算一开始想偏了,也不会一路狂奔到把仓库搞坏。
换句话说,前两者主要解决“想清楚”,Harness 主要解决“做稳”。
一个好用的 Harness 有哪几层
如果把 Harness 拆开看,我觉得至少有五层:项目地图、工具层、沙盒层、验证层和收敛层。
用图来理解,会更直观一点:
这张图没有把所有细节都画全,主要想表达一点:Harness 要靠多层配合,让 Agent 一步步靠近可交付结果。
项目地图

AI 进入一个项目,最怕两件事:找不到入口,不知道禁区。
所以我越来越看重项目里有没有一份足够短、但足够管用的说明文件。名字不重要,AGENTS.md、CLAUDE.md、团队手册都行。关键是它能不能把下面这些事讲明白:
- 项目是什么技术栈;
- 源码、测试、配置分别在哪里;
- 常用构建和验证命令是什么;
- 代码分层和依赖方向是什么;
- 哪些目录不能手动改;
- 常见坑和禁止模式是什么。
对代理来说,这份文件就是第一张地图。
很多人喜欢把所有规则一次性塞进提示词里,我现在反而觉得不如给一个清晰入口,让代理按需读。这样更省上下文,也更不容易漏重点。
工具层
模型本身不会真的“看见”仓库,它只能通过工具接触代码。
最基础的一组工具,通常包括:
read_file:读文件;rg/grep:搜索代码;list_files:看目录结构;shell:跑构建、测试和脚本;apply_patch:用可审查的方式改文件;git diff:确认改动范围。
很多时候,代理好不好用,模型能力只占一部分,工具顺不顺手也很关键。
- 工具太少,它只能猜;
- 工具太散,它容易乱试;
- 工具权限太大,又会变成安全问题。
比较理想的状态是:给它完成任务所需的能力,但把危险能力放到审批之后。
沙盒层
AI 跑命令之前,最好先问一句:它失败了,会不会伤到真实环境?
沙盒的意义就在这儿。它不一定多炫技,但它决定了你敢不敢真的让 AI 动手。
常见限制包括:
- 只允许修改当前工作区;
- 外部网络访问需要额外批准;
- 删除文件、重置分支、部署服务要人工确认;
- 临时文件只能写到指定目录;
- 密钥和生产配置不直接暴露给代理。
这些限制看起来麻烦,但正因为有限制,我们才敢把更多实际任务交给 AI。
现在的编程工具大部分都会默认创建一个沙盒了。
人工闸门
现在强大的模型搭配合适的工具会自动提示风险,便于提供给用户介入。

验证层
AI 写代码最麻烦的地方,往往不在语法。
真正难受的是:它写出来的东西乍一看像那么回事,跑起来又露馅。
所以 Harness 里必须有验证回路,不能让代理靠一句“我已经改好了”就结束任务。常见验证信号包括:
- 格式化检查;
- lint;
- 类型检查;
- 单元测试;
- 集成测试;
- 构建结果;
- 静态安全扫描;
- 人工 review。
这些检查不一定一次全上,可以分层跑。越便宜、越快的越该前置;越重的越适合放到 CI 或人工验收阶段。
更关键的是,测试失败之后,代理还能不能拿着错误信息继续修。
如果它看到报错就停,测试只是拦截器;如果它能进入“修改 -> 验证 -> 读错误 -> 再修改”的循环,测试才真正变成反馈系统。
收敛层
长任务里,AI 很容易出现一种情况:修 A 引入 B,修 B 又破坏 C,最后越改越偏。
所以一个好的 Harness,要同时告诉代理怎么做事、什么时候才算做完。
这个“做完”不能只听模型自己说,要看外部事实。比如:
- 目标文件确实改到了;
- 相关测试通过了;
- 构建通过了;
- diff 范围基本符合预期;
- 没混进无关改动;
- 高风险操作已经获得确认;
- 最终说明和实际变更对得上。
这些条件满足了,任务才算真的收敛。
如果代理连续几次都卡在同一个错误上,Harness 也该让它停一下,重新分析,别无休止地试错。
拿修一个 bug 举个例子
如果把场景换成“让 AI 修一个后端接口 bug”,一个比较像样的流程应该长这样:
- 用户描述问题,并给出复现方式;
- 代理先找接口代码、日志、测试和最近相关改动;
- 它给出计划,说明准备动哪些文件;
- 通过 patch 做受控修改,不要直接重写整块模块;
- 先跑最相关的局部测试;
- 如果失败,把错误日志重新喂回去继续分析;
- 局部通过后,再扩大验证范围;
- 最后输出改动摘要、验证命令和风险点,交给人看。
真实工作里,最容易出问题的,往往卡在这些地方:
- 上下文没找全;
- 失败日志没看懂;
- 明明只该改一个函数,却顺手改了一片。
AI 会写代码已经不稀奇了。真正难的是,让它在错误反馈里不断缩小问题范围,别一路拍脑袋往前冲。
怎么开始实践Harness?
模型的能力是第一位,模型能力跟不上,harness再多也是徒劳。
一开始没必要先搭很重的平台。一个最小可用的 Harness,通常可以从四件事开始。
写清楚项目入口
最容易见效的一步,是维护好项目根目录的 AGENTS.md。
它不需要写成长篇论文,但至少要能回答:
# 项目说明
## 项目架构
## 技术栈
- Hugo static site
- 自定义 thinkblog 主题
## 常用命令
- hugo server -D
- hugo
## 目录约定
- content/post/ 存放文章
- themes/thinkblog/ 存放主题源码
- public/ 为构建产物,不要手动编辑
## 修改原则
- 优先小步修改
- 不要混入无关格式化
- 修改主题后需要验证首页、详情页、列表页和搜索页
## 任务流程
## 注意事项
Claude.md
这其实就是最小可用版 Harness。很轻,但常常比一堆空泛要求更有用。
它在代理动手前给方向,在代理动手后给验收条件。如果某类错误反复出现,就继续把它写进去。这相当于给项目补长期记忆。
建一张命令清单
很多项目其实有验证命令,只是命令散落在 README、CI 配置和开发者记忆里。
对 Agent 来说,最好把命令整理成一张小表:
| 场景 | 推荐命令 | 说明 |
|---|---|---|
| 改后端逻辑 | go test ./internal/... | 先跑相关模块 |
| 改前端组件 | npm run test -- Button | 先跑局部测试 |
| 改全局样式 | npm run lint && npm run build | 检查样式和构建 |
| 改 Hugo 内容 | hugo | 检查 front matter 和模板 |
这张表不用替代 CI,它主要帮代理判断“先验证什么最划算”。
给任务分风险等级
不同任务不应该用同一套权限。
一个简单分级可以是:
- 低风险:改文案、补注释、加测试,可以让代理直接做完并给出 diff;
- 中风险:改业务逻辑、改构建配置,必须跑对应验证;
- 高风险:删文件、改数据库迁移、改权限规则,必须人工确认;
- 生产风险:发版、部署、操作线上数据,代理只能准备步骤,不能直接执行。
分级越清楚,越容易把自动化范围往前推,也越不容易把“省时间”变成“埋雷”。
定义完成标准
很多 AI 任务失败,常常卡在“完成”的定义太模糊。有些AI去取巧,绕过事实,利用打桩或者借口,忽略失败。
可以把完成标准写得更具体一点:
- 改动只覆盖任务相关文件;
- 关键测试或构建命令已经执行;
- 失败日志已经处理或明确说明原因;
- 没有引入无关格式化;
- 最终说明包含改了什么、如何验证、还有什么风险。
这几个条件一旦固定下来,Agent 的输出就会更像工程交付,少一点看起来很自信的空话。
有哪些技术可以构建harness?
利用subagent增强Harness
Subagent 这件事,表面上看像“多开几个 AI 一起干活”,但实际要好用,前提是 Harness 已经把分工和边界画清楚了。
不然多 Agent 很容易从提效工具变成混乱放大器:都在读同一堆上下文,都想改同一批文件,最后互相覆盖,主代理还得花时间收拾残局。
所以 subagent 更适合这种场景:
- 任务能拆成几个相对独立的小块;
- 每个小块都有明确产出;
- 写入范围可以尽量错开;
- 主代理能负责最后集成和验收。
比如修一个稍复杂的功能时,可以这么拆:
- 一个 subagent 去扫相关文件和历史实现,给主代理补地图;
- 一个 subagent 只负责补测试;
- 一个 subagent 只负责改某个独立模块;
- 主代理最后统一看 diff、跑验证、决定要不要合并思路。
这样分才有意义。因为 subagent 擅长的是并行探路,不是替你逃避设计。
还有一点很关键:subagent 最好拿到的是收窄过的问题,而不是一句“你去帮我把这个系统搞定”。问题越具体,边界越清,回来的结果越能直接接进主流程。
所以在我看来,subagent 不是 Harness 的替代品,反而是 Harness 成熟之后才更有价值的一层。你先把任务入口、工具、权限、验证和完成标准定住,再让多个代理去并行干活,这时它们才像协作;不然就只是多人一起乱试。
利用skills增强harness
如果说 AGENTS.md 是项目级地图,那 skill 更像任务级外挂。
它解决的不是“这个仓库是什么”,而是“这类事通常该怎么做”。比如写博客、改测试、查日志、补前端样式,这些任务都有各自稳定的套路。每次都靠一大段 prompt 现编,效果往往不稳;把它们沉淀成 skill,Harness 就多了一层可复用的领域经验。
一个好用的 skill,通常会把几件事提前讲明白:
- 适用场景是什么;
- 这类任务优先看哪些文件;
- 有哪些固定步骤;
- 哪些表达或操作要避免;
- 最后要交付成什么样。
像我现在写这篇文章,用的其实就是博客写作 skill。它不会替我写内容,但它会提前把边界卡住:文章放哪、front matter 怎么跟旧文风格保持一致、哪些句子太像 AI 腔、哪些站内旧文值得参考。
这类东西一旦沉淀下来,收益很直接:
- 少重复说明;
- 少把上下文塞爆;
- 让不同任务走不同轨道;
- 把“经验”从人脑里搬到系统里。
我现在更愿意把 skill 理解成:可调用的任务手册。它本质上还是 Harness,只不过粒度更细,贴着具体任务类型。
不过 skill 也别贪大。最怕把十几类任务、几十条规则全塞进一个大 skill,最后谁都能用,谁都用不好。比较稳的做法还是小而专:一个 skill 只解决一类问题,必要时再挂参考文档、脚本和模板。
利用Hook增强Harness
Hook 的价值,在于把“提醒”变成“拦截”。
很多规范如果只写在文档里,模型是有可能看漏的;但如果放到 Hook 里,它就会在关键节点真的执行。比如:
- 修改文件前,自动检查目标目录有没有
AGENTS.md; - 运行命令前,识别是否包含高风险操作;
- 写完代码后,自动跑格式化或最小验证;
- 命令失败后,把 stderr 摘出来重新喂给代理;
- 输出结果前,补上变更摘要和验证记录。
这样一来,Harness 就不只是“告诉 Agent 应该怎么做”,而是能在生命周期节点上主动介入。
一个很常见的例子是风险命令拦截。像 rm、git reset、部署脚本、数据库迁移这类动作,你完全可以在 Hook 里先识别,再决定是直接拦、要求确认,还是转成只读预演。
还有一种特别实用的 Hook,是把失败信息整理干净。模型经常不是不会修,而是拿到的错误太脏:几百行日志混在一起,重点埋掉了。Hook 可以先把报错裁短、提取关键栈和退出码,再交给 Agent 继续分析,这种效果一般比“把原始日志整段扔回去”稳得多。
所以 Hook 更像一层自动值守。它不是替模型思考,而是在入口、执行中和收尾处,把一些确定性的动作先做掉。
利用workflow构建Harness
很多团队一开始做 Harness,容易只盯着 prompt、工具和权限。真正用久了会发现,workflow 才是把这些东西串起来的骨架。
因为真实任务不是一次调用,它更像一条流水线:
接任务 -> 读上下文 -> 出计划 -> 小步修改 -> 跑局部验证 -> 失败回喂 -> 扩大验证 -> 输出结论
如果这条线没有固定下来,Agent 每次都会自己决定顺序,结果就是今天先改再测,明天先全量构建,后天又跳过验证,稳定性很差。
把 workflow 固定下来之后,很多事就顺了:
- 什么时候该读文档;
- 什么时候该给计划;
- 什么时候只能小步改动;
- 什么时候先跑局部验证;
- 什么时候必须人工确认才能继续。
常见误区
把 Harness 当成提示词模板
提示词模板当然有用,但它只是 Harness 的一小部分。
真正的 Harness,一定得有外部验证和执行约束。否则系统只能说“请遵守规范”,却不能在越界时发现并拦住,那顶多算建议,还谈不上护栏。
把所有知识塞进一个大文件
超长说明文件很容易把重点冲淡。
我现在更喜欢“入口索引 + 按需读取”这套方式:入口文件只写关键规则,再把更细的内容拆到别的文档、脚本说明和测试说明里。这样既省上下文,也更不容易漏关键约束。
只盯着模型升级
更强的模型当然重要,但可靠性不能只靠模型本身。
没有测试、没有沙盒、没有权限边界、没有人工闸门,再强的模型也可能在错误路径上高速前进。Harness 的价值,就是拿软件工程的方法,去对冲模型本身的不确定性。
不区分任务风险
改文案、补测试、修 lint、改数据库迁移脚本,这几件事的风险完全不是一个量级。
所以 Harness 最好按风险分级:低风险任务可以自动完成;中风险任务至少要跑验证;高风险任务必须人工确认;生产操作要有单独审批。
怎么判断 Harness 有没有用
看演示效果不太够,还是得看长期指标。
比较值得盯的,有这些:
- 任务解决率:AI 在少干预情况下完成任务并通过验证的比例;
- 首次通过率:第一次修改就过测试的比例;
- 返工率:合并后还要人工二次修的比例;
- 无关变更率:一次任务里混进不相关改动的比例;
- 验证覆盖率:关键路径有没有自动化检查兜底;
- 人工中断次数:高风险动作有没有被正确拦住。
这些指标能帮你判断,问题到底出在模型、上下文,还是 Harness 本身的约束和反馈设计。
harness发展的两个方向
- 内化到模型里
- 内化到编程工具里
结语
如果让我用一句话概括我现在对 Harness Engineering 的理解,大概就是:
每当你发现 Agent 犯了一个错误,你就花时间设计一个解决方案,使 Agent 永远不再犯同样的错误。——Harness Engineering
这句话我很喜欢,因为它一下子把重点说透了。
按这个思路做,就不能把希望寄托在模型下一次“自己聪明一点”上。出了问题也别只盯着这一次修补,最好顺手把护栏补上。
比如这次是上下文没给够,那就补检索和项目地图;这次是改动越界了,那就补权限和审批;这次是测试过不了还硬说完成,那就补验证回路和收敛条件。
也就是说,Harness Engineering 想做的,是把错误慢慢沉淀成系统能力,别让同一类问题反复重演。
所以我越来越觉得,未来程序员的工作不会只是“自己写代码”,还会越来越多地变成下面这些事:
- 设计任务边界;
- 编写项目规则;
- 维护验证体系;
- 建立自动化反馈;
- 审查 AI 无法自证的部分。
AI 负责把速度拉起来,人负责守住工程确定性。
当 AI 写代码的速度已经快到人很难逐行盯完时,真正让人安心的,往往是你有没有能力把它犯过的错,持续变成下一次不会再掉进去的工程护栏。
参考资料
- 本地参考稿:《AI Harness 工程详解与实践》
- 知乎参考链接:https://zhuanlan.zhihu.com/p/2021716359613032366
- LangChain Blog: The rise of context engineering
- Agents Cookbook: Harness engineering
- Thoughtworks: Patterns for building effective AI coding assistants
版权声明: 本文首发于 指尖魔法屋-Harness Engineering 的介绍与实践(https://blog.thinkmoon.cn/post/993_harness-engineering%E7%9A%84%E4%BB%8B%E7%BB%8D%E4%B8%8E%E5%AE%9E%E8%B7%B5/) 转载或引用必须申明原指尖魔法屋来源及源地址!
