Agent Harness 解剖:全面解析
从定义到核心组件,系统理解 Agent 约束层的设计原理
TLDR:Agent = 模型 + Harness。Harness 工程就是我们围绕模型构建系统、将其转变为工作引擎的方式。模型承载智能,Harness 让智能发挥作用。本文将定义什么是 Harness,并推导出当今和未来 Agent 所需的核心组件。
能不能先定义一下什么是 "Harness"?
Agent = 模型 + Harness
如果你不是模型,那你就是 Harness(约束层)。
Harness 是模型本身之外的一切——所有代码、配置和执行逻辑。一个裸模型不是 Agent,但当 Harness 给它加上状态管理、工具执行、反馈循环和可执行的约束时,它就变成了一个 Agent。
具体来说,Harness 包括以下内容:
- 系统提示词(System Prompts)
- 工具、技能、MCP(模型上下文协议)及其描述
- 基础设施捆绑(文件系统、沙箱、浏览器)
- 编排逻辑(子代理生成、交接、模型路由)
- 确定性执行的钩子/中间件(上下文压缩、延续、代码检查)
关于如何划分 Agent 系统中模型与 Harness 的边界,有很多混乱的方式。但在我看来,上面这个定义是最清晰的,因为它迫使我们思考如何围绕模型智能来设计系统。
接下来,我们将逐一介绍 Harness 的核心组件,并从模型这个基本原语出发,推导出每个组件存在的理由。
为什么需要 Harness……从模型的视角来看
有些事情我们希望 Agent 能做,但模型本身做不到。这时候就需要 Harness 了。
模型(大多数情况下)接收文本、图像、音频、视频等数据,然后输出文本。仅此而已。它们本身无法:
- 在交互之间维护持久状态
- 执行代码
- 访问实时知识
- 搭建环境并安装软件包来完成工作
这些都是 Harness 层面的功能。LLM 的结构要求某种机制来包裹它们,才能完成有用的工作。
例如,要实现"聊天"这样的产品体验,我们需要用一个 while 循环来包装模型,以追踪之前的消息并追加新的用户消息。读到这里的人应该都已经用过这种 Harness 了。核心思路是:我们希望将期望的 Agent 行为转化为 Harness 中的实际功能。
从期望的 Agent 行为反推 Harness 工程
Harness 工程帮助人类注入有用的先验知识来引导 Agent 行为。随着模型能力越来越强,Harness 被用来精准地扩展和纠正模型,以完成以前不可能的任务。
我们不会穷举所有 Harness 功能。目标是从"帮助模型完成有用的工作"这个起点出发,推导出一组功能。我们将遵循这样的模式:
期望的行为(或需要修复的问题)→ 帮助模型实现这一目标的 Harness 设计
文件系统:持久化存储与上下文管理
我们希望 Agent 拥有持久化存储,以对接真实数据、卸载放不进上下文的信息、并在跨会话时保留工作成果。
模型只能直接操作其上下文窗口内的知识。在有文件系统之前,用户不得不手动复制粘贴内容给模型——这种用户体验很笨拙,对自主 Agent 来说根本行不通。世界已经在用文件系统来做工作了,所以模型自然被训练了数十亿个 token 的文件系统使用方式。自然而然的解决方案就变成了:
Harness 自带文件系统抽象和文件操作工具。
文件系统可以说是 Harness 中最基础的原语,因为它解锁了以下能力:
- Agent 获得一个工作空间来读取数据、代码和文档。
- 工作可以增量添加和卸载,而不用把所有东西都放在上下文里。Agent 可以存储中间输出,并维护跨会话的持久状态。
- 文件系统是天然的协作界面。多个 Agent 和人类可以通过共享文件进行协作。Agent 团队(Agent Teams)等架构就依赖于此。
Git 为文件系统增加了版本控制,使 Agent 能够追踪工作进度、回滚错误和分支实验。我们后面还会再讨论文件系统,因为它实际上是其他所需功能的关键 Harness 原语。
Bash + 代码:通用工具
我们希望 Agent 能自主解决问题,而不需要人类预先设计好每一个工具。
当今主流的 Agent 执行模式是 ReAct 循环——模型进行推理,通过工具调用执行动作,观察结果,然后在 while 循环中重复。但 Harness 只能执行它有逻辑的工具。与其强迫用户为每个可能的动作构建工具,更好的方案是给 Agent 一个像 Bash 这样的通用工具。
Harness 自带 Bash 工具,让模型能通过编写和执行代码来自主解决问题。
Bash + 代码执行是向"给模型一台计算机,让它自己想办法"迈出的一大步。模型可以通过代码动态设计自己的工具,而不是受限于一组预先配置好的固定工具。
Harness 仍然会附带其他工具,但代码执行已经成为自主问题解决的默认通用策略。
沙箱与工具:执行和验证工作
Agent 需要一个具有正确默认配置的环境,以便安全地行动、观察结果并取得进展。
我们给了模型存储能力和代码执行能力,但这些都需要在某个地方运行。在本地运行 Agent 生成的代码是有风险的,而且单个本地环境无法扩展到大型 Agent 工作负载。
沙箱为 Agent 提供安全的运行环境。 Harness 可以连接到沙箱来运行代码、检查文件、安装依赖并完成任务,而不是在本地执行。这创造了安全、隔离的代码执行环境。为了更高的安全性,Harness 可以允许列表命令并强制网络隔离。沙箱还能实现扩展——环境可以按需创建、分发到多个任务中,工作完成后即可销毁。
好的环境需要好的默认工具链。Harness 负责配置工具链,让 Agent 能完成有用的工作。这包括预装语言运行时和软件包、用于 git 和测试的 CLI、用于 web 交互和验证的浏览器。
浏览器、日志、截图和测试运行器等工具让 Agent 能够观察和分析自己的工作。这帮助它们创建自我验证循环——编写应用代码、运行测试、检查日志和修复错误。
模型本身不会自行配置执行环境。Agent 在哪里运行、有哪些工具可用、能访问什么、如何验证工作——这些都是 Harness 层面的设计决策。
记忆与搜索:持续学习
Agent 应该记住它们见过的内容,并能访问训练时不存在的信息。
模型除了权重和当前上下文中的内容外,没有额外的知识。在无法编辑模型权重的情况下,"添加知识"的唯一方式就是通过上下文注入。
对于记忆功能,文件系统再次成为核心原语。Harness 支持 AGENTS.md 等记忆文件标准,这些文件在 Agent 启动时被注入上下文。当 Agent 添加和编辑这个文件时,Harness 会将更新后的文件加载到上下文中。这是一种持续学习的形式——Agent 将某次会话中的知识持久存储,并在未来的会话中注入这些知识。
知识截止日期意味着模型无法直接获取新数据(如更新后的库版本),除非用户主动提供。对于最新知识,网络搜索和 Context7 等 MCP 工具帮助 Agent 访问知识截止日期之后的信息,如新库版本或训练停止时不存在的当前数据。
网络搜索和用于查询最新上下文的工具是值得内置于 Harness 的有用原语。
对抗上下文腐化
Agent 的性能不应在工作过程中逐渐下降。
上下文腐化(Context Rot)描述了模型在上下文窗口填满时推理和完成任务能力下降的现象。上下文是宝贵而稀缺的资源,因此 Harness 需要策略来管理它。
当今的 Harness 在很大程度上是优质上下文工程的传递机制。
上下文压缩(Compaction) 解决的是上下文窗口即将填满时该做什么的问题。没有压缩机制时,对话超过上下文窗口会发生什么?一种可能是 API 报错——这可不好。Harness 必须针对这种情况使用某种策略。所以上下文压缩会智能地卸载和总结现有上下文窗口,让 Agent 可以继续工作。
工具调用卸载(Tool Call Offloading) 有助于减少大型工具输出的影响——这些输出可能在上下文窗口中产生大量噪音,却提供不了有用信息。Harness 保留超过阈值的工具输出的头部和尾部 token,并将完整输出卸载到文件系统,以便模型在需要时访问。
技能(Skills) 解决的是 Agent 启动时加载过多工具或 MCP 服务器导致性能下降的问题。技能是一种 Harness 层面的原语,通过渐进式披露来解决这个问题。模型并没有选择在启动时将技能的前置内容加载到上下文中,但 Harness 可以支持这一点,以保护模型免受上下文腐化的影响。
长周期自主执行
我们希望 Agent 能够自主、正确地在长时间跨度内完成复杂工作。
自主软件创建是编码 Agent 的圣杯。但当今的模型存在提前停止、难以分解复杂问题、以及工作跨越多个上下文窗口时出现不连贯等问题。一个好的 Harness 必须围绕这些问题进行设计。
这时候前面提到的 Harness 原语开始产生叠加效应。长周期工作需要持久化状态、规划、观察和验证,才能在多个上下文窗口中持续工作。
文件系统和 Git 用于跨会话追踪工作。Agent 在一个长任务中会产生数百万个 token,文件系统能持久地捕获工作内容以追踪进度。加上 Git 后,新 Agent 可以快速了解项目的最新工作和历史。对于多个协同工作的 Agent,文件系统还充当共享工作台账。
Ralph 循环(Ralph Loop) 用于持续推进工作。Ralph 循环是一种 Harness 模式,通过钩子拦截模型的退出尝试,并在干净的上下文窗口中重新注入原始提示词,迫使 Agent 继续朝着完成目标工作。文件系统使这成为可能——每次迭代都从全新上下文开始,但会读取前一次迭代的状态。
规划和自我验证 以保持正确方向。规划是指模型将目标分解为一系列步骤。Harness 通过良好的提示词和注入使用计划文件的提醒来支持这一点。完成每个步骤后,Agent 可以通过自我验证来检查工作的正确性。Harness 中的钩子可以运行预定义的测试套件,并在失败时将错误信息循环回模型;也可以提示模型独立评估自己的代码。验证将解决方案建立在测试之上,并创建自我改进的反馈信号。
Harness 的未来
模型训练与 Harness 设计的耦合
当今的 Agent 产品如 Claude Code 和 Codex,是在模型和 Harness 共同参与的情况下进行后训练的。这帮助模型改进 Harness 设计师认为它们应该天生擅长的操作,如文件系统操作、Bash 执行、规划、或与子代理并行化工作。
这创造了一个反馈循环:有用的原语被发现、添加到 Harness 中,然后用于训练下一代模型。随着这个循环不断重复,模型在它们被训练的 Harness 中变得越来越强大。
但这种共同进化对泛化能力产生了一些有趣的副作用。它表现为改变工具逻辑会导致模型性能下降。一个很好的例子在 Codex-5.3 提示词指南中描述了用于编辑文件的 apply_patch 工具逻辑。一个真正智能的模型应该可以轻松切换不同的补丁方法,但在 Harness 参与下的训练造成了这种过拟合。
但这并不意味着对你的任务来说最好的 Harness 就是模型被后训练时使用的那个。Terminal Bench 2.0 排行榜就是一个很好的例子。在 Claude Code 中运行的 Opus 4.6 得分远低于在其他 Harness 中运行的 Opus 4.6。在之前的一篇博客中,我们展示了仅通过改变 Harness 就将我们的编码 Agent 从 Top 30 提升到 Top 5。针对你的任务优化 Harness,还有很大的提升空间。
Harness 工程的走向
随着模型变得更强大,今天 Harness 中的一些功能将被吸收到模型中。模型在规划、自我验证和长周期连贯性方面会变得天生更好,因此需要更少的上下文注入。
这暗示 Harness 会随着时间变得不那么重要。但正如提示词工程今天仍然有价值一样,Harness 工程很可能将继续在构建优秀 Agent 方面发挥作用。
诚然,当今的 Harness 确实在弥补模型的不足,但它们也围绕模型智能构建系统,使其更高效。一个配置良好的环境、合适的工具、持久化状态和验证循环,能让任何模型变得更高效——无论其基础智能水平如何。
Harness 工程是一个非常活跃的研究领域,我们用它来改进 LangChain 的 Harness 构建库 deepagents。以下是我们正在探索的一些开放且有趣的课题:
- 编排数百个 Agent 在共享代码库上并行工作
- Agent 分析自己的追踪记录来识别和修复 Harness 层面的故障模式
- Harness 动态地按需为特定任务组装正确的工具和上下文,而非预先配置
这篇博客是一个关于定义 Harness 是什么、以及它如何被我们希望模型完成的工作所塑造的尝试。
模型承载智能,Harness 是让智能发挥作用的系统。
致以更多的 Harness 构建、更好的系统和更好的 Agent。