/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */
#content_views .toc,
/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */
#content_views.markdown_views > p:empty:has(+ .toc),
#content_views.markdown_views > .toc + p:empty,
/* 富文本旧版目录标记 */
#content_views.htmledit_views #main-toc,
#content_views.htmledit_views #hr-toc,
#content_views.htmledit_views p[id*=\”-toc\”] {
display: none !important;
}
/* 目录去掉后,紧跟的首个标题不再多出一块上边距 */
#content_views.markdown_views > .toc + h1,
#content_views.markdown_views > .toc + h2,
#content_views.markdown_views > .toc + h3,
#content_views.markdown_views > .toc + h4,
#content_views.markdown_views > .toc + p:empty + h1,
#content_views.markdown_views > .toc + p:empty + h2,
#content_views.markdown_views > .toc + p:empty + h3,
#content_views.markdown_views > .toc + p:empty + h4 {
margin-top: 0 !important;
}
一、引言:为什么给大模型接上工具,还不等于 Agent 能正常运行?
面试官问:
Agent Harness 是什么?
有人回答:
就是给大模型接几个工具,让模型能够读取文件、调用 Python、查询数据库。
面试官继续追问:
工具接好了,谁负责真正执行?执行失败怎么办?模型下一轮应该看到什么?任务中断后怎么恢复?
这些问题,实际上都指向 Agent Harness。
在普通的大模型聊天场景中,用户提出问题,模型生成回答,交互就可能结束。
但 Agent 不一样。
Agent 往往需要完成多个连续步骤,例如:
读取用户指定的文件。
分析文件内容。
调用程序处理数据。
根据执行结果调整操作。
检查最终产物。
将结果交付给用户。
这些步骤不一定一次就能成功。
如果某一步出错,Agent 可能还需要根据错误信息重新判断和执行。
因此,完整的 Agent 不只是“大模型 + 工具”。
还需要有一套机制,负责组织模型调用、工具执行、结果反馈和任务推进。
这套运行支撑机制,就可以称为 Agent Harness。
二、先理解 Agent Harness 是什么
2.1 Agent Harness 的基本定义
Agent Harness 可以理解为:
围绕大语言模型的一套运行支撑机制,用于组织模型调用、工具执行、结果反馈和任务控制,让 Agent 能够围绕用户目标连续执行任务。
通俗一点:
模型负责想,工具负责做,Harness 负责让整个过程真正运转起来。
举个生活中的例子。
假设一个工厂需要完成一笔订单。
工厂里有:
-
决策主管。
-
生产机器。
-
工人。
-
生产调度系统。
决策主管决定下一步应该生产什么。
机器和工人负责实际加工。
但如果没有生产调度系统,整个工厂就很难协调各个步骤。
例如:
机器执行结束后,谁负责收集结果?
出现故障后,谁负责通知主管?
任务暂停之后,谁知道应该从哪里继续?
产品加工完成后,谁负责检查是否符合要求?
在 Agent 系统中,Harness 就类似这样的运行调度机制。
2.2 Agent 的几个核心组成部分
我们先区分几个容易混淆的概念。
| LLM | 大脑 | 理解任务、分析问题、生成决策 |
| Prompt | 工作要求 | 表达目标、规则和约束 |
| Skill | 操作手册 | 提供特定任务的操作方法 |
| Tool | 双手 | 执行文件、数据库、程序等操作 |
| Harness | 运行调度机制 | 组织模型调用、工具反馈和任务控制 |
| Agent | 完整智能体系统 | 将各部分组织起来完成任务 |
这里需要特别注意:
Harness 并不一定是某一个独立软件,也不一定必须有一个名为 harness.py 的文件。
它描述的是一组运行职责。
这些职责可以由开发者自行实现,也可以由现有 SDK、框架或宿主应用封装。
三、为什么一次模型调用,还不等于任务执行?
这是理解 Harness 的第一个关键知识点。
假设用户提出:
帮我读取 data.xlsx,删除其中的重复行,并另存为 cleaned.xlsx。
大模型收到任务以后,判断:
我应该先读取 Excel 文件。
于是模型产生一个结构化工具调用请求:
{
"tool": "read_file",
"arguments": {
"path": "data.xlsx"
}
}
现在我们思考一个问题:
模型输出了工具调用请求,文件是不是已经被读取了?
答案是:没有。
因为这个 JSON 只表达了一件事:
模型希望调用名为 read_file 的工具,并传入文件路径。
但模型输出请求本身,不会让电脑自动打开文件。
真正的执行还需要外部程序完成。
3.1 谁负责真正执行工具?
典型过程如下:
大模型生成工具调用请求
|
v
Harness 接收工具请求
|
v
检查工具名和参数
|
v
检查执行权限和运行条件
|
v
调用实际工具
|
v
获取工具执行结果
|
v
将结果返回给模型
例如,工具真正执行后返回:
{
"status": "success",
"file": "data.xlsx",
"rows": 100,
"columns": ["姓名", "日期", "金额"]
}
此时模型才知道:
-
文件确实读取成功。
-
文件包含 100 行数据。
-
文件有姓名、日期和金额三个字段。
如果没有把实际结果返回给模型,模型就无法可靠判断下一步应该怎么做。
所以这里必须区分两种能力:
模型的能力:根据当前输入决定下一步动作。
工具和运行程序的能力:真正执行动作,并返回实际结果。
Harness 的重要作用,就是把这两种能力连接起来。
四、Agent Harness 的核心:Agent Loop 执行循环
前面讲的是一次工具调用。
但是一个完整任务,通常需要多次工具调用。
这就引出了 Agent Harness 最重要的概念:
Agent Loop(智能体执行循环)。
它的基本逻辑是:
思考 → 执行 → 观察 → 再思考。
4.1 Agent Loop 的运行原理
一个典型的执行过程如下:
用户提出任务
|
v
Harness 准备输入
|
v
调用大模型
|
v
模型决定下一步操作
|
v
Harness 处理工具请求
|
v
工具实际执行
|
v
Harness 收集执行结果
|
v
将结果交给下一轮模型
|
|
+—-> 继续思考与执行
满足结束条件后,返回最终结果
核心在于:
模型不是一次性决定完所有操作,而是可以根据前一步执行的真实结果,动态调整下一步。
这也是智能体区别于简单固定脚本流程的重要特点之一。
4.2 用 Excel 清理任务理解执行循环
假设用户提出:
帮我清理 Excel 表格中的重复行,并统一日期格式,最后保存新文件。
第一轮:读取文件
模型决定调用读取工具。
工具返回:
文件读取成功。
总行数:100
字段:姓名、日期、金额
Harness 把结果交给模型。
第二轮:清理数据
模型根据实际文件结构,决定调用 Python 清理数据。
工具返回:
原始数据:100 行
删除重复数据:10 行
清理后数据:90 行
输出文件:cleaned.xlsx
Harness 再次把结果交给模型。
第三轮:验证结果
模型判断还需要检查:
-
新文件是否存在?
-
是否仍然存在重复行?
-
日期格式是否统一?
-
原始文件有没有被修改?
Harness 调用相应工具进行检查。
只有验证结果符合用户要求,才能有依据地判断任务完成。
这个例子说明:
Harness 不只是多次调用模型,而是让每轮决策都能够根据真实执行结果继续推进。
4.3 用简化伪代码理解 Harness
下面是一段教学用伪代码,用于帮助理解执行循环的核心结构,并不是可以直接部署的完整实现。
def agent_harness(user_task):
state = create_task_state(user_task)
while not state.is_terminal():
# 1. 准备当前模型需要的信息
context = build_context(state)
# 2. 调用大模型
response = call_llm(context)
# 3. 模型请求使用工具
if response.has_tool_call():
tool_call = response.tool_call
# 检查工具、参数、权限和预算
check_execution_policy(tool_call, state)
# 4. 真正执行工具
result = execute_tool(tool_call)
# 5. 保存执行结果和进度
state.record(tool_call, result)
save_state(state)
else:
# 6. 模型生成最终结果
if verify_completion(response, state):
state.mark_completed(response)
else:
state.handle_incomplete(response)
return state.result()
这段伪代码最值得关注的,不是 Python 语法,而是其中的逻辑:
第一,Harness 调用模型。
第二,模型决定是否使用工具。
第三,Harness 安排工具真正执行。
第四,工具执行结果被记录下来。
第五,Harness 再次调用模型。
第六,满足结束条件后,任务才终止。
真实系统还需要补充异常处理、超时、取消、持久化、幂等控制和权限隔离等机制。
五、为什么 Harness 需要管理上下文?
随着 Agent 不断执行任务,会出现一个新的问题:
模型下一轮应该看到哪些信息?
假设 Agent 已经执行了 20 次工具调用。
执行过程中可能产生:
-
用户最初的需求。
-
文件读取结果。
-
Python 执行日志。
-
测试报错。
-
修改后的文件。
-
已经解决的问题。
-
尚未完成的步骤。
如果每轮都把所有历史信息完整交给模型,可能导致上下文不断增长。
而且有些历史信息已经失效。
5.1 一个简单例子
假设 Agent 第一次读取文件时,工具返回:
错误:找不到 data.xlsx
随后,Agent 发现正确路径是:
/project/data.xlsx
并且成功读取了文件。
那么下一轮模型需要重点知道的是:
当前文件路径:
/project/data.xlsx
当前状态:
文件读取成功。
历史问题:
路径错误,已经解决。
而不是始终把之前的错误当成当前状态。
因此,Harness 需要组织每轮上下文。
这类工作叫:
Context Management(上下文管理)。
通俗理解:
上下文管理,就是决定模型这一轮应该看到什么。
它可以包括:
-
保留用户目标和约束。
-
保留当前关键证据。
-
整理历史执行结果。
-
减少重复或过时信息。
-
将较长资料保存在外部,需要时再读取。
但需要注意,不能为了压缩上下文而丢失关键规则或验证依据。
六、上下文管理和任务状态管理有什么区别?
这是 Agent Harness 中另一个非常重要的概念。
很多初学者容易把 Context 和 State 混为一谈。
其实它们关注的问题不同。
Context:模型这一轮需要看到什么?
State:任务实际已经进行到哪里?
举个例子。
假设 Excel 清理任务的执行进度如下:
任务:清理 Excel
已完成:
1. 读取 Excel 文件
2. 删除重复数据
3. 统一日期格式
未完成:
4. 检查清理结果
5. 验证原始文件未修改
6. 向用户交付文件
这些信息属于任务状态。
它描述整个任务的进展。
但下一轮模型可能只需要知道:
用户目标:
清理 Excel,不修改原文件。
当前进度:
数据已经清理完成。
当前文件:
cleaned.xlsx
下一步:
检查结果是否满足要求。
这部分才是当前模型需要的上下文。
两者的区别如下:
| 核心问题 | 模型现在需要看什么? | 任务已经进行到哪里? |
| 主要内容 | 指令、证据、反馈 | 进度、产物、记录 |
| 是否全部交给模型 | 属于当前输入内容 | 不一定 |
| 核心作用 | 帮助模型判断下一步 | 记录和恢复任务进展 |
可以把它们理解成:
上下文是工人当前手里的施工说明,任务状态是整个工程的进度记录表。
任务状态可以持久化保存,但每一轮不需要把完整状态都交给模型。
七、Agent 执行一半中断,Harness 怎么恢复?
假设 Agent 正在执行一个比较复杂的任务。
任务包含:
读取 Excel。
删除重复数据。
统一日期格式。
检查文件。
交付结果。
执行到第三步时,服务器突然重启。
如果系统没有保存任务进度,就可能需要重新开始。
对于长时间运行的 Agent,这显然不理想。
因此,Harness 可以配合状态存储机制实现断点恢复。
7.1 什么是 Checkpoint?
Checkpoint 可以理解为任务的检查点。
它记录任务在某个阶段的必要状态。
例如:
任务 ID:task_001
已完成:
– 文件读取
– 重复数据清理
执行中:
– 日期格式统一
未完成:
– 文件验证
– 最终交付
输出文件:
cleaned.xlsx
当前状态:
运行中断,待恢复
恢复时,Harness 读取这些记录。
但这里有一个关键细节:
记录某个动作已经发出,不代表动作一定成功。
例如:
Harness 向外部服务发出了上传请求。
请求发送后,网络突然断开。
此时可能存在三种情况:
-
上传没有发生。
-
上传已经成功。
-
上传只完成了一部分。
如果系统直接重新上传,可能发生重复操作。
尤其是发送邮件、支付、创建订单等操作,重复执行可能造成严重后果。
因此,正确的恢复过程应该是:
任务发生中断
|
v
读取保存的任务状态
|
v
核对实际文件或外部系统状态
|
v
确认已经完成的操作
|
v
识别尚未完成或状态不明的操作
|
v
决定继续、补查或重试
|
v
恢复后续任务执行
对于可能重复产生副作用的操作,还可以采用幂等键、操作 ID 或去重机制。
7.2 为什么不能只对模型说“继续”?
因为模型可能不知道:
-
哪些操作已经成功。
-
哪些文件已经生成。
-
哪些请求仍然在执行。
-
哪些操作可以安全重试。
所以:
断点恢复不是简单恢复一段聊天记录,而是恢复任务状态并核对真实执行结果。
需要注意,持久化和断点恢复并非所有 Harness 都自动具备的能力。
简单 Agent 可能只需要内存中的短循环;复杂任务才会更依赖持久化状态。
八、为什么权限管理也是 Harness 的职责?
Agent 能够提出操作请求,不代表所有请求都应该被执行。
例如,用户要求:
清理 Excel 文件,但不要删除原始数据。
模型却提出:
{
"tool": "delete_file",
"arguments": {
"path": "data.xlsx"
}
}
这时候能不能直接执行?
显然不应该。
因为这个请求违反了用户要求。
Harness 应该在实际执行路径上落实必要的检查。
例如:
-
当前工具是否允许使用?
-
文件路径是否在授权范围内?
-
是否允许修改原始文件?
-
是否需要用户确认?
-
操作是否超过任务允许的权限?
这里存在一个非常重要的区别:
Prompt 中写着“禁止删除原始文件”,不等于系统真正拥有阻止删除的能力。
Prompt 主要用于指导模型行为。
真正的权限控制还需要执行程序和运行环境实施约束。
例如:
-
只读权限。
-
沙箱隔离。
-
文件访问范围限制。
-
工具白名单。
-
高风险操作确认。
因此:
模型负责提出动作,Harness 和执行环境负责落实可检查的执行边界。
九、为什么 Harness 还要控制预算和执行次数?
想象一个 Agent 不断重复下面的过程:
模型思考
|
v
调用工具
|
v
执行失败
|
v
模型再次思考
|
v
重复调用工具
|
v
继续失败……
如果没有控制机制,任务可能一直运行下去。
这会造成:
-
Token 消耗持续增长。
-
工具调用次数过多。
-
执行时间过长。
-
资源和费用浪费。
-
Agent 陷入没有进展的循环。
因此,Harness 通常需要设置运行预算。
例如:
| 最大执行轮数 | 限制模型与工具的循环次数 |
| 时间限制 | 避免任务无限运行 |
| Token 预算 | 控制模型输入输出规模 |
| 费用预算 | 控制调用成本 |
| 工具超时 | 避免工具一直没有响应 |
| 取消机制 | 允许用户终止任务 |
但是:
达到预算上限,不等于任务已经完成。
例如,Agent 执行到第 20 轮,触发了最大执行次数限制。
此时任务停止。
但是结果可能仍然没有达到要求。
因此,系统应该区分:
-
成功完成。
-
运行失败。
-
用户取消。
-
超过预算。
-
暂停或等待。
-
结果需要进一步验证。
不能把这些情况都当成任务成功。
十、模型说完成,为什么不代表任务真正完成?
这是 Agent 工程实践中非常重要的一点。
假设用户要求:
帮我修复 Python 项目中的 Bug,并确保原来的测试全部通过。
模型修改代码后回复:
我已经修复完成。
这是否意味着任务成功?
不一定。
因为模型可能只是认为代码已经修好,但并没有真正运行测试。
即使修改命令执行成功,也只能证明代码操作已经发生,不能证明业务行为正确。
因此,Harness 还需要组织必要的完成检查。
例如:
模型修改代码
|
v
Harness 调用测试工具
|
v
获得真实测试结果
|
v
检查是否满足验收要求
|
+—- 测试失败 —> 继续修复
|
+—- 测试通过 —> 检查其他要求
|
v
任务验收通过
这里要区分三个概念。
第一,模型认为完成。
只是模型输出的判断。
第二,工具执行成功。
只说明某次工具操作成功。
第三,任务真正完成。
表示最终结果满足明确的任务要求,并通过必要验证。
这三个概念不能混淆。
对于代码修复任务,可以通过测试和构建检查提供完成依据。
对于文件处理任务,可以检查输出文件及其内容。
对于无法完全自动验证的复杂任务,则可能需要人工验收。
Harness 可以组织完成判断,但不会自动知道所有业务场景下什么才算正确。
十一、Harness 与 Host、Skill、Framework 到底有什么区别?
在 Agent 开发中,以下几个概念经常同时出现:
-
Agent。
-
LLM。
-
Host。
-
Harness。
-
Framework。
-
Skill。
-
Tool。
它们之间存在联系,但侧重点不同。
11.1 Harness 和 Host 的区别
Host 中文通常称为宿主。
它可以理解为负责承载和管理 Agent 的应用程序。
例如:
宿主可能负责:
-
模型调用。
-
Skill 发现和加载。
-
文件读取。
-
工具管理。
-
上下文维护。
Harness 则更强调:
围绕模型组织任务执行的运行机制。
例如:
-
如何执行模型与工具之间的循环?
-
如何根据工具结果继续执行?
-
如何保存任务状态?
-
如何管理运行权限?
-
如何判断任务是否完成?
所以可以这样理解:
Host 更强调谁在运行 Agent,Harness 更强调 Agent 的任务怎样持续运行。
但二者并不是严格互斥的两个模块。
在很多项目中,宿主应用本身就实现了 Harness。
11.2 Harness 和 Skill 的区别
Skill 可以理解为专业操作手册。
例如:
一个 table-cleaning Skill 告诉模型:
读取 Excel 文件。
删除重复数据。
统一字段格式。
验证处理结果。
但 Skill 只是提供工作方法。
它不会因为被模型读取,就自动执行 Python。
Harness 负责组织模型按照这些步骤工作,并协调实际工具调用。
因此:
Skill 解决“应该怎么做”,Harness 解决“怎样让任务持续执行”。
11.3 Harness 和 Framework 的区别
Framework 是框架。
可以把它理解为开发 Agent 时使用的一套工具箱。
例如,一个框架可能提供:
-
模型调用接口。
-
工具注册机制。
-
消息管理。
-
状态存储。
-
执行循环。
开发者可以使用这些组件构建 Agent。
但是:
使用了 Agent 框架,并不一定意味着已经拥有完整的 Harness 能力。
原因在于:
有的框架只提供基础组件,需要开发者自己组合。
有的 SDK 则已经封装好了模型循环、工具调度、状态管理等运行机制。
所以是否具备完整 Harness 能力,需要看实际实现。
不能仅凭使用某个框架,就认为权限、预算、恢复和任务验收等问题已经全部解决。
11.4 整体关系总结
| Agent | 围绕目标工作的整体智能系统 | 完整工厂 |
| LLM | 理解问题、生成决策 | 大脑 |
| Prompt | 表达目标和约束 | 工作要求 |
| Skill | 提供专业操作方法 | 操作手册 |
| Tool | 真正执行具体动作 | 双手 |
| Host | 承载和管理 Agent 的程序 | 管理应用 |
| Harness | 组织持续执行与运行控制 | 调度机制 |
| Framework | 提供开发组件和封装 | 工具箱 |
十二、从零开发一个 Agent,最基础的 Harness 需要什么?
对于一个简单 Agent,不需要一开始就实现所有复杂功能。
可以先建立一套最小运行循环。
第一阶段:实现基础执行能力
需要能够:
接收用户任务。
准备模型输入。
调用大模型。
识别模型输出的工具请求。
执行被允许的工具。
将执行结果交给下一轮模型。
在合理条件下结束任务。
这是基础 Harness 的核心。
第二阶段:增强运行可靠性
当任务复杂度提高,可以继续加入:
-
上下文整理与压缩。
-
错误处理和重试。
-
超时与取消机制。
-
任务进度记录。
-
运行预算。
-
结果验证。
第三阶段:支持长任务和高风险操作
对于更复杂的系统,可以继续加入:
-
持久化状态。
-
Checkpoint 检查点。
-
中断恢复。
-
工具权限管理。
-
沙箱隔离。
-
幂等控制。
-
审计日志。
-
人工审批机制。
具体需要哪些能力,取决于任务和安全要求。
例如,一个只负责查询天气的简单 Agent,与一个能够修改代码、执行命令并部署服务的 Agent,对 Harness 的要求显然不同。
十三、为什么同一个模型,在不同 Agent 系统中的表现可能不同?
理解 Harness 以后,就能够回答另一个重要问题。
假设两个 Agent 使用完全相同的大模型。
为什么最终执行效果可能不一样?
原因可能包括:
第一,上下文不同。
两个系统提供给模型的资料、历史结果和规则不同。
第二,工具不同。
一个 Agent 只能读取文件,另一个还能够执行 Python 和测试代码。
第三,执行反馈不同。
一个系统只告诉模型“执行失败”,另一个能够返回具体错误信息。
第四,运行策略不同。
一个系统遇到失败直接结束,另一个可以根据错误信息重新规划。
第五,验证机制不同。
一个系统只要模型说完成就停止,另一个要求通过实际测试。
因此:
Agent 的能力和效果,不仅取决于模型本身,也受到 Harness、工具、上下文和执行环境的影响。
这也是为什么同一个大模型,接入不同的 Agent 系统后,可能表现出不同的任务执行能力。
十四、面试官问:Agent Harness 到底是什么?
可以这样回答:
Agent Harness 可以理解为围绕大模型的一套运行支撑机制,核心是组织模型调用、工具执行和结果反馈,使模型能够根据实际执行结果连续推进任务。
首先,大模型负责理解用户目标和判断下一步操作,但模型输出的工具调用只是一个请求。真正的文件读取、代码执行或接口调用,需要外部程序完成。
Harness 负责接收这些请求,检查参数和权限,协调工具执行,再把实际结果提供给下一轮模型调用。
其次,对于复杂的多步骤任务,Harness 还需要组织上下文和管理任务状态。上下文管理决定模型当前需要看到哪些信息,任务状态记录任务进度,并可以配合持久化机制支持中断恢复。
另外,Harness 还需要落实运行预算、超时、取消和必要的完成检查,避免 Agent 无限执行,或者仅凭模型声明就认定任务成功。
因此,模型负责理解和决策,工具负责实际操作,而 Harness 负责协调它们如何持续、可控地运行。
至于 Agent Framework,它可以提供构建 Harness 的组件,也可能已经封装了运行机制,具体取决于框架或 SDK 的实际能力。
十五、总结
通过本文,我们可以得出以下结论。
第一,模型发出工具调用请求,不等于工具已经执行。
真正的操作仍然需要外部程序完成。
第二,Agent Harness 的核心是执行循环。
通过模型决策、工具执行、结果反馈和再次决策,使 Agent 能够连续推进任务。
第三,Harness 需要管理模型上下文。
因为每一轮模型需要的信息不同,不能无限制地把全部历史内容重复输入。
第四,任务状态与上下文不是一回事。
上下文记录模型当前需要看到的信息,任务状态记录整个任务的进度和结果。
第五,复杂任务需要恢复和运行控制。
中断恢复需要核对真实执行状态,不能只让模型重新说一句“继续”。
第六,任务停止与任务完成不同。
达到预算、工具调用成功或模型宣布完成,都不一定代表最终结果满足用户要求。
第七,Harness、Host 和 Framework 之间没有绝对固定的模块边界。
Host 更强调运行应用,Harness 更强调执行机制,Framework 则提供实现这些能力的组件或封装。
最后,用一句话总结全文:
模型负责思考,工具负责执行,Harness 负责把模型和工具组织成连续、可控、可验证的任务运行过程。
这也是 Agent Harness 相比单纯为大模型接入几个工具,更有价值的地方。
网硕互联帮助中心




评论前必须登录!
注册