同步至个人站点:Harness 工程:不是新词,而是 Agent 工程终于被讲明白了
最近 Agent 圈突然开始密集讨论一个词:Harness。
但 Harness 不是新技术发明,它是 Agent 工程里那部分一直存在、但从未被完整命名的”软件工程现实”。OpenAI 在 2026 年 2 月的官方文章里基本就是这么描述的:工程师的工作正从”写代码”转向”设计环境、指定意图、建立反馈回路,让 agent 能可靠工作”。
我之前做 memo code、去高校做 Agent 开发交流时,一直在讲同一个判断:Agent 的核心 loop 本身不复杂,真正难的还是软件工程。Harness 就是把这件事具象化、命名了。
Harness 到底是什么?
先说我的定义:
Harness 不是模型。不是 Prompt。不是 Tool Call。不是框架。 Harness 是 Agent 运行时的“工程环境总和”。
这个“环境总和”里包含什么?
至少包括这几类东西:
- 任务如何被表达
- 上下文如何被组织
- 工具如何被暴露、治理、拦截
- 状态如何被保存、恢复、裁剪
- 反馈如何回流给模型
- 错误如何被分类、重试、升级
- 安全边界如何被建立
- 系统如何验证 agent 真的把事做好了
如果你把 Agent 想成一个“会调用工具的大脑”,那 Harness 就是:
你给这个大脑配的身体、传感器、护栏、操作台、流程制度、回执系统,以及出事后的保险。
所以我更愿意把它翻成:
Harness = 驾驭系统 或者更工程一点:
Harness = 让 Agent 能被稳定驾驭的环境系统
OpenAI 后续关于 Codex App Server 的文章也把这件事说得更具体:所谓 harness,不只是“用户-模型-工具”的核心 loop,还包括线程生命周期与持久化、配置和鉴权、工具执行与扩展、客户端与运行时之间的协议层。也就是说,真正的 harness 不是一个 prompt 文件,而是一个完整运行时。
为什么这个词现在突然火了?
因为行业终于开始承认:Agent 的问题,越来越不是”模型够不够聪明”,而是”环境够不够好”。
同一个模型,放到不同系统里,表现天差地别。有的 agent 乱调工具、丢上下文、踩穿安全边界、在长任务里越来越漂;有的 agent 却能持续做事、利用反馈修正自己、甚至让一个不算新的模型也表现得很像样。
我做 memo code 时故意没有把测试重心放在最新最强模型上,很长一段时间都在用一个发布将近一年的 DeepSeek 模型来测。原因很简单:
我想验证的不是”模型天赋有多高”,而是”环境设计能把一个普通模型托到什么程度”。
这也和近期公开的工程经验对齐。OpenAI 把重点放在 scaffolding、环境约束、反馈回路上;OPENDEV 那篇论文则关注安全控制、上下文压缩、记忆系统和事件驱动提醒。两边说法不同,但本质一致:Agent 的能力,不是模型能力,而是模型 × 环境。
Agent 的核心很简单,真正难的还是软件工程
Agent 的原理不复杂。抽象层面你甚至十几分钟就能写个最小版本——给模型一个 system prompt,给它几个 tools,让它在循环里不断决定”要不要继续做事”,这就已经是 agent 了。
但真正的问题是:一个 loop,为什么会在生产环境里烂掉?
答案通常不是因为模型突然变笨,而是这些工程问题集中出现:
- 上下文越来越脏
- 工具越来越多,但没有治理
- 状态没有结构化
- 安全边界靠”相信模型懂事”
- 错误没有归类,反馈不可消费
- 长任务没有阶段性 checkpoint
- 文档和规则堆成一坨,模型根本吃不动
这些问题全是软件工程问题,不是模型理论问题。Harness 这个词的价值就在这里:它提醒你,Agent 项目的真正主战场不是模型层,而是运行环境层。
Harness 和 Context Engineering 的区别是什么?
我看到不少讨论会把 Harness 和 Context Engineering 混在一起。
我觉得可以这样区分:
1)Prompt Engineering
关注的是:怎么说
比如 system prompt 怎么写,few-shot 怎么摆,措辞怎么调。
2)Context Engineering
关注的是:给模型什么信息
比如:
- 放哪些文档
- 怎么裁剪历史
- 怎么组织 AGENTS.md
- 怎么做记忆注入
- 怎么避免 context bloat
3)Harness Engineering
关注的是:模型在什么环境里做事
它比 Context 更大一层。
因为它不只管“喂什么”,还管:
- 什么时候能动手
- 动手时有哪些工具
- 工具是否需要审批
- 输出太长怎么办
- 危险操作怎么拦
- 会话如何恢复
- 中间产物如何持久化
- 任务失败后如何回路修复
- 客户端如何实时展示 agent 的状态
所以我会说:
Context Engineering 是 Harness 的一个组成部分,但 Harness 不等于 Context。
OpenAI 官方中文页里有一句话我很认同:情境是一种稀缺资源,巨大指令文件会挤掉任务、代码和相关文档,导致 agent 开始围绕错误约束优化。这个观察本身说的是 context,但他们整篇文章讲的解决方式,其实已经进入 harness 级别了:代码库结构、AGENTS.md、审阅回路、验证手段、仓库作为记录系统、熵管理。
从 memo 的实践看,Harness 具体长什么样?
如果让我用 memo code 的经验来拆,我会把 Harness 至少拆成五层。
第一层:上下文装配系统
很多人以为系统提示词就是一份大 Markdown。
其实不是。
在 memo 里,我更在意的是:提示词不是静态文档,而是动态拼装系统。
我在那篇《系统提示词架构解析》里把它拆成六层:
- 基础模板
- 用户偏好(SOUL.md)
- 项目上下文(AGENTS.md)
- Skills
- 工具描述
- 工具定义 JSON
这个拆法的关键不是“层多”,而是:
不同来源的信息,有不同优先级、不同新鲜度、不同职责。
它们不能全塞进一个大 prompt 里,然后指望模型自己理解层级关系。 你必须先在工程上把层级关系建好,再交给模型。
这就是 Harness。 因为你不是在“写提示词”,你是在“设计上下文的注入机制”。
第二层:工具治理系统
一个 agent 只要开始接工具,复杂度会立刻上升。
因为工具不是“多几个 function call”这么简单。工具系统背后至少有四个问题:
- 模型如何发现工具
- 参数如何校验
- 风险如何分级
- 调用如何被统一拦截
我在 memo 的工具系统设计里,把这件事拆成三层:
- 工具定义层:声明式 DSL
- 风险与审批层:read / write / execute / critical 分级
- 编排层:统一入参校验、审批拦截、结果裁剪、错误归类
这个设计的重点不是“优雅”,而是:
让工具调用成为一个可治理系统,而不是一堆裸奔接口。
很多 Agent 项目为什么一开始能跑,后来越来越不稳?
因为它们的工具系统不是“系统”,只是“工具列表”。
而 Harness 的一个核心任务,就是把工具从“模型可以调用的能力”提升成“可控、可审计、可演化的运行时能力”。
第三层:安全与审批系统
只要 agent 能写文件、跑 shell、改配置,它就不再是一个“聊天模型”。
它已经是一个操作系统参与者了。
这时候安全问题不是“以后再说”,而是第一天就存在。
我在 memo 的安全设计里,最后收敛成了三道防线:
- 子进程管理:会话池、数量限制、输出截断、超时终止、自动清理
- 命令守卫:命令解析、危险命令黑名单、system hint 回传
- 审批系统:风险分级、审批模式、指纹缓存、dangerous 模式兜底
这里最关键的一点是:
安全不能只靠模型自觉。
你不能把“请不要执行危险命令”写在 prompt 里,然后假装问题解决了。 真正的安全边界,必须落在运行时。
这也是 Harness 和很多“Demo Agent”的根本区别。
Demo 级别的 agent 靠的是“模型大概会听话”。 Harness 级别的 agent 靠的是“即便模型不听话,系统也有边界”。
第四层:反馈与状态系统
Agent 之所以能持续做事,不是因为它会一直“想”。
而是因为它会不断收到反馈。
比如:
- 工具执行结果
- 审批是否通过
- 输出是否被截断
- 查找结果是否过多
- 命令是否被拒绝
- 当前任务计划是否已更新
- 会话是否可恢复
在 memo 的 prompt 架构里,我专门用 XML system_hint 去承载一些异常状态,比如:
- 输出过长
- 查找结果过多
- 危险调用被拦截
很多人会觉得这只是“小技巧”。
但我不这么看。
这其实是 Harness 里非常重要的一件事:
你要把系统内部发生的事,翻译成模型能消费的反馈语言。
如果没有这层翻译,模型只能看到“失败了”。 而有了这层翻译,它才能理解:
- 失败是因为权限问题
- 失败是因为输出被裁剪
- 失败是因为查找范围太大
- 失败是因为命令危险而被拒绝
这直接决定了 agent 是否能做出下一步正确行动。
第五层:熵管理系统
这是我觉得很多人会忽略,但其实特别关键的一层。
Agent 一旦持续运行,系统一定会逐渐“变脏”。
表现形式包括:
- prompt 越来越长
- rules 越来越旧
- AGENTS.md 越来越像垃圾场
- 工具定义越来越多但没人维护
- 会话历史越来越重
- memory 里混入大量无效信息
OpenAI 在那篇文章里其实已经非常明确提到了这件事:当一切都重要时,一切都不重要;大而全的说明文件会迅速腐烂。
所以 Harness 不是“搭完就完了”。
Harness 还有一个长期任务:
持续做熵管理。
也就是:
- 让过期规则失效
- 让长上下文压缩
- 让低价值历史退出上下文
- 让项目知识以可维护方式沉淀
- 让系统不断回到“对模型友好”的状态
如果没有这层意识,再强的 agent 也会越跑越歪。
从公式看 Harness 的位置
以前我会说 Agent = Loop(LLM + Context + Tools),但现在我更愿意升级成:
Agent = Loop(Model + Harness)
因为 Context 和 Tools 本质上都属于 Harness 的一部分。真正决定 agent 上限的,不是”你有没有这些组件”,而是你有没有把这些组件工程化成一个可以长期运转的环境。同样是一个模型、一个工具列表、一个上下文窗口,有人做出来的是玩具,有人做出来的是生产系统——差别就在 Harness。
所以,Harness 的本质是什么?
一句话:
Harness 工程,就是把 Agent 从”会调用工具的模型”,变成”能在约束中稳定完成任务的系统”。
最重要的三个词是约束、反馈、稳定。真实世界里的 agent 不是靠”聪明”活下来的,是靠有边界、有结构、有状态、有反馈、有兜底活下来的。模型像发动机,但决定这台车能不能上路、会不会翻车的,是底下那整套工程环境——也就是 Harness。
如果你要开始做 Harness 工程,先抓什么?
我给一个非常实用的落地顺序。
1. 先别急着追最强模型
先把环境搭起来。
因为环境是可复用资产,换模型能继承; 但只靠换模型,通常不能替你补环境债。
2. 先把工具系统做成“系统”
至少做到:
- 可发现
- 可校验
- 可分级
- 可拦截
- 可审计
3. 上下文不要写成一坨
把 prompt 当成装配系统,不要当成单文件。
4. 安全边界必须在运行时
不要把安全寄托在提示词上。
5. 所有失败都尽量可解释
让系统错误能回流成模型能理解的反馈。
6. 给长任务设计状态与恢复机制
没有状态管理,就没有真正的持续执行。
7. 定期做熵管理
规则、记忆、会话、文档,都会腐烂。 你不清理,系统就会慢慢失控。
为什么我会说:Harness 不是新东西,但它是一个重要命名
Harness 终于把很多 Agent 开发者长期在做、但总说不清的事情命名清楚了——为什么 prompt 调半天没用、为什么换模型只能解决一部分问题、为什么工程化之后效果会突然稳定、为什么长任务能力往往取决于环境而不是参数量。它把这些零散经验收束成了一个明确的讨论入口。
回头看 memo code,我当时真正做的事情不只是”做一个 coding agent”,我其实一直在做一套 Harness。prompt 分层装配、工具 DSL、风险分级、审批缓存、危险命令拦截、子进程管理、system hint 反馈、输出裁剪——这些东西单拿出来都不性感,但正是这些东西,决定了一个 agent 到底是 demo、玩具,还是一个真的能在环境里持续做事的系统。
所以 Harness 不是横空出世的新发明,它让 Agent 工程这门课终于有了一个更准确的词。
(完)