跳转到内容

模型为什么需要 Harness:从一次推理到可运行系统

很多人对 Agent 有一个误解:模型能力继续提升,外面的工程迟早会变薄。

实际情况往往相反。模型越能理解目标、调用工具和处理长任务,我们越需要明确它能看什么、能做什么、做到哪一步、失败后怎样恢复,以及谁有资格宣布完成。

模型降低了生成决策的成本,没有降低系统承担后果的成本。

包围模型、让它能够安全运行的这一整套东西,可以统称为 Agent Harness

一、只调用模型,为什么还不是一个系统

Section titled “一、只调用模型,为什么还不是一个系统”

一次最简单的模型调用通常只有三件事:准备输入、请求模型、读取输出。

response = model.generate(messages)
print(response.text)

这段代码可以回答问题,却无法独立完成现实任务。只要加入一个“帮我处理退款”的需求,新的问题马上出现:

  • 客户是谁,订单是哪一笔?
  • 退款政策来自哪里,当前版本是什么?
  • 模型能否直接退款,还是只能提出建议?
  • 金额和币种怎样验证?
  • 工具超时后能否重试?
  • 第一次请求其实已成功,第二次重试会不会重复退款?
  • 退款完成以后,谁读取数据库确认终态?
  • 敏感信息能否进入日志?

这些都不是“再写一句 Prompt”能解决的问题。它们属于身份、上下文、工具、状态、权限、可靠性和审计。

换句话说:模型给出候选动作,Harness 决定候选动作能否变成真实动作。

这套教程采用下面的定义:

Agent Harness 是包围模型的执行系统。它负责装配上下文和工具,管理状态与生命周期,执行并约束动作,收集环境反馈,记录证据,并决定循环是否继续。

Harness 不是某个产品名称,也不等于 Agent Framework。你可以用一个 SDK 构建 Harness,也可以用普通 Python、数据库、队列、沙箱和日志系统自己组合。

框架提供的是零件和默认值。Harness 是这些零件在具体应用中形成的运行边界。

OpenAI Agents SDK 仓库页面

图 1:OpenAI Agents SDK 用 Agent、Runner、Tool、Handoff、Guardrail、Session 和 Trace 组成轻量执行框架。来源见文末。

三、一套 Harness 至少承担八类责任

Section titled “三、一套 Harness 至少承担八类责任”

1. Context Assembly:给模型准备什么

Section titled “1. Context Assembly:给模型准备什么”

模型每一次决策都依赖当前输入。Harness 要决定:

  • 放入哪些系统规则;
  • 提供哪些工具定义;
  • 取回哪些历史状态;
  • 检索哪些外部证据;
  • 哪些内容应该压缩;
  • 哪些不可信文本必须与系统指令隔离。

上下文不是仓库。把所有历史、所有工具和所有文档塞进去,既浪费预算,也会增加冲突和注入风险。

2. Model Adapter:怎样调用不同模型

Section titled “2. Model Adapter:怎样调用不同模型”

不同模型在 Tool Call、结构化输出、并行调用、上下文长度、缓存和错误返回上并不完全一致。

Harness 需要把供应商差异转换成应用可以理解的接口,同时保留必要的能力差异。所谓“随时切换模型”,如果只统一了请求格式,却没有验证行为变化,很容易变成虚假的可移植性。

工具层至少需要处理:

  • 参数验证;
  • 身份和授权;
  • 超时、重试与取消;
  • 结果截断和错误整形;
  • 并行与依赖;
  • 有副作用动作的幂等;
  • 运行环境和网络边界。

模型说“调用退款工具”,不代表应用必须照做。Tool Runtime 才是执行动作的地方。

4. State Management:事实保存在哪里

Section titled “4. State Management:事实保存在哪里”

一次运行可能跨越几十步,也可能隔夜等待人工批准。Harness 要保存当前任务、工具结果、计划、工件、预算和待办事项。

消息历史可以帮助模型理解对话,但它不是可靠的状态数据库。关键状态应该结构化、可版本化,并有明确的权威来源。

5. Policy and Guardrails:哪些动作不允许

Section titled “5. Policy and Guardrails:哪些动作不允许”

安全规则不能只写在 System Prompt 里。模型可以理解规则,但执行系统必须独立检查高风险动作。

常见控制包括:目录和域名白名单、工具级权限、金额上限、敏感字段过滤、人工审批、速率限制,以及删除、付款、发布等动作的二次确认。

6. Loop Control:什么时候继续或停止

Section titled “6. Loop Control:什么时候继续或停止”

Harness 负责运行 Agent Loop,也要负责限制 Loop。

它需要管理最大轮次、Token 预算、总时长、重复动作、无进展检测,以及成功、失败、暂停和取消等终态。没有这些限制,自治很容易退化成无限重试。

7. Observability and Evidence:发生了什么

Section titled “7. Observability and Evidence:发生了什么”

一次 Agent Run 不应只留下最后一句回复。至少要能追踪模型调用、工具调用、Handoff、Guardrail、错误、延迟、Token 和关键状态变化。

Trace 回答发生了什么,Evidence 回答任务是否完成。两者相关,但不能混为一谈。

Agent 可能运行在聊天界面、IDE、后台任务、客服系统或移动端。Harness 需要把内部事件转换为产品能理解的流:文本增量、工具状态、审批请求、工件、错误和恢复入口。

如果 Harness 只能在命令行输出日志,它还不是完整的产品运行层。

四、用一次退款看八类责任怎样协作

Section titled “四、用一次退款看八类责任怎样协作”

用户说:“上周买的耳机有杂音,帮我退款。”

一个可靠 Harness 的处理顺序可能是:

  1. 身份层确认用户和订单归属;
  2. 上下文层读取当前退款政策和订单状态;
  3. 模型判断还缺少哪些信息;
  4. 工具层读取物流和售后记录;
  5. 策略层判断金额是否需要人工批准;
  6. 模型生成退款动作参数;
  7. 工具层使用幂等键执行退款;
  8. 状态层保存交易编号和政策依据;
  9. 验证器重新读取订单与支付状态;
  10. 界面层向用户展示真实结果,而不是模型的预期结果。

在这条链里,模型负责理解开放语言、补全信息和选择候选动作。身份、授权、交易、终态和审计仍由确定性系统负责。

这就是 Harness 的核心价值:让概率决策进入确定性边界。

五、Harness 为什么会从几十行循环长成一套系统

Section titled “五、Harness 为什么会从几十行循环长成一套系统”

最小 Agent Loop 的确可以很短:调用模型,遇到工具请求就执行,把结果放回消息,再调用模型。

问题是,真实应用很快会遇到四种压力。

读天气和退订单不是同一级别的工具。动作一旦影响资金、数据、权限或公开内容,就必须增加审批、幂等、审计和回滚。

用户可能十分钟后才批准,外部系统可能两小时后返回,任务也可能因为进程升级而中断。状态和恢复会从“可选功能”变成基本能力。

运行越久,消息、工具和材料越多。Harness 必须选择、压缩和隔离上下文,否则模型会在一堆旧信息中做决定。

Demo 失败可以重跑,生产故障需要知道是模型、工具、权限、数据、网络还是状态出了问题。没有 Trace,团队只能盯着最终回复猜。

因此,Harness 变厚通常不是框架作者喜欢堆功能,而是现实责任逐层进入系统。

Harness Engineering 研究资料截图

图 2:Harness Engineering 开始成为独立讨论对象,因为模型之外的执行环境直接影响 Agent 的能力与可靠性。原始出处见图片来源台账。

OpenAI Agents SDK 和 PydanticAI 都重视普通 Python 的组合能力。模型可以选择工具,但应用能够用代码明确编排、验证和异常处理。[1][2]

优点是容易与现有工程体系结合;代价是长流程和复杂恢复需要额外设计。

2. Graph-driven:状态和路径显式化

Section titled “2. Graph-driven:状态和路径显式化”

LangGraph 把 State、Node、Edge、Checkpoint 和 Interrupt 放在核心位置。[3]

它适合分支多、需要人工介入和恢复的任务。代价是图会增加设计负担,简单问题可能被过度建模。

3. Model-driven:把更多编排交给模型

Section titled “3. Model-driven:把更多编排交给模型”

Strands 等项目强调模型负责规划和工具选择,应用用 Hook、Session 和策略限制运行。[4]

它能快速覆盖开放任务,但更依赖轨迹评测和权限约束。模型自由度越高,外部证据越不能少。

4. Runtime-driven:让持久化运行时拥有生命周期

Section titled “4. Runtime-driven:让持久化运行时拥有生命周期”

Temporal、DBOS 等 Durable Execution 系统不负责模型推理,却能保存流程历史、重试活动和跨故障恢复。[5][6]

在长时 Agent 中,它们常与 SDK 或图框架组合。Harness 负责决策,Durable Runtime 负责“即使机器重启,这件事也不会凭空消失”。

四条路线可以叠加。真正需要选择的是控制权和状态归属,不是框架 Logo。

误区一:Prompt 写清楚,权限就安全了

Section titled “误区一:Prompt 写清楚,权限就安全了”

Prompt 是行为指导,不是访问控制。高风险动作必须由代码和基础设施检查。

消息适合交流,不适合承担交易事实、锁、版本和幂等。结构化状态必须独立保存。

误区三:支持很多工具就是能力强

Section titled “误区三:支持很多工具就是能力强”

工具越多,选择混淆和攻击面越大。生产系统需要工具搜索、按需加载和最小权限。

Trace 能告诉你调用了什么,不能自动告诉你做得对不对。Eval 需要标准、数据集、环境检查或人工准则。

误区五:框架替你解决了生产问题

Section titled “误区五:框架替你解决了生产问题”

框架可以提供原语,无法替你定义订单成功、隐私边界、业务补偿和责任人。

Anthropic Building Effective Agents 原始文章

图 3:Anthropic 建议优先使用简单、可组合的模式。Harness 的目标不是追求复杂,而是承接现实责任。来源见文末。

八、30 分钟练习:写一份 Harness Contract

Section titled “八、30 分钟练习:写一份 Harness Contract”

选一个你熟悉的任务,例如“整理三份资料并输出摘要”,写出下面八项:

goal: 最终要产生什么可检查结果
context: 模型能看到哪些材料
tools: 可以调用哪些只读/写入工具
state: 哪些事实必须结构化保存
policy: 哪些动作禁止或需要审批
limits: 最大轮次、时间和预算
evidence: 怎样证明任务完成
terminal_states: success / failed / paused / cancelled

然后检查两件事:

  1. 把模型换成能力稍弱的模型,系统是否仍能安全失败?
  2. 运行到一半强制退出,是否知道从哪里恢复?

如果答案都是否,缺的通常不是新 Prompt,而是 Harness 责任。

模型可以提出行动。Harness 才能让行动成为受约束、可恢复、可观察的工程事实。

未来模型继续增强,Harness 不会消失。它会把更多精力从“教模型怎么说”转向“规定系统能做什么、怎样验证、怎样负责”。

下一讲进入 Harness 内部最小、也最容易失控的结构:Agent Loop。我们会从 ReAct 出发,解释一次运行怎样在推理、行动和观察之间循环,以及为什么停止条件比“继续努力”更重要。


[1] OpenAI, OpenAI Agents SDK. https://openai.github.io/openai-agents-python/

[2] Pydantic, PydanticAI. https://ai.pydantic.dev/

[3] LangChain, LangGraph Overview. https://docs.langchain.com/oss/python/langgraph/overview

[4] Strands Agents, Introducing Strands Agents. https://strandsagents.com/blog/introducing-strands-agents/

[5] Temporal, Durable Execution. https://docs.temporal.io/

[6] DBOS, Durable Workflows. https://docs.dbos.dev/

[7] Anthropic, Building Effective Agents. https://www.anthropic.com/engineering/building-effective-agents

[8] OpenAI, A practical guide to building agents. https://openai.com/business/guides-and-resources/a-practical-guide-to-building-ai-agents/