Harness Engineering:从 LLM 到可靠 AI Agent 的关键工程
为什么同一个大模型,在不同 Agent 系统中的表现可能天差地别?答案往往不在模型本身,而在于模型周围的 Harness。
关键词: LLM、AI Agent、Harness、Agent Runtime、Context Engineering、Tool Calling、Sandbox、HITL
一、背景:为什么需要 Harness?
过去几年,大模型应用经历了从 Chatbot 到 Agent 的演进。
早期的 LLM 应用主要依赖 Prompt Engineering,通过精心设计提示词,让模型生成符合预期的文本。
随着 Tool Calling、RAG、MCP 等技术的发展,大模型逐渐具备了调用外部工具、查询知识库、操作文件和执行代码的能力。
但当 Agent 开始处理复杂任务时,一系列问题也随之暴露:
- 上下文丢失: 长时间执行任务后,模型遗忘早期目标、约束和已经完成的工作。
- 工具调用失控: 模型反复调用同一个工具,或者使用错误的参数。
- 任务执行中断: 遇到网络异常、工具超时或服务重启时,Agent 无法恢复此前的执行状态。
- 缺乏安全边界: 模型可能执行危险命令,访问不应访问的文件,甚至受到 Prompt Injection 攻击。
- 缺乏结果验证: Agent 认为任务已经完成,但实际产物可能不满足用户要求。
- 难以调试和优化: 开发者无法准确定位失败发生在模型推理、工具执行还是上下文管理环节。
这些问题并不能简单地通过更换更强的大模型来解决。
原因在于:
大模型负责生成决策,而复杂任务的可靠执行需要一整套外部工程系统。
这套围绕大模型构建的执行与控制系统,就是 Harness。
2026 年 2 月,OpenAI 在《Harness engineering: leveraging Codex in an agent-first world》中介绍了其围绕 Codex 构建的工程实践,强调通过改进环境、知识组织和验证机制,让 Agent 能够持续完成复杂的软件工程任务。
二、什么是 Harness?
Harness 原本有“挽具、线束、约束装置”的含义。在 AI Agent 领域,它通常指 Agent Harness。
可以将它定义为:
Harness 是围绕大语言模型构建的一套运行、控制和保障系统,负责管理上下文、工具调用、执行循环、状态持久化、安全约束以及任务结果验证,使模型能够可靠地完成多步骤任务。
Microsoft Agent Framework 和 Google Cloud 对 Agent Harness 的描述,都强调了模型调用、工具执行、状态管理及安全控制等能力。
可以用一个简化公式描述:
\[ \text{Agent} \approx \text{LLM} + \text{Harness} \]
这里的公式是一种工程抽象,而不是严格的数学定义。
其中:
- LLM 是 Agent 的推理与决策核心。
- Harness 是 Agent 的运行、执行和控制环境。
例如,当用户提出“帮我分析一个 GitHub 项目,修复 Bug,并提交 Pull Request”时:
LLM 可以分析代码、判断 Bug 原因、生成修改方案,但它本身并不能直接操作 Git 仓库。
Harness 则需要负责获取代码、执行文件操作、调用测试工具、管理工作区、检查修改结果,并在提交前处理必要的权限审批。
Harness 的整体架构
User / Application
任务输入、交互、用户反馈
Agent Harness
Agent 的运行与控制层
Context Manager
上下文、记忆、压缩
Agent Loop
推理、执行、反馈
Tool Runtime
工具调度、异常重试
State Manager
检查点、持久化、恢复
Guardrails
权限、安全、人工审批
Evaluator
测试、验证、可观测性
LLM / Reasoning Model
任务理解、规划、决策、内容生成
Tools / MCP
Sandbox
External APIs
需要注意,这只是一个概念架构。不同产品对 Harness 的边界划分并不完全一致,例如某些实现会把 Agent Runtime 和 Harness 视为不同层次,也有框架将两者整合。
三、Harness、Agent、Workflow 和 Framework 有什么区别?
这几个概念容易混淆,但它们解决的问题不同。
| 概念 | 核心关注点 | 典型作用 |
|---|---|---|
| LLM | 推理能力 | 理解、生成、决策 |
| Agent | 自主完成任务 | 根据目标选择行动 |
| Workflow | 流程编排 | 定义执行步骤和分支 |
| Framework | 开发抽象 | 提供构建 Agent 的 API |
| Harness | 运行和控制 | 让 Agent 可靠地持续执行 |
| Runtime | 运行时支撑 | 提供进程、资源与执行环境 |
例如使用 LangGraph 开发代码修复 Agent:
LangGraph 可以作为开发框架,帮助我们定义状态、节点、边和执行流程。
但一个完整的 Harness 还需要考虑:模型上下文如何裁剪、工具权限如何控制、执行环境如何隔离、中断后如何恢复、结果如何验证等。
因此:
Framework 提供开发 Agent 的基础能力,Harness 关注如何把这些能力组织成可可靠运行的 Agent 系统。
两者并不是互斥关系。Framework 可以内置 Harness 能力,Harness 也可以基于 Framework 实现。
四、Harness 的六大核心能力
4.1 Agent Loop:管理推理与执行循环
Agent Loop 是 Harness 最基本的组成部分。
它负责在模型与外部环境之间不断循环:
接收任务 / 加载状态
LLM 推理,生成下一步动作
Harness 检查模型输出
调用工具
权限验证 → 执行 → 获取结果
生成答案
验证完成条件
未完成:更新上下文并继续循环
输出结果 / 保存最终状态
已完成,或达到明确的退出条件
在最简单的实现中,Agent Loop 本质上就是一个 while 循环。
async def agent_loop(messages, llm, tools): for step in range(30): response = await llm.generate( messages=messages, tools=tools.schemas ) messages.append(response) if not response.tool_calls: return response.content for call in response.tool_calls: result = await tools.execute( call.name, call.arguments ) messages.append( make_tool_result(call.id, result) ) raise RuntimeError("Agent exceeded step limit")
这段代码展示了最基础的 Agent Loop,但还不是生产级 Harness。
实际工程中,还必须考虑:
- 工具参数是否合法,调用权限是否满足。
- 多个工具调用能否并发执行。
- 工具超时、失败后是否重试。
- 是否存在无限循环或重复调用。
- 用户是否主动取消任务。
- 是否达到 Token、时间和费用预算。
- 模型声称任务完成时,是否真的满足验收条件。
其中,一个容易忽视的问题是:LLM 认为任务完成,不代表任务真的完成。
例如代码修复 Agent 返回“Bug 已修复”,Harness 仍然可以要求运行单元测试、静态检查或集成测试。
如果验证失败,再将错误信息反馈给模型,进入下一轮修复。
这种“执行—反馈—验证”的闭环,是 Agent 能够完成复杂任务的重要基础。
4.2 Context Engineering:上下文工程
对于长任务 Agent,上下文管理往往比 Prompt 本身更重要。
虽然现代大模型能够处理较长的上下文,但上下文窗口仍然是有限资源。
尤其当 Agent 持续执行几百次工具调用时,大量中间结果会不断累积。
例如:
- Git 日志和代码文件
- 搜索结果和网页内容
- 工具调用参数及返回值
- 执行错误与异常堆栈
- 历史推理结果
- 已完成与待完成任务
如果每一轮都将所有历史消息发送给模型,不仅会增加 Token 成本,还可能降低模型识别关键信息的能力。
Harness 通常会结合以下机制。
1. Context Compression(上下文压缩)
将较早的历史交互压缩成简洁摘要。
例如:
原始历史:
- 已读取 25 个代码文件
- 执行 12 次测试
- 发现 3 个异常
- 修改 4 个函数
- 完成 2 次验证
压缩后的状态:
目标:修复用户登录失败问题
已定位:JWT 过期判断逻辑错误
已修改:auth.py、token.py
测试情况:18 通过,2 失败
下一步:修复剩余 2 个测试
压缩不应只追求更少的 Token,还必须保留关键约束、决策依据和未完成事项。
2. Context Offloading(上下文卸载)
将大体积工具结果保存到文件系统、对象存储或数据库中,模型上下文只保留文件路径、标识符和必要摘要。
当 Agent 需要详细信息时,再按需读取。
3. Context Retrieval(上下文检索)
通过 RAG、关键词搜索或文件索引,只获取当前步骤相关的信息,而不是每次重新加载全部资料。
4. Memory Management(记忆管理)
区分不同的存储层次:
| 类型 | 保存内容 | 生命周期 |
|---|---|---|
| 工作上下文 | 当前模型请求需要的信息 | 单次模型调用 |
| 会话状态 | 任务计划、工具结果、执行位置 | 当前任务或会话 |
| 长期记忆 | 用户偏好、项目规范、可复用知识 | 跨会话 |
| 外部工作区 | 代码、文档、生成文件 | 按项目保留 |
OpenAI 在 Harness Engineering 实践中强调,通过精简入口文档并建立清晰的知识导航,让 Agent 按需读取信息,而不是将所有知识直接塞进一个巨大的指令文件。
这也说明,Context Engineering 的核心不是单纯增加上下文长度,而是让模型在正确的时间获取正确的信息。
4.3 Tool Runtime:工具执行与管理
Tool Calling 让模型能够表达调用工具的意图,而 Harness 负责真正执行工具。
通常可以拆分为三个阶段:
LLM 生成 Tool Call
↓
Harness 校验工具名称、参数与权限
↓
Tool Runtime 执行工具
↓
结果标准化、记录日志
↓
返回 LLM
一个成熟的 Tool Runtime 需要解决以下问题。
工具注册与发现
通过统一的工具注册表管理工具的名称、描述、参数 Schema 和权限要求。
MCP 可以作为连接外部工具及资源的一种标准化接口,但 MCP 本身并不等同于 Harness。
参数验证
使用 JSON Schema 或 Pydantic 验证模型生成的参数,避免错误参数直接传入业务系统。
并发执行
当模型同时请求多个相互独立的工具时,可以使用 asyncio.gather() 等机制并发执行。
但对于存在数据依赖的工具,应保证执行顺序。
例如“创建订单”和“扣减库存”不能仅因为同时生成,就无条件并发执行。
超时与重试
对于网络超时等临时故障,可以采用有限次数重试与指数退避策略。
但对付款、下单和数据删除等具有副作用的操作,必须结合幂等键或操作状态查询,避免重复执行。
执行结果标准化
将成功、失败、耗时、错误类型及可恢复性转换成统一结构,便于模型和监控系统消费。
4.4 State Management:状态持久化与恢复
复杂 Agent 的任务可能持续数分钟,甚至数小时。
如果执行过程只保存在内存中,服务重启就意味着任务丢失。
因此,Harness 应具备状态持久化能力。
典型的状态数据包括:
{
"task_id": "task_001",
"status": "running",
"current_step": 12,
"goal": "修复登录模块 Bug",
"completed_steps": [
"read_repository",
"locate_bug",
"modify_code"
],
"pending_steps": [
"run_tests",
"create_pull_request"
],
"workspace": "/workspace/task_001",
"checkpoint_id": "checkpoint_012"
}
实际运行状态还需要保存模型消息、工具调用标识、必要的中间结果引用、待审批动作、错误记录和恢复位置。
Harness 可以通过 Checkpoint 实现任务中断与恢复。
执行任务
↓
保存 Checkpoint
↓
发起工具调用
↓
执行中断 / HITL
↓
重新加载 Checkpoint
↓
恢复待执行操作
↓
继续任务
需要注意,恢复不能简单地从上一个步骤重新执行。
例如订单已经创建成功,但程序在接收返回结果前崩溃。重新执行创建订单操作可能导致重复下单。
因此,对外部副作用操作需要设计:
- 幂等键与去重机制
- 执行状态记录
- 操作结果查询
- 必要的补偿操作
这类问题与传统分布式系统中的可靠任务执行具有很强的共性。
4.5 Guardrails:安全控制与执行隔离
Harness 不能无条件相信模型的每个决定。
模型输出可能存在误判,也可能受到恶意外部内容影响。
因此,Harness 必须提供独立于模型推理的安全控制机制。
常见机制包括:
最小权限原则
Agent 只获取当前任务所需的工具和资源权限。
Sandbox(沙盒隔离)
对代码执行、Shell 命令和不可信文件处理采用隔离环境,限制文件系统、网络访问和计算资源。
HITL(Human-in-the-Loop)
对于高风险操作,在真正执行前暂停任务,由人工批准、修改或拒绝。
例如:
| 操作 | 建议策略 |
|---|---|
| 读取项目文件 | 自动执行 |
| 执行只读查询 | 自动执行 |
| 修改本地工作区 | 在授权范围内执行 |
| 删除生产数据库 | 高风险审批或直接禁止 |
| 对外付款 | 明确授权与专门审批 |
Prompt Injection 防护
网页、仓库文件、邮件、数据库查询结果都应视为潜在的不可信数据。
不能允许工具返回的文本直接提升为系统指令,也不能仅凭模型判断来保障安全。
4.6 Evaluation & Observability:评估和可观测性
Agent 的输出是非确定性的,仅通过“能否正常运行”无法判断其质量。
Harness 应记录完整执行轨迹,例如:
Trace ID: 9f23...
Task: 修复登录 Bug
Step 01: LLM Planning 620 ms
Step 02: read_file 42 ms
Step 03: grep_code 58 ms
Step 04: LLM Generate 1350 ms
Step 05: edit_file 36 ms
Step 06: run_tests 2450 ms
Step 07: LLM Repair 980 ms
Step 08: run_tests 2200 ms
Result: Success
可以从以下维度评价:
| 维度 | 常用指标 |
|---|---|
| 任务质量 | 成功率、验收通过率 |
| 工具质量 | 调用成功率、参数合法率 |
| 运行效率 | 总耗时、LLM 延迟、工具耗时 |
| 成本 | Token 消耗、模型费用、执行资源 |
| 可靠性 | 中断恢复率、异常率、重复操作率 |
| 安全性 | 越权调用率、危险操作拦截率 |
值得强调的是,Agent Evaluation 应尽量关注最终环境状态,而不仅是模型生成的文本。
例如,对于代码修复任务,“模型回复已经修复”不是最可靠的评估依据,测试通过、功能恢复和没有引入回归问题才更重要。
五、Harness 的核心设计理念:从 Prompt Engineering 到 Harness Engineering
Prompt Engineering 主要关注如何组织模型输入,让模型尽可能给出正确输出。
Harness Engineering 则进一步关注:
如何设计模型运行的环境,让它能够持续地、可验证地完成任务。
例如,面对同一个 Bug 修复失败的问题,可以采取不同优化方式。
| 问题 | Prompt Engineering | Harness Engineering |
|---|---|---|
| 模型修改错误文件 | 增加提示词约束 | 限制可编辑文件范围 |
| 模型遗漏测试 | 强调必须测试 | 将测试设为完成前置条件 |
| 模型忘记原始任务 | 重复目标描述 | 状态持久化与上下文压缩 |
| 模型执行危险命令 | 提示不要执行 | 沙盒隔离与权限策略 |
| 模型陷入循环 | 提示避免重复 | 循环检测、预算限制和终止策略 |
| 模型生成结果不正确 | 优化推理指令 | 引入自动化验证与反馈机制 |
一个重要的原则是:
不要仅仅告诉模型不要犯错,而应该改进运行环境,使错误更难发生、更容易发现、更容易恢复。
这也是 Harness Engineering 区别于传统 Prompt Engineering 的关键价值。
六、如何实现一个最小可用的 Harness?
假设我们要实现一个代码分析 Agent,可以将系统拆分为以下模块:
agent_harness/
├── core/
│ ├── agent.py # Agent Loop
│ ├── context.py # 上下文管理
│ ├── state.py # 状态持久化
│ └── planner.py # 任务规划
├── tools/
│ ├── registry.py # 工具注册
│ ├── executor.py # 工具调度
│ └── schemas.py # 参数校验
├── security/
│ ├── permissions.py # 权限管理
│ ├── sandbox.py # 沙盒执行
│ └── approval.py # HITL
├── evaluation/
│ ├── verifier.py # 结果验证
│ └── tracing.py # 链路追踪
└── main.py
在实际项目中,推荐从以下四个阶段逐步完善。
第一阶段:基础 Agent Loop
支持模型调用、工具注册、工具执行和结果回传,让 Agent 能够完成简单的多步骤任务。
第二阶段:可靠执行
加入超时、重试、工具参数校验、任务状态管理、循环检测以及 Checkpoint。
第三阶段:安全与上下文管理
加入 Sandbox、HITL、Context Compression、工作区隔离和权限控制。
第四阶段:生产化
加入 Trace、Evaluation、成本预算、任务调度、自动验证和长期运行能力。
这四个阶段不是严格的先后依赖关系。例如,在第一阶段开放真实外部写操作时,就必须同时引入必要的权限与安全控制。
七、主流 Harness 工程实践
目前已有不少产品或开源项目体现了 Harness 的设计理念。
Codex 的 Harness 支持模型在软件工程任务中检索上下文、调用工具、执行代码,并在配置的权限边界内推进工作。OpenAI 也将其底层 Harness 作为可复用的集成能力。
以开发者工作环境为中心,结合代码检索、工具调用、工作区操作与权限审批,让模型在真实代码库中执行复杂任务。
LangChain Deep Agents
开源 Agent Harness,面向多步骤和长时运行任务,提供任务规划、上下文管理、文件系统抽象和子 Agent 编排等能力。
这些系统各有侧重点,但共同体现了一个趋势:Agent 的工程能力越来越多地体现在模型周围的执行与控制系统,而不仅仅是模型本身。
八、进一步思考:Harness 与多 Agent 系统的关系
Harness 不只适用于单 Agent,也可以作为多 Agent 系统的基础设施。
在多 Agent 架构中,每个子 Agent 可能具有独立的角色、工具、上下文和任务状态。
例如:
User
|
Supervisor Agent
|
Harness
|
Task Orchestration
|
+------------+------------+
| | |
Research Agent Coding Agent Review Agent
| | |
Search Tools Sandbox Test Tools
| | |
+------------+------------+
|
Shared Task State
|
Final Evaluator
Harness 可以负责管理任务分配、并发执行、上下文隔离、执行状态和结果合并。
需要注意的是,多 Agent 不一定比单 Agent 更好。
多 Agent 可能带来额外的 Token 开销、通信成本、状态协调复杂度和调试难度。
当任务可以被清晰拆分,且子任务能够并行或使用不同专业工具时,多 Agent 才更容易体现优势。
因此,设计系统时应先判断任务是否真正需要多 Agent,再考虑相应的 Harness 编排能力。
九、总结
Harness 并不是一个全新的单点技术,而是将 Agent 开发中原本分散的能力,组织为统一的运行与控制系统。
它的核心价值体现在三个方面:
第一,让 Agent 从“能使用工具”走向“能可靠地完成任务”。
Tool Calling 只是赋予模型行动的接口,而完整的 Harness 需要处理执行、反馈、重试、恢复和结果验证。
第二,将模型的不确定性限制在可控的工程边界内。
通过 Sandbox、权限管理、HITL、状态持久化和自动化验证,降低错误决策造成的影响。
第三,让 Agent 系统具备持续改进的能力。
通过 Trace、Evaluation 和系统化的失败分析,可以判断问题究竟来自模型、上下文、工具还是运行环境,从而进行针对性优化。
从长期来看,模型能力仍然是 Agent 智能水平的重要基础,但能否在真实业务场景中稳定运行,越来越依赖 Harness 的工程质量。
模型决定 Agent 能够思考什么,Harness 决定这些思考如何转化为可靠、可控、可验证的行动。
- 点赞
- 收藏
- 关注作者
评论(0)