Harness 与上下文工程:Harness 工程和提示词、上下文工程有什么区别
提示词工程改进单次请求的表述,上下文工程决定每一步哪些信息进入模型的窗口,Harness 工程则搭建智能体的整个环境:指令、工具、运行环境、跨会话状态和反馈回路。前两者在单次模型调用内部起作用,Harness 则作用于整个系统和长时间任务,关键不是回答本身,而是经过验证的结果。
简而言之:同一任务的三个层次
提示词工程回答“如何提问”,上下文工程回答“模型此刻需要知道什么”,Harness 工程回答“智能体在什么环境中工作,以及它如何得知自己出了错”。这三者不是互相竞争的方法,而是逐层嵌套的:好的提示词是好的上下文的一部分,而精心设计的上下文又是 Harness 的一个子系统。
三者容易被混淆,是因为它们都会改变模型的行为,但杠杆不同。如果智能体无法运行测试,任何措辞的提示词都解决不了这个问题。如果智能体忘记了昨天的决定,问题不在于请求的文字,而在于状态存放在哪里。弄清 harness vs context engineering 的区别,能为你节省数周时间:你不会再去改写本该修复环境的指令。
提示词工程:单次请求的表述
提示词工程处理的是请求文本:角色、任务、输出格式、示例(few-shot)、约束、步骤顺序。工作单元是一次模型调用。结果通过回答来评估:是否正确,格式是否符合要求,模型是否跑偏。
常用手法包括:
- 明确描述输出格式(JSON 结构、表格、列表);
- 给出 2 到 3 个“输入 → 正确输出”的示例;
- 要求模型在回答前逐步推理;
- 用清晰的分隔符区分指令和数据;
- 列出不能做的事情。
提示词工程适合“一个输入、一个输出”的任务:分类、信息抽取、翻译、按模板生成文本。当模型开始行动——调用工具、修改文件、连续执行几十个步骤——它的天花板就显现出来了。此时质量取决于的已经不是某一句话,而是围绕模型的整个环境。
上下文工程:什么进入模型的窗口
上下文工程是在每一步管理上下文窗口的内容。窗口是有限的,而智能体在长会话中会不断积累命令输出、文件内容和对话历史。目标是:在每一时刻,窗口里有需要的东西,没有多余的东西。
它包括:
- 筛选:根据任务加载哪些文件、文档和代码片段(搜索、RAG、按需读取);
- 压缩:总结冗长的历史,截断命令输出,压缩会话;
- 结构:把入口指令文件当作目录,把细节放在需要时才打开的独立文档中;
- 隔离:把子任务交给拥有独立干净上下文的子智能体,避免主线程被污染。
上下文工程的衡量标准是:智能体是否在需要的时刻找到了正确的规则或事实,是否被噪声淹没。典型症状是:规则明明写在 CLAUDE.md 里,智能体却违反了它,因为文件有五页长,规则淹没在语气要求和团队负责人偏好的风格之中。
Harness 工程:模型周围的一切
Harness(“驾驭”)是智能体工作的环境。模型只是其中的一个组件,在回路中出现一次。其余的一切——指令、工具、环境、状态和反馈——都由工程师设计。Harness 工程负责让智能体不仅能写代码,还能运行它、验证它、得知错误,并在下一次会话中从原来的位置继续。
可以把 Harness 分解为五个子系统:
| 子系统 | 包括什么 | 失效的迹象 |
|---|---|---|
| 指令 | AGENTS.md / CLAUDE.md、skills、文档、架构决策记录 | 智能体违反了“人人都知道”的约定 |
| 工具 | shell、测试、代码检查器、调试器、浏览器、MCP 服务器 | 智能体“想做却做不了”:没有所需命令的访问权限 |
| 环境 | 依赖锁文件、运行时版本、Docker/devcontainer、git worktree、沙箱 | 每个会话都从修复环境开始 |
| 状态 | PROGRESS.md、feature_list.json、DECISIONS.md、git 历史 | 新会话不知道上次停在哪里 |
| 反馈 | make check、端到端测试、钩子、评分标准、独立评估者 | “完成”与实际情况不符 |
上下文工程存在于前两个子系统之中:它决定指令和工具输出如何进入窗口。而 Harness 增加的是那些无法放进上下文的东西:可运行的验证命令、可复现的环境、能在重启后保留下来的状态文件。
对比表
| 维度 | 提示词工程 | 上下文工程 | Harness 工程 |
|---|---|---|---|
| 工作单元 | 一次请求 | 每一步的模型窗口 | 整个系统:智能体、仓库、环境、流程 |
| 改变的是什么 | 请求文本 | 窗口中信息的构成与顺序 | 工具、环境、状态存储、检查 |
| 时间跨度 | 几秒 | 一次会话 | 多次会话,数小时到数天 |
| 衡量什么 | 回答的质量 | 智能体是否找到所需信息,窗口是否溢出 | 真正做到可工作状态的任务比例;“完成”与验证之间的差距 |
| 典型产物 | 系统提示词、示例 | 文档结构、RAG、压缩、子智能体 | AGENTS.md、验证脚本、钩子、Docker、feature_list.json、PROGRESS.md |
| 谁来检验结果 | 人阅读回答 | 人或模型 | 机器:测试、代码检查、端到端测试、独立评估者 |
| 何时触及天花板 | 模型开始行动时 | 智能体缺的是能力而不是知识时 | 任务需要人来做决定(产品、风险)时 |
为什么只靠提示词和上下文不够
经典的情形是:团队发现智能体总出错,于是花一周写了一份五页的 AGENTS.md。智能体依然不会在提交前运行代码检查器。原因不在文字:智能体根本没有带正确权限的 shell 访问,镜像里也没有装代码检查器。这是工具和环境的问题,却试图用指令来修复。
第二种情形是:智能体连续第三次会话修同一个 bug,因为每次重启后它都不记得自己试过什么。会话内部的上下文工程帮不上忙:窗口已被清空。需要的是状态子系统:一个让智能体记录尝试和决定的文件,以及开始工作时必须读取它的规则。
第三种情形代价最大:智能体报告“完成”,单元测试全部通过,但功能并不工作。无论是“仔细检查”这样的提示词,还是在上下文里多塞几份文档,都不能给智能体独立的验证。能提供这种验证的,只有来自机器的反馈:端到端测试、验证脚本,或者一个不能看到执行者推理的独立评估者。
总结:提示词和上下文影响的是模型会想什么。Harness 影响的是模型能做什么,以及行动之后它知道什么。
为什么换一个模型也没用
面对不稳定的智能体,常见的反应是换一个更强的模型。通常这并不能解决问题:同一个模型,在组织良好的仓库里像自信的资深工程师,在没有验证命令和技术栈说明的仓库里却会迷失方向。更强的模型猜不到你团队的约定,也无法访问它没有权限访问的数据库,更不会知道迁移已经坏了,除非有人运行过它。
Harness 也不会随着新模型的发布而过时。指令、可复现的环境和检查对任何模型都有用。变化的只是:可以省去多少手把手的指导。强模型只需要不变量(“数据在领域边界处校验”),而不需要逐步的指示。
如何判断该修哪一层
根据症状诊断,比任何实验都快:
| 症状 | 问题所在 | 怎么做 |
|---|---|---|
| 回答格式错误,模型没理解任务 | 提示词 | 明确格式,添加示例 |
| 规则写了,但智能体没有应用 | 上下文 / 指令 | 把入口文件精简为目录,细节移到按需加载的文档,关键规则改为检查 |
| 会话进行到中途,智能体“忘记”早先的决定 | 上下文 | 压缩、用子智能体处理旁支任务、把内容写入状态文件 |
| 智能体说“无法运行” | 工具 | 开放命令访问权限,接入 MCP 服务器,调整权限 |
| 每个会话都从安装依赖、修环境开始 | 环境 | 锁文件、Docker/devcontainer、初始化脚本 init.sh |
| 新会话反复问“昨天做了什么” | 状态 | PROGRESS.md、带状态的功能列表、检查点提交 |
| “完成”了,但功能不工作 | 反馈 | 端到端测试、完成定义(DoD)、验证脚本、独立评估者 |
从哪里开始搭建 Harness
从零开始时,合理的顺序是:反馈 → 指令 → 状态 → 环境 → 工具。反馈排第一,因为没有它就无法衡量其他改动的效果。在没有一条命令能诚实地回答“能不能用”之前,对指令的任何改进都只能凭感觉评价。
最小起步版本如下:
# AGENTS.md(节选)
## 如何验证
- make check # 代码检查、类型、单元测试
- make e2e # 端到端场景
只有两条命令都以退出码 0 结束,功能才算完成。
## 规则
- MUST:所有 SQL 查询都必须参数化
- MUST:提交前运行 make check
- 支付细节:docs/payments.md(涉及支付的任务才阅读)
注意最后一行:这就是 Harness 内部的上下文工程。入口文件是地图,不是教科书;细节按“什么时候”的条件加载。
如何衡量每一部分的贡献
Harness 有一个提示词没有的指标:智能体宣布完成、但独立检查未能确认的任务比例。这叫做 verification gap(验证差距)。拿 10 个连续的任务,每个任务记录智能体是否宣布“完成”,以及验证是否通过,就能得到一个可以用来比较改动的数字。
要判断哪个子系统真正起作用,可以使用消融实验:固定模型和任务集,每次关闭 Harness 的一个部分,观察性能下降多少。需要记住两点。首先,不要把消融实验作为第一步,而应先用失败日志找到瓶颈,消融实验只用来验证。其次,关闭某个组件后没有下降,并不说明它没用,可能只是这组任务没有用到它。
常见错误
- 把 Harness 等同于提示词文件。指令只是五个子系统之一。货架上的菜谱,并不等于厨房。
- 用文字弥补缺失的工具。“一定要运行测试”没有用,如果智能体的环境里根本无法运行测试。
- 无限膨胀指令。入口文件越长,重要规则被忽略的概率越高。重要的规则应当变成可执行的检查。
- 相信智能体的自我报告。自己评估自己工作的模型,往往会高估结果。检查应由脚本或拥有干净上下文的独立智能体完成。
- 只配置一次 Harness。它会像代码一样过时:规则与现实脱节,命令发生变化。需要定期审查。
总结
提示词工程改进表述,上下文工程筛选模型窗口中的信息,Harness 工程则覆盖智能体的整个环境,包括工具、运行环境、状态和检查。当智能体长时间工作、自己修改代码时,Harness 变得最为关键:它把“智能体说完成了”变成“系统确认它能用”。因此 harness vs context engineering 并不是二选一:上下文是 Harness 的一部分,应当修复症状所指向的那一层。这一主题在 Harness 工程课程中,通过一个支付后端的实际项目进行了讲解。
常见问题
Harness 工程会取代提示词工程吗?
不会,它把提示词工程包含在内。指令的措辞依然重要,但它只是五个子系统之一,另外还有工具、环境、状态和反馈。
如果我只用智能体做小修改,还需要 Harness 吗?
最低限度的 Harness 总是需要的:一个写有技术栈和验证命令的指令文件。完整的一套(功能列表和评估者)则在长任务和团队协作中才能回本。
上下文工程和 RAG 有什么区别?
RAG 是上下文工程的一种手段,即检索并加载相关片段。上下文工程的范围更广,还包括历史压缩、文档结构设计,以及在子智能体中隔离子任务。
应该先搭建 Harness 的哪一部分?
反馈:一条能机器化地判断结果是否可用的命令。没有它,其他改进的效果就无法衡量。
Harness 工程只适用于 Claude Code 吗?
不是。原理是通用的:AGENTS.md 被许多智能体读取,验证脚本、Docker、状态文件和端到端测试也不依赖于某个具体工具。
课程“Harness Engineering: инженерия надёжности AI-агентов”结合实践详细讲解了这一主题。
- Что такое harness engineering: почему AI-агент ломается из-за среды, а не модели
- Из чего состоит harness AI-агента: инструкции, инструменты, среда, состояние, обратная связь