Claude Code 和 Cursor 并不是用来跟 AI 对话的界面。同一个项目上跑AI 编码助手:Claude Code、Trae 和 Qwen,你就会发现同一个任务,换一个工具,结果就不一样。
或者是代码看着没问题,但是违反了一条以为已经设好的约束,或者产生了结构的差异。这不是模型问题,也不是文档问题,而是一个典型的 Harness 问题。
- 编码 Agent 的 Harness 是模型完成结构化、可重复工作所需要的一整套基础设施:上下文加载、工具访问、编排(Orchestration)、执行钩子(Execution Hooks)、权限范围、记忆管理、会话生命周期。
- 模型决定输出质量的上限,Harness 决定下限。
- 把 Harness 理解成一个操作系统,会改变你配置它的方式;也能解释为什么不同工具之间的配置漂移(Configuration Drift),会产生那种看上去像是模型不稳定的失败。
大多数人第一次用 Claude Code 或 Cursor 时,会把它们当成一个能力不错的聊天界面:描述任务,AI 产出代码,人来审查并应用。认为工具是模型输出的交付通道,这样虽然可以但是整体上是有问题的。
的确是有一个模型而且我们是在和它交流,但是如果它把几乎所有的工作、几乎所有的差异都算到了模型头上,其实大部分差异并不来自模型而是来自 Harness。
Agent = Model + Harness
每一个 AI 编码 Agent 都是同样的两部分结构:
Agent = Model + Harness
模型是认知基础:处理文本、生成 Token 的神经网络。但模型是无状态的、没有工具、上下文。单独放在那里,它能在聊天窗口里回答问题;它读不了代码库、写不了文件、跑不了测试,也不记得上一次会话做过什么。
Harness 是除此之外其他东西,可以把一个无状态的语言模型,变成一个能持续产出工作的编码 Agent。可以把它想成 AI 工作的操作系统:模型是 CPU,是原始的计算能力;没有 OS —— 没有内存管理、没有 I/O、没有进程隔离、没有调度 —— 一颗 CPU 没办法和文件、网络、用户发生有用的交互。Harness 就是这一层 OS它给模型一个结构化的运行环境,并负责模型和外部世界之间每一次交互的中介。
Claude Code 是一个 Harness。Trae 是一个 Harness。Cursor 是一个 Harness。它们包的是不同的模型,或者是同一个模型在不同配置下的样子,但在结构上做的都是同一件事:把模型的原始能力,变成可以应用到真实工作上的形态。
编码 Agent Harness 的七个组件
Harness 不是一块单一的基础设施而是一层一层叠起来的能力栈。每个 AI 编码 Harness,不管包的是哪个模型,都会以某种形式提供下面这七层。
1、 上下文加载
在模型对任何任务采取行动之前,Harness 会先注入上下文:项目规则、架构约束、工作流指令、工具相关的指引。Claude Code 中的 CLAUDE.md 就是这一层的入口。模型在启动时能看到什么,决定了它能做什么。上下文加载不等于聊天历史,它是 Harness 在每一次会话开始之前都重新准备的一份结构化简报,每次都重新准备。
2、工具层
模型本身不能读文件、跑 Shell 命令、调外部 API。Harness 提供一套模型可以调用的工具词汇:read、write、edit、search、execute、fetch。每一次工具调用都由 Harness 居中处理:模型请求动作,Harness 决定是否执行、如何执行,以及返回什么。
3、编排(Orchestration)
复杂任务需要多个 Agent 或多个步骤。Harness 负责派生子 Agent —— 拥有独立上下文的独立模型实例 —— 在它们之间路由任务,并安排工作顺序。这是 Harness 和聊天客户端的根本区别:聊天客户端一次只转发一条消息;Harness 可以并行跑多条工作流,再把结果合成在一起。
4、执行钩子(Execution Hooks)
这是最被低估的组件。钩子是在模型发起动作之前或之后运行的确定性代码 —— 不是建议、不是指南,而是强制执行的。一个钩子可以拦截一次文件写入,按 Schema 校验输出,在失败时阻止该动作,并向模型返回一个结构化错误。钩子把概率性的模型,变成在关键决策点上行为可预测的系统。它们是强制层是 Harness 中模型无法绕过的那部分。
5、 权限层
Harness 定义模型能做什么、不能做什么:可以写入哪些目录、可以执行哪些命令、能不能访问网络。这是运行边界。一个能不受限制删掉生产文件的模型,不是一个安全的编码 Agent。权限层让有边界的自治成为可能:模型可以在定义好的范围内独立行动,而这个范围由 Harness 强制,不是靠模型自己克制。
6、记忆与状态管理
语言模型在会话之间没有记忆。Harness 管理持久层:哪些状态会被带到下一次,上下文变得过大时如何压缩,启动时如何加载来自之前会话的记忆。少了这一层,每次会话都从零开始,每一条规则、每一条约束、每一条项目约定都得从头重建。
7、会话生命周期
Harness 管理工作的边界:一次会话如何开始,上下文如何初始化,任务如何在会话之间交接,模型如何发出任务完成的信号。这一层让跨会话的工作可以保持连贯,而不是退化成一串互不相干的交互;让三天前被打断的任务,今天可以接着做下去,不丢线索。
为什么 Harness 比模型有更大的杠杆
模型决定输出质量的上限。Harness 决定下限。
一个没有被治理的 Harness 包着的模型能在一次会话里产出优秀代码,也能在下一次会话里在难度完全相同的任务上产出意外糟糕的代码。其中一部分差异来自模型;但大部分结构性差异 : 上下文没加载,钩子没就位,权限没划,记忆没持久化。
在结构化工作上,一个带治理的 Harness 配上中等模型,会持续地胜过一个没有治理的 Harness 配上更强模型。把模型的天花板往上推,只有在 Harness 的地板已经够高、够得到那块天花板的时候才有用。
这就让"Claude Code 还是 Cursor"对大多数团队来说成了一个错误的问题。两者都是能力不错的 Harness,各自包着能力不错的模型。问题不在哪个 Harness 更聪明,而是是哪一层治理在指挥这个 Harness;以及换工具的时候,那一层治理能不能跟着迁移过去。
两个 Harness,一层治理
在同一个项目上同时跑多个 AI 编码助手,会让 Harness 的结构以一种单工具配置做不到的方式显形。
每个工具读取不同的配置格式。每个工具有不同的钩子语法。每个工具有不同的权限系统。而在这个项目的三个助手之间,同样的约束依然成立,同样的工作流触发依然会触发,同样的架构规则依然被执行。不是因为每个工具都被单独调过一遍,而是因为治理层只存在一份,放在一个共享目录里,每个助手的配置都指向同一个来源。
Harness 读取治理层。治理层不关心是哪一个 Harness 在读它。
这就是理解 Harness 是什么所带来的结构性结论:治理层和 Harness 是可分离的。Harness 执行,治理指挥。Harness 是载体,治理是指令集。
把编码 Agent 的 Harness 理解成一个操作系统,而不是一个聊天界面,那些原本看起来像是小调整的配置决策,就会变成架构决策。
会话开始时加载进上下文的内容:不是一段系统 Prompt。它是 OS 在进程运行之前下发给它的简报。
配置出来的钩子:不是可选的增强项。它们是把概率性模型变成可预测系统的确定性强制层。
定义出来的权限范围:不是一个安全上的礼节性配置,它是让自治执行变得可信任的运行边界。
放进 Harness 里的治理内容:不是文档,它是 OS 在模型每一次行动时都会执行的指令集。
总结
大多数被 AI 编码结果的不一致的原因不是模型,而是操作系统,也就是我们所说的Harness ,因为每一个编程工具提供给模型的上下文都不一样,所以有时候出现问题,不妨先看看Harness ,没准改一改就好了。
https://avoid.overfit.cn/post/b455636bc99d42cc899314e14288b7f7
作者:Rakesh Patel