目录

一、Harness 工程到底是什么?

二、Prompt、Context 和 Harness 有什么区别?

三、一个完整 Harness 通常包含什么?

四、从 0 搭建一个代码 Agent Harness

第一步:建立项目结构

第二步:编写 AGENTS.md

第三步:定义一个具体任务

第四步:加入自动检查脚本

第五步:规定 Agent 的执行循环

五、如何处理长任务?

六、如何让 Agent 自己发现错误?

七、Agent 反复犯错时怎么办?

八、如何建立评估集?

九、Harness 工程的五条实践原则

总结


最近 AI 圈出现了一个新词:Harness Engineering,通常翻译为 Harness 工程,也有人称为“驾驭工程”。

这个词听起来很新,但它解决的问题其实非常现实:

为什么同样使用 GPT、Claude 或 Codex,有些 Agent 能连续完成复杂任务,有些 Agent 却经常跑偏、忘记目标、乱调用工具,最后还无法判断自己到底做没做对?

很多时候,问题不只在模型,而在模型外面的那套运行环境。

这套运行环境,就是 Harness。

一、Harness 工程到底是什么?

Harness 原本指的是马具或缰绳。

马本身有力量,但如果没有缰绳、路线、障碍和骑手,它的力量并不能稳定地服务于目标。

AI Agent 也是一样。

模型可以理解语言、生成代码、调用工具,但它并不知道:

当前任务的边界是什么;

哪些工具可以使用;

每一步应该先做什么;

什么结果才算成功;

失败之后应该如何恢复;

上一次执行留下的状态在哪里。

Harness 工程,就是围绕 Agent 建立一整套“让它看得准、做得对、错了能恢复”的工程系统。

一个实用的定义是:

Harness 工程 = 提示词 + 上下文 + 工具 + 任务编排 + 状态管理 + 评估 + 约束与恢复

它不是某个框架,也不是一个固定产品,而是一种设计 Agent 的方法。

二、Prompt、Context 和 Harness 有什么区别?

这三个概念不是互相替代,而是范围逐步扩大。

Prompt Engineering 解决的是:

怎么把任务讲清楚,让模型理解你的要求。

例如:

你是一个 Python 工程师,请修复登录接口的参数校验问题,并保留现有 API 格式。

Context Engineering 解决的是:

怎么把模型需要的信息送到它面前。

除了任务本身,模型还需要知道:

项目目录结构;

相关代码;

接口文档;

测试结果;

团队规范;

历史执行状态。

Harness Engineering 解决的是:

怎么让模型在真实环境中连续完成任务,并且能被验证和纠错。

简单来说:

Prompt 是把话说清楚。

Context 是把资料准备好。

Harness 是把整个工作流程搭起来。

三、一个完整 Harness 通常包含什么?

一个实用的 Harness,至少可以拆成六层。

第一层:上下文管理

决定当前这一轮应该给模型看什么。

不要每次都把整个项目、所有规则、全部历史记录塞进上下文,而是按照任务动态加载。

第二层:工具系统

决定 Agent 能使用哪些工具。

例如:

读取文件;

搜索代码;

运行测试;

查看 Git diff;

调用接口;

发送消息。

工具不是越多越好。工具越多,Agent 越容易误用。

第三层:任务编排

规定 Agent 应该按照什么顺序工作。

例如:

先读需求;

再分析代码;

然后制定计划;

接着修改代码;

运行测试;

根据测试结果修复;

最后汇报结果。

第四层:状态与记忆

决定任务完成到一半后,下一轮如何继续。

任务状态不要只放在上下文里,而应该写入文件、数据库或任务系统。

第五层:评估与观测

决定如何判断 Agent 做得好不好。

不能只看 Agent 自己说“任务完成”,而要看测试、日志、输出格式和业务指标。

第六层:约束与失败恢复

限制 Agent 的危险行为,并为常见失败准备恢复路径。

例如:

限制修改目录;

限制工具调用次数;

禁止直接删除生产数据;

API 限流后自动重试;

任务超时后保存进度;

失败后从上一个检查点继续。

四、从 0 搭建一个代码 Agent Harness

下面用一个代码项目举例。

目标是:

让 Agent 为项目添加一个新功能,并且必须经过测试、代码检查和结果验收。

第一步:建立项目结构

在项目根目录增加以下文件:

project/
├── AGENTS.md
├── progress.md
├── tasks/
│   └── task-001.md
├── scripts/
│   └── check.ps1
└── evals/
    └── cases.md

这些文件分别负责:

AGENTS.md:项目规则和工作流程。

progress.md:任务进度和交接信息。

tasks/task-001.md:当前具体任务。

scripts/check.ps1:自动检查代码。

evals/cases.md:评估 Agent 是否完成任务。

第二步:编写 AGENTS.md

示例内容:

# 项目开发规则
​
1. 修改代码前,先阅读当前任务文件和相关模块。
2. 先给出简短实现计划,再开始修改。
3. 不要修改任务范围之外的文件。
4. 修改完成后必须运行 scripts/check.ps1。
5. 测试失败时,先分析错误原因,再继续修改。
6. 不要删除已有测试。
7. 最终报告必须包含:
   - 修改了哪些文件
   - 运行了哪些检查
   - 检查结果是什么
   - 仍然存在什么风险
8. 每完成一个阶段,就把进度写入 progress.md。

注意,这个文件不应该写成项目百科全书。

只放最重要的规则,详细规范可以拆到 docs 目录中,需要时再读取。

第三步:定义一个具体任务

tasks/task-001.md:

任务:为用户模块增加邮箱格式校验。
​
要求:
​
1. 只修改用户模块相关代码。
2. 邮箱为空时返回明确错误。
3. 邮箱格式错误时返回明确错误。
4. 增加至少两个测试用例。
5. 不改变已有接口返回结构。
6. 完成后运行项目测试和代码检查。

任务越具体,Agent 越不容易跑偏。

不要只写:

“优化一下用户模块。”

应该写清楚:

改什么;

不改什么;

成功标准是什么;

如何验收。

第四步:加入自动检查脚本

如果项目使用 Node.js,可以创建 scripts/check.ps1:

$ErrorActionPreference = "Stop"
​
npm test
​
npm run lint
​
git diff --check
​
Write-Host "All checks passed."

如果是 Python 项目,可以替换为:

$ErrorActionPreference = "Stop"
​
python -m pytest
​
ruff check .
​
git diff --check
​
Write-Host "All checks passed."

关键不在于具体命令,而在于:

不要只告诉 Agent “请认真检查”。

要给它一个可以真实执行的检查入口。

第五步:规定 Agent 的执行循环

给 Agent 的工作流程可以固定为:

1. 阅读 AGENTS.md。
2. 阅读当前任务文件。
3. 阅读 progress.md。
4. 搜索相关代码和测试。
5. 输出实现计划。
6. 修改代码。
7. 运行 scripts/check.ps1。
8. 如果失败,分析错误并修复。
9. 再次运行检查。
10. 更新 progress.md。
11. 输出最终修改说明。

这比一句“帮我完成这个功能”稳定得多。

因为 Agent 不仅知道目标,还知道工作顺序和验收方式。

五、如何处理长任务?

长任务最容易出现两个问题:

第一,Agent 忘记最初目标。

第二,上下文越来越长,模型开始忽略早期信息。

解决方法是把状态写到文件里,而不是只留在对话中。

progress.md 可以这样写:

任务:增加邮箱格式校验
​
已完成:
- 找到用户模块入口
- 找到参数校验类
- 增加了邮箱为空的测试
​
进行中:
- 增加邮箱格式错误测试
​
待完成:
- 运行完整测试
- 检查接口返回结构
- 更新任务说明
​
遇到的问题:
- 当前项目使用统一异常处理,不能直接返回字符串

下一轮 Agent 开始时,先读取 progress.md,就能知道自己目前做到哪一步。

如果任务很长,还可以采用“分轮执行”:

第一轮:分析和规划。

第二轮:实现主要功能。

第三轮:补充测试。

第四轮:运行检查和修复。

每一轮都使用新的上下文,但通过文件保存任务状态。

这比让一个 Agent 在同一个超长对话里连续工作更稳定。

六、如何让 Agent 自己发现错误?

不要让执行 Agent 自己给自己打分。

一个更可靠的流程是:

规划 Agent:拆解需求
执行 Agent:修改代码
验收 Agent:运行测试和检查
修复 Agent:根据失败结果修改
再次验收

即使不使用多个模型,也可以把执行和验收分成两个独立阶段。

例如:

执行阶段只负责修改代码。

验收阶段只负责:

运行测试;

检查接口;

查看 Git diff;

验证输出格式;

确认是否满足任务要求。

验收必须尽量接近真实使用场景。

例如,做前端 Agent 时,不能只检查代码有没有语法错误,还要真正打开页面、点击按钮、提交表单,确认功能能用。

七、Agent 反复犯错时怎么办?

最重要的一条原则是:

不要只在提示词里提醒 Agent。

应该把解决方案沉淀到项目环境中。

例如,Agent 总是忘记运行测试:

错误做法:

“请注意,修改后一定要运行测试。”

更好的做法:

把测试写进 scripts/check.ps1,并规定任务完成前必须执行这个脚本。

再比如:

Agent 总是使用错误的代码格式。

可以增加:

代码格式检查;

Lint 规则;

提交前 Git Hook;

自动化测试;

类型检查。

Agent 每犯一次错误,环境就变强一点。

这就是 Harness 工程最重要的“复利效应”:

Agent 犯错
→ 找到原因
→ 把修复写入规则、测试或工具
→ 下一次自动避免
→ Harness 持续增强

八、如何建立评估集?

如果没有评估集,你只能凭感觉判断 Agent 是否变好了。

可以从过去真实任务中挑选 10 到 20 个案例,记录:

任务描述;

正确修改的文件;

预期测试结果;

不能修改的内容;

最终应该输出什么。

例如:

案例 1:
任务:增加邮箱格式校验
必须修改:user/service.py、tests/test_user.py
禁止修改:payment 模块
必须通过:python -m pytest

每次修改 Harness 后,都重新运行这些案例。

关注以下指标:

任务完成率;

测试通过率;

越权修改率;

平均执行轮数;

工具调用失败率;

人工返工时间。

这样才能知道改动到底有没有效果。

九、Harness 工程的五条实践原则

第一,状态外置,不要依赖模型记忆。

第二,执行和验收分离,不要让 Agent 自己当裁判。

第三,失败要沉淀成规则、测试或工具。

第四,规则文件保持简短,详细内容按需加载。

第五,技术债持续偿还,不要等到项目失控后再集中清理。

总结

Prompt Engineering 解决的是“怎么把任务讲清楚”。

Context Engineering 解决的是“怎么把正确资料送给模型”。

Harness Engineering 解决的是“怎么让 Agent 在真实环境中持续做对”。

真正可落地的 Harness,不是一个复杂的名词,而是一套可以执行的工程机制:

有明确任务;

有可控工具;

有固定流程;

有外部状态;

有自动检查;

有评估数据;

有失败恢复。

如果你正在使用 Codex、Claude Code、Cursor 或其他编程 Agent,不要只花时间修改提示词。

先从这几件小事开始:

建立 AGENTS.md;

建立任务文件;

加入自动检查脚本;

保存 progress.md;

整理一组真实评估案例。

这就是 Harness 工程最简单、也最有效的起点。

更多推荐