Harness Engineering 是什么:从提示词到驾驭工程的演化路径
2023 年大家在背"如何写好提示词",2025 年所有人在讨论"上下文工程",2026 年 OpenAI 又抛出了一个新词——Harness Engineering(驾驭工程)。
每隔一段时间这个领域就出现一个新名词,初看像是炒概念,但仔细看其实是工程边界在不断外扩:从最早只关注怎么和模型对话(一句话),到组织信息(一段上下文),再到把模型嵌入完整的执行循环(一整套外壳)。
这篇文章把这条演化路径梳理清楚——三个名词之间到底是什么关系、各自解决什么问题、Claude Code 这类 Coding Agent 又是怎么把它们落地的。
起点:大模型本身是什么
把 ChatGPT、Claude、DeepSeek 这些产品的外壳全部拨开,核心就是一个大模型(LLM)——本质上是磁盘上的一个超大参数文件。
| 你看到的 | 实际是 |
|---|---|
| ChatGPT 网页 | 大模型 + 聊天界面 |
| OpenAI API | 大模型 + HTTP 接口 |
| Claude Code | 大模型 + 终端 + 文件系统 + MCP |
| Cursor | 大模型 + 代码编辑器 + 项目索引 |
模型本身做的事情只有一件:基于当前输入,预测下一个 token。它是一个超高维度的"猜词机器"——给它前文,它给出最可能的接续。
这个特性带来一个根本问题:它不知道你真正想要什么,只能根据输入推测。指令越宽泛,输出越发散。
例如丢一段代码上去说"加个排序",可能拿到的就是一个孤立的排序函数,原来的代码结构全没了。但如果说"在不改动其他逻辑的前提下,给以下完整函数加上按 created_at 倒序的逻辑,给我修改后的整段代码",结果就准确得多。
这就是后续所有工程的起点:怎么让"猜词机器"稳定地猜中你的意图。
第一层:提示词工程(Prompt Engineering)
提示词工程是最早被讨论的方向。它的核心动作是:在输入里显式写清楚约束。
一个最小提示词的解剖
每一行都在做一件事——把模型猜测的范围越收越窄。
提示词的常见构成
| 组件 | 作用 | 示例 |
|---|---|---|
| 角色设定 | 限定回答风格和深度 | "你是一名 SRE,擅长 K8s" |
| 任务描述 | 主目标 | "帮我排查这个 OOM 问题" |
| 背景信息 | 现状 | "服务跑在 EKS 上,4GB limit" |
| 输入数据 | 处理对象 | 日志、代码、表格 |
| 输出格式 | 结构限制 | JSON / Markdown / 代码块 |
| 边界约束 | 禁止行为 | "不要给推测,只给事实" |
| 示例(few-shot) | 引导风格 | 一两条示范输入输出 |
提示词工程的边界在哪里
它解决了 模型"无引导乱说话"的问题——但这是不够的。
只有提示词时,每次对话都是孤立的:模型不知道你之前发生了什么,不知道项目结构是什么,不知道刚才的代码改完之后报了什么错。换句话说,提示词只能塞静态信息。一旦任务复杂,光靠手写提示词撑不住。
第二层:上下文工程(Context Engineering)
提示词写得再好,模型本身只能看到一次输入。当任务涉及多轮对话、多文件代码库、动态环境时,光有提示词不够——你要把所有相关信息都给它。
上下文 = 比提示词大的概念
提示词只是上下文的一部分,真正喂给模型的是整个上下文。
上下文窗口与上下文腐化
模型一次能"看"的总信息量叫 上下文窗口:
| 模型 | 上下文窗口 |
|---|---|
| GPT-3.5(早期) | 4K tokens |
| GPT-4 Turbo | 128K |
| Claude Sonnet 4 | 200K |
| Claude Opus 4.7 | 1M |
| Gemini 2.5 Pro | 2M |
看起来越来越大,但实际工程中很容易打满——一份大型代码库读几个文件就上万 token,几轮工具调用结果一塞,窗口立刻见底。
打满之后只有两条路:压缩(让模型自己总结历史对话)或 丢弃(直接截断旧消息)。无论哪种,都会带来 上下文腐化(Context Rot):
- 早期信息被压缩成一句概括,细节丢了
- 关键约束被截断,模型忘了"不要改 schema"这种铁律
- 历史决策的因果链断裂,模型重复犯同样的错
表现就是模型越聊越不准、自相矛盾、忘记初始目标。
上下文工程的三个动作
为了对抗上下文腐化,做的事可以归纳为三步:
1. 召回(Retrieve)
从历史对话、代码库、报错日志、文档库中,找出当前任务最相关的信息。RAG(Retrieval-Augmented Generation)就是召回的典型实现。
2. 压缩(Compress)
不是简单截断,而是结构化压缩。例如:
- 把 50 轮对话总结成 10 行决策记录
- 把整个文件读取压成"这个文件定义了 X 类,主要方法是 Y"
- 把 5000 字日志提炼成"OOM at line 42, root cause: 缓存未释放"
3. 组装(Compose)
调整顺序,越关键的越靠近末尾——模型对最近的内容注意力最高(这是 transformer 架构的固有特性,叫"recency bias")。
经典的上下文组装顺序:
提示词工程是上下文工程的子集:手写提示词只解决了"系统提示词"那一层,上下文工程把整个动态信息流都纳入了管理。
不同 AI 工具的上下文策略差异
同一个 GPT-4 / Claude,套在不同壳里效果差异巨大:
| 工具 | 上下文策略特点 |
|---|---|
| Cursor | 项目级 embedding 索引,问什么搜什么 |
| Claude Code | 终端原生,主动 read 文件,工具结果直接进上下文 |
| Trae | 类似 Cursor,强调多文件编辑场景 |
| WorkBuddy | 工作流编排,记忆/技能注入 |
不是模型谁强谁弱——是外壳的上下文工程谁做得好。
第三层:Harness Engineering(驾驭工程)
到这一步,模型还只能"聊天"——它能理解上下文,能给出建议,但不能自己动手。
要让它真正"干活",就得给它配上手脚。
给模型加上执行能力
把这些能力插到模型身边:
| 能力 | 干什么 |
|---|---|
| Bash 沙箱 | 执行 shell 命令 |
| 文件系统 | 读写文件、创建目录 |
| HTTP 客户端 | 调用 API、抓取网页 |
| MCP(Model Context Protocol) | 标准化的外部工具协议 |
| 代码执行环境 | 跑测试、跑 lint |
| 浏览器自动化 | 真实浏览器交互 |
这些统称为执行层(Execution Layer)。模型决定"做什么",外壳负责"怎么做"。
ReAct 循环:思考 + 行动
把执行层和模型串成循环就是 ReAct(Reason + Act):
这就是所有 AI Agent 的本质骨架——一个永不停止的"思考-行动"循环。
但循环一长就出问题
ReAct 的副作用:循环越长,上下文膨胀越快。即使上下文工程做得好,也敌不过 50 轮工具调用的累积。表现:
- Agent 写到第 30 步,忘了最初的需求
- 看了太多代码后,"哪个是入口"开始混乱
- 最早的禁止事项被压缩淘汰,开始干被禁止的事
光靠上下文工程压缩还不够——需要把核心信息"钉"在每次调用里。
Harness 的四层架构
到这里完整的 Harness Engineering 浮出水面,由四层组成:
执行层(Execution)
让模型"动手"。具体是文件系统、Bash、HTTP、浏览器、MCP——上一节讲过了。
反馈层(Feedback)
执行不可能一帆风顺,报错就是 Agent 的眼睛。反馈层把错误信息正确回流给模型:
好的反馈层不是简单贴报错——还要:
- 过滤噪声(堆栈里 90% 是 node_modules,丢掉)
- 突出关键(加一段"上次执行的关键失败点")
- 提供环境信号(操作系统、Node 版本、文件存在与否)
记忆层(Memory)
把项目核心信息单独成文件,每次调用都注入。这就是 Claude Code 的 CLAUDE.md、Cursor 的 .cursorrules、Workbuddy 的 MEMORY.md:
记忆层的关键:轻量、可扩展、按需加载。如果文件太大可以拆:
入口里写"涉及部署看 deploy.md",模型按需读取,不是一开始就把 50KB 都塞进上下文。
编排层(Orchestration)
最上面这层管"先做什么、再做什么"。没有它,Agent 拿到大需求会漫无目的或陷入死循环。
编排层做三件事:
| 动作 | 例子 |
|---|---|
| 拆解 | "实现登录功能" → ① 设计 schema ② 后端接口 ③ 前端表单 ④ 单元测试 |
| 验收标准 | 每个子任务都有"做完什么样算完" |
| 顺序控制 | 数据库 schema 必须先于接口实现 |
这就是 Spec-Driven Development(SDD,规范驱动开发) 的核心——先把规范写清楚,再让 Agent 按规范分步做。
公式与因果
把所有这些放到一起,OpenAI 给的公式是:
而 Harness Engineering 又分四层:
进一步拆,三个工程之间的关系是这样的:
| 工程 | 处理对象 | 解决问题 |
|---|---|---|
| 提示词工程 | 单次输入的措辞 | 模型听不懂指令 |
| 上下文工程 | 整个输入的组织 | 信息塞不下、塞不准 |
| 驾驭工程 | 模型外的整套循环 | 模型不能持续干活 |
每一层都不取代前一层,而是包住前一层。
实战:用 Claude Code 落地四层 Harness
Claude Code 是目前最贴近"开箱即用 Harness"的 Coding Agent,四层都有原生支持。
最小落地:写好一个 CLAUDE.md
只需要在项目根目录创建一个 CLAUDE.md:
每次和 Claude Code 对话,这个文件会自动作为系统提示词注入——这就是记忆层。
进阶:引入 Spec-Kit 等编排插件
手写计划繁琐,可以用 Spec-Kit 这类插件——它会强制把开发拆成三个阶段:
| 阶段 | 产出 |
|---|---|
| Specify | 一份明确的需求约束文件(spec.md) |
| Plan | 一份分步计划(plan.md) |
| Execute | 边改代码边加测试 |
每个阶段结束都更新 CLAUDE.md,保证下一阶段拿到的上下文都是最核心的精华。这就是编排层 + 记忆层的工程化落地,本质是 Spec-Driven Development。
反馈层基本是免费的
Claude Code 跑 npm run lint 失败时,stderr 自动回流到下一轮上下文,你什么都不用做。这是反馈层的标准配置。
执行层的扩展点
需要 Claude Code 操作 Notion / GitHub / Slack?装一个 MCP server:
执行层瞬间扩展。
几个常见误解
"提示词工程过时了"
不对。提示词是 Harness 的最内层——每个外层最终都要回到一个写得好的提示词上。它没过时,只是从"全部"变成了"一部分"。
"上下文工程就是 RAG"
RAG 只是召回这一步。上下文工程还包含压缩、组装、和大模型的交互节奏控制。
"Harness 等于 Agent 框架"
LangChain / LlamaIndex 这类框架确实在做 Harness 的事,但不是有 Agent 框架就有 Harness。手写一个有 CLAUDE.md + tool calling + 任务计划的 CLI 程序,也是完整的 Harness Engineering。
"模型一升级,Harness 就没用了"
恰恰相反。模型越强,Harness 的价值越大——一个会写代码的模型 + 强 Harness = 真能交付的 Agent;一个会写代码的模型 + 没 Harness = 只能聊天给建议。
给开发者的落地清单
如果你正在搭一个 Agent,按这个顺序走:
- 先写好提示词模板——明确角色、任务、输出格式、边界
- 加一个项目规则文件(CLAUDE.md / .cursorrules)——记住核心约束
- 接入工具调用——文件读写、Bash、HTTP,最少这三样
- 设计反馈回路——错误必须能回到下一轮上下文
- 加任务拆解——大任务必须能被拆成有验收标准的小步
- 观察上下文窗口使用率——超过 60% 就要考虑压缩或分阶段
- 做评测——每轮迭代用真实任务跑通过率,不要只看"看起来对"
总结
三个名词不是互相替代,而是工程边界一层层向外扩:
| 时代 | 关键能力 | 关键产物 |
|---|---|---|
| 2023 | 提示词工程 | 一句好指令 |
| 2025 | 上下文工程 | 一个组织好的输入 |
| 2026 | 驾驭工程 | 一套能持续交付的外壳 |
公式:
回到一句最简单的总结:
- 提示词工程:让大模型明白具体需求和输出标准
- 上下文工程:给大模型注入精准、有效的上下文
- 驾驭工程:让大模型持续按规范执行任务并最终交付
下一个名词大概率会出现在 Multi-Agent 协作领域——但底层逻辑不变:模型负责思考,工程负责一切其他。