一文弄懂 Agent Harness 与 Agent Runtime 的区别

Cosolar 6 阅读 AI Agent架构与设计

同一个 Agent,同一款模型,换个 Runtime 就能稳定上线,换个 Harness 就能彻底重写人格。

本文把 Agent 系统的核心术语——Harness(线束/驱动程序)Runtime(运行时)——一次性掰开揉碎,从定义、职责、生命周期、接口、资源管理、安全隔离、可扩展性、可观察性、部署模型、性能、故障恢复到典型用例逐一对比,并给出判别方法、分层架构图、真实框架对照表与选型清单,帮你彻底告别"这俩词是不是一个东西"的困惑。

本文参考了 Smartpig (@Smartpigai) 的 X Article 原文,并融合了 OpenClaw、Claude Code、AgentScope、QwenPaw、AWS AgentCore、Azure Agent Service 等真实项目的落地经验。

一、开篇:一个让所有人绕晕的命名事故

2026 年上半年,AI Agent 领域出现了一场教科书级别的"术语漂移"。

同一批开发者,同一个社区,在讨论同一个问题——“我的 Agent 外面那一层工程化的东西到底该叫啥”——却分裂成了两个阵营,而且双方都不是在瞎说。

阵营 A:叫 Harness。 OpenClaw、Claude Code、Hermes 的社区里,这个词已经火到成了"Agent 工程"的代名词。微软将其称为"runtime 脚手架 (scaffolding)“,用以驱动模型调用、管理上下文并让智能体能够持续前进。业界甚至冒出了 Harness Engineering(线束工程) 这个新学科,专门研究"模型外面那一圈东西该怎么造”。主流观点将其凝练为一个公式:Agent = 模型 + Harness

阵营 B:叫 Runtime。 传统软件工程的直觉派坚信,任何"负责调度、执行、管理状态的东西"都理应叫运行时。Google 云架构指南明确指出:“代理运行时是代理的应用逻辑运行所在的计算环境”。Erlang/OTP 有 Erlang Runtime,Node.js 有 V8 + libuv Runtime,Java 有 JVM——现在 Agent 也需要一个 Agent Runtime,来管理它的进程、隔离环境、资源调度与生命周期。

于是你在 GitHub README、技术博客、架构评审会上会看到这种诡异景象:

“我们基于自研的 Agent Runtime,实现了一套完整的 Harness Engineering 方案,通过 Harness FrameworkRuntime 进行增强……”

一个句子里 Runtime 和 Harness 像同义词一样自由互换。评论区因此吵得不可开交。

这篇文章的目标只有一个:终结这场混淆。

读完之后你应当能做到三件事:

  1. 用一句话说清两者的本质区别;
  2. 拿到任何一个开源 Agent 框架,在 30 秒内判断它属于哪一类(或者兼具两者);
  3. 在设计自己的 Agent 系统时,明确知道"这行代码该写在 Harness 层还是 Runtime 层"。

二、先回到源头:这两个词各自的历史包袱

混淆的根源不是概念模糊,而是两个词各自带着完全不同的语义包袱,而作者们在造词时都默认读者"懂我的包袱"。

2.1 Harness 的包袱:来自硬件和汽车

Harness 的英文本义是"马具"——套在马身上、连接缰绳与马车的整套皮带与金属件。

但它真正在工程界站稳脚跟,是在汽车线束(wiring harness)测试夹具(test harness) 这两个场景:

  • 汽车线束:发动机、ECU、方向盘、刹车、车灯之间的所有电线与接头。线束自己不产生任何能量,也不做任何决策,但它决定了信号能走哪条路、能被谁切断、断了之后车会不会自燃
  • 测试夹具:给一块电路板做可靠性测试时,把板子插进去的那套工装。板子是主角,夹具不改变板子的芯片,但它决定了板子能接触哪些探针、以什么电压供电、多久被复位一次

这两个场景的共性极其重要,请记住它:

Harness 是"连接件",不是"执行件"。 它自身不产生行为,它的价值在于约束、接线、保护

所以当业界把这个词借来形容 Agent 的外层工程时,继承的正是这层语义:模型是发动机,Harness 是线束——它不替模型思考,它决定模型能碰哪些工具、能看哪些上下文、哪一步必须先被人批准、出错时往哪里回滚。

更具体地说,Harness 是位于基础模型之上的应用层逻辑,为模型提供多步规划、工具调用、状态管理、策略控制等功能,使得一个原本只会生成文本的模型能够完成多步骤任务。如果把模型看作大脑,Harness 就是围绕大脑的工作台、笔记本、工具和权限系统

Harness Engineering 这门新学科的完整定义可以概括为一句话:

模型能力是概率的、会漂移的、偶尔会失控的,真正让 Agent 可用、可控、可演化的,是模型外面那一层工程化的"骨架":结构化的上下文、约束性的工具协议、生命周期的钩子、可恢复的状态、可观测的评估。

这个判断在多个真实落地上被反复验证过。例如淘天直播场景下的 Agent,被推到了一个极端苛刻的压力测试场:Agent 下发的指令即时生效且面向公众、错误无法撤回、代价是真金白银,而主播在镜头前根本没有余力逐条核验 Agent 的每个动作。这意味着 Agent 的安全边界必须由工程兜底,而不是靠人工复核——这正是 Harness 的主场。

2.2 Runtime 的包袱:来自操作系统和虚拟机

Runtime 的历史包袱则完全相反,它来自执行环境这条血脉:

技术 它的 “Runtime” 负责什么
JVM 字节码解释/编译、GC、类加载、线程调度
Erlang VM 进程创建/隔离、消息传递、容错监督树
Node.js (V8+libuv) 事件循环、非阻塞 IO、异步调度
WebAssembly 线性内存、指令解释、沙箱隔离
Kubernetes Pod 容器编排、网络/存储挂载、生命周期回调

它们的共性同样清晰:

Runtime 是"发动机+变速箱",它的天职是"让代码真正跑起来"。

在 Agent 语境下,Runtime 类似于"Agent 专用的 Lambda"——一个为智能体提供安全隔离执行环境、资源调度与限制、网络与凭证管理的基础设施层。它负责创建隔离会话(如容器或微 VM)、管理资源限额、控制网络出入、注入短期凭证、提供持久化状态与并发调度。

这是 Runtime 的领地,Harness 完全不碰这里。 你不会去问一辆车的线束"你的汽油燃烧效率是多少",同理你也不该让 Harness 去负责线程池大小、容器重启策略、GC 参数。

2.3 混淆的真正原因

那为什么大家还是把这两个词混用?三个真实原因:

  1. Agent 是新兴物种,没有成熟范式。 Java 生态花了 30 年才把 Runtime / Container / Framework / Library 的边界吵清楚。Agent 生态现在连"框架"这个词都还在被 AgentScope、LangGraph、CrewAI 各自重新定义。
  2. 现代 Agent 框架是"打包交付"的。 LangGraph 同时给你循环引擎(Runtime 属性)和检查点存储+人工审批(Harness 属性)。你装了一个包,等于同时装了两层,于是描述它就必然混着两个词。
  3. Harness 这个词太有魅力了。 它比 Runtime 更有画面感、更有"工程手艺"的暗示,因此在博客标题里传播得更快——但这造成了"凡是外层工程都叫 Harness"的滑坡。

认清这三点之后,混淆就不再是知识问题,而是选择问题:你必须主动给这两个词定死边界。

三、一句话定义 + 判别三问

下面这段是可以直接抄进团队 Wiki 的定义。

Agent Harness(智能体线束 / 驱动程序)

位于基础模型之上、负责组织智能体行为的软件层。 它包含提示工程、工具接口、执行循环、记忆和策略等,使得一个原本只会生成文本的模型能够完成多步骤任务。

Harness 是可替换的策略层——换一套 Harness,等于换掉 Agent 的人格、权限边界与工作方法论。


Agent Runtime(智能体运行时)

提供智能体实际执行环境的基础设施层。 类似于云函数或容器环境,负责调度和运行智能体逻辑及工具执行。

Runtime 是可替换的执行层——换一套 Runtime,Agent 的人格与提示词可以完全不变,但它的稳定性、并发能力与部署形态会变。

一句话对比:

Harness 定义了智能体"思考"和"行动"的方式;Runtime 负责在哪儿和怎样安全地执行这些动作。

更简练的版本:

Harness 决定 Agent “想什么、能做什么、被允许做什么”;Runtime 决定 Agent “在哪儿跑、跑多快、挂了怎么恢复”。

如果这句话你理解了 80%,剩下的就是把它落到判别标准上。面对任何一个 Agent 系统,问三个问题:

判别三问

Q1:这个模块改了,Agent 的"性格/行为/知识"会变吗?

  • 会变 → Harness
  • 不会变,只影响性能、稳定性、部署形态 → Runtime

Q2:这个模块的核心产出是"内容"还是"进程"?

  • 产出的是提示词、工具调用请求、记忆片段、评估报告 → Harness
  • 产出的是任务调度结果、线程池状态、checkpoint 文件、容器实例 → Runtime

Q3:把这个模块删掉,Agent 会"变笨/变坏"还是"跑不起来"?

  • 变笨或变危险(例如删掉工具权限校验,Agent 就开始越权) → Harness
  • 跑不起来(例如删掉进程管理器,整个服务直接崩) → Runtime

用这三问回看 QwenPaw v2.1.0 的 harnesses/ 子包,判断立刻清晰。这个子包的 docstring 写的是 “Third-party agent runtime integrations”(第三方 Agent 运行时集成)——注意它是在集成别人的 RuntimeHarnessRuntime 接管的恰好是四件 QwenPaw 必须亲自管、但不属于 Codex 自己执行核心的事:

  1. 生命周期编排:第三方 CLI 进程的启动、复用、停止;
  2. 信封协议归一化:把第三方流式输出翻译成自己的 AgentResponse / Message / Content 流,让前端、会话、记忆对"后端是谁"无感知;
  3. 能力投影:把自己的 Skills 与 MCP 服务器投影进第三方运行时,反向把对方自有的 Skills / MCP 只读发现回来;
  4. 安全审批:第三方 Agent 要改文件、执行命令、请求权限时,桥接到统一的 ApprovalService 由用户裁决。

这四项没有一项是"让代码跑起来",全部是"约束、接线、保护"——所以它是 Harness,而它被集成的 Codex / Qoder 才是 Runtime。 一个框架内部两个词各安其位,混淆自然消失。

四、职责拆解:两层各干什么

定义只是起点。真正的差别藏在职责细节里。

4.1 Harness 的七项职责

如 Credal 所述,Harness 负责智能体的执行循环和逻辑控制,具体包括:

# 职责 说明
1 执行循环 (Agent Loop) 控制模型与环境的交互步骤(ReAct、计划-执行等流程)
2 提示拼装与上下文管理 构造合理的提示,管理对话历史和记忆,有效引导模型
3 工具接口 定义并向模型公开可用工具,处理工具调用请求与结果反馈
4 消息/状态跟踪 跟踪会话内容与任务状态,用于历史持久化和任务恢复
5 输出解析与校验 解析模型输出、校验格式或语义,必要时重试或纠正
6 错误处理 识别运行时错误(工具失败、超时等),采取重试、更换工具、升级到人工审批或安全停止
7 子代理管理 协调多智能体的创建与合并结果,处理协作与冲突

简言之,Harness 就是构建在模型之上的逻辑层,负责**“想什么"和"怎么做”**。其目标是让模型的推理能力变成对现实有用的工作能力。

4.2 Runtime 的六项职责

Runtime 层着重于执行时的基础设施支持:

# 职责 说明
1 隔离与沙箱执行 每个会话在独立隔离环境(容器/微 VM)中执行,防止故障或恶意行为跨会话传播
2 资源限制 强制实施 CPU、内存、磁盘、令牌(API 调用)等限制,防止无限循环或资源滥用
3 网络和凭证控制 控制网络出入,限制可访问的 API;安全注入短期凭证,避免密钥暴露在模型上下文
4 持久化与检查点 为长时运行或并发任务提供状态持久化,允许会话重启时从检查点恢复
5 并发与可扩展性 调度和扩缩容多个会话,管理队列与并行执行,确保高负载下稳定运行
6 监控与审计日志 记录每次模型调用、工具执行、网络请求的追踪信息,支持调试与合规

简单来说,Runtime 负责执行环境和治理,包括安全、隔离、资源和监控等基础设施层面的内容。

4.3 职责分界线:一句话总结

应当将"网络出口控制、执行沙箱和凭证管理"等基础设施安全留给 Runtime 实现,而将"工具调用权限和输出验证"等业务安全留给 Harness。

五、生命周期:从用户请求到任务结束

智能体从用户请求到任务结束的生命周期通常经历以下步骤:

  1. 用户发起请求 → Harness 接收
  2. Harness 加载 任务指令、上下文和策略
  3. Harness 调用模型 生成下一步行动
  4. 模型请求调用工具? → Harness 将调用分发到 Runtime
  5. Runtime 在隔离环境中执行 工具代码或命令
  6. Runtime 返回结果 → Harness 接收
  7. Harness 继续循环(可能再调模型或进一步工具)
  8. 达到终止条件?(任务完成 / 错误上限 / 超时)→ 结束
  用户                    Harness                     Runtime
   |                         |                           |
   |--- 请求 --------------->|                           |
   |                         |--- 加载上下文+策略        |
   |                         |--- 调用模型 ------------->|
   |                         |<-- 模型返回行动 ----------|
   |                         |                           |
   |                         |--- 需要工具? ------------>|
   |                         |    分发工具调用           |
   |                         |                           |--- 隔离执行
   |                         |<-- 返回结果 --------------|
   |                         |                           |
   |                         |--- 继续循环 ...           |
   |                         |--- 终止条件满足?          |
   |<-- 返回最终结果 --------|                           |
   |                         |                           |

关键读法: Harness 是循环的驱动者,Runtime 是工具执行的承包者。整个生命周期中,Harness 调用了多少次模型、Runtime 执行了多少次工具,都可以通过 trace ID 端到端追溯。

六、接口与资源管理

6.1 接口形态对比

Harness 接口 通常由具体的智能体框架或 SDK 提供:

  • Microsoft Agent Framework:通过 create_harness_agent(Python)或 AsHarnessAgent(.NET)等工厂方法生成带有默认功能的 Harness 智能体
  • 其他开源框架:LangChain、CrewAI、Anthropic Agents SDK、OpenAI Agents SDK 等也提供相应接口,让开发者定义提示、工具和记忆
  • 工具集成协议:MCP(Model-Context Protocol)让 Harness 通过统一协议调用外部工具服务器
  • 暴露方式:通常以函数调用或服务方式暴露给应用,包括启动会话、发送用户消息、处理模型响应等方法

Runtime 接口 体现在对外的执行入口和管理控制面:

  • SDK / CLI:如 AWS AgentCore CLI 的 InvokeHarness 命令,将任务发给 Runtime 执行
  • 托管服务端点:Azure Agent Service、Google Gemini Runtime、AWS AgentCore 等提供 REST API 或托管服务端点
  • 管理操作:支持管理会话(启动、停止、检查点)和查询执行状态
  • 权限模型:例如 AWS AgentCore 要求调用 InvokeHarness 时对 Harness 资源和底层 Runtime 资源都具有权限
  • 透明性:Runtime 接口对上层透明,主要用于部署和监控——用户不必关注内部实现细节

6.2 资源管理分工

维度 Harness 资源管理 Runtime 资源管理
关注什么 模型上下文相关的资源 底层计算资源
token 管理 追踪对话历史长度和 token 使用,限制模型调用步数或费用 强制执行 API 调用令牌限制
CPU/内存 不关心 每个会话独立配额,如 AWS AgentCore 在每个微 VM 中分配固定内存和 CPU
调度与扩缩容 不关心 多会话间调度与扩缩容,将任务分发到可用节点或新启实例
关注点 逻辑正确性和上下文完整度 资源利用率和吞吐量

简言之:Harness 关注逻辑正确性,Runtime 是资源管理的第一责任层。

七、安全隔离:两层各管什么?

7.1 Harness 安全:业务逻辑层面的权限和护栏

Harness 从业务逻辑层面提供保护:

  • 工具权限:决定哪些工具可以被调用、哪些 API 可以访问
  • 参数校验:检查调用参数是否合法、过滤敏感信息
  • 人工审批:是否需要人工审批,以及审批的粒度
  • 输入/输出校验:对模型输出进行格式校验,必要时重试或用不同模型
  • 提示层防护:在提示中加入检测逻辑,避免模型进行未经授权的操作

7.2 Runtime 安全:环境隔离与系统防护

Runtime 从操作系统和基础设施层面提供保护:

防护维度 具体措施
进程隔离 每个会话在独立沙箱(容器或 Firecracker 微 VM)中运行,不共享文件系统和网络空间
网络出口控制 只有允许的域名或 API 可被访问,避免智能体随意外联
短期凭证注入 注入短期令牌供模型代码使用,避免长期密钥泄露在模型上下文中
系统加固 定期打补丁、监控恶意行为,提供审计日志

一句话总结:

将"网络出口控制、执行沙箱和凭证管理"等基础设施安全留给 Runtime;将"工具调用权限和输出验证"等业务安全留给 Harness。

八、可扩展性与可观察性

8.1 可扩展性对比

Harness 扩展:插件化设计

现代智能体平台通常提供可扩展机制,让开发者添加新工具、技能、记忆模块和处理逻辑:

  • AWS AgentCore:可挂载 AWS Skills(自研技能)、从 Git 或 S3 载入自定义函数库
  • LangChain:通过扩展 Tool 类添加第三方 API
  • DeepSeek Harness:提出"万物即插件"理念,将执行环境、工具都统一视为可插拔组件
  • Anthropic Agents SDK:允许注册自定义验证器或批准器
  • 扩展方式:编写中间件、回调(hook)或策略文件来增强功能

Runtime 扩展:环境配置和镜像

Runtime 主要通过环境配置和镜像来扩展:

  • 自定义容器镜像:预装特定库或依赖
  • 网络策略:配置网络出口规则和节点类型来满足不同性能需求
  • 边车 (sidecar):高级平台允许编写 sidecar 或网络策略插件来增强监控能力
  • 总体来说:Runtime 的可扩展性体现在运行时环境的可定制——选择或构建带有所需功能的沙箱环境,而不是在运行时中编写业务代码

8.2 可观察性对比

维度 Harness 可观察性 Runtime 可观察性
关注什么 上层事件日志 底层执行和安全日志
记录内容 每步对话、提示内容、模型决策、工具调用请求与结果 容器/会话启动、资源使用(CPU/内存)、工具执行入口与出口、网络请求审计
追踪系统 OpenTelemetry,如 OpenAI Agents SDK 默认开启全链路追踪,LangSmith 提供可视化调试 Prometheus、CloudWatch、Azure Monitor 等
关联方式 将用户输入、对话历史、内存状态纳入日志,以便回溯问题 通过共享 trace ID 将 Harness 的决策与 Runtime 的执行关联,实现端到端可追溯

正如 Credal 所建议的:审计跟踪应将 Harness 的决策与 Runtime 的执行关联起来,通过共享的跟踪 ID 实现端到端可追溯。

九、部署模型:三种经典模式

智能体系统的部署通常分为 Harness 层和 Runtime 层。常见模式有三种:

模式 1:一 Harness 一 Runtime(紧耦合)

应用逻辑与执行环境紧耦合,同一个仓库管理代码和基础设施。

  [Harness A] <--> [Runtime A]
  • 适用场景:初创团队快速迭代,单团队单项目
  • 优点:部署简单,调试方便,无跨团队协调成本
  • 缺点:无法独立扩展,环境差异难管理

模式 2:一 Harness 多 Runtime(多环境)

同一应用在不同环境(开发/测试/生产)中使用不同配置的 Runtime。

                   --> [Runtime: 开发沙箱]
  [Harness A] ---|--> [Runtime: 测试集群]
                   --> [Runtime: 生产集群]
  • 适用场景:需要在不同环境下应用不同网络或资源策略
  • 优点:同一套代码在不同环境下独立配置,安全隔离
  • 缺点:需要维护多套 Runtime 配置

模式 3:多 Harness 共用一 Runtime(平台化)

多个不同业务逻辑共用统一的执行平台,便于统一管理安全和监控。

  [Harness A] ---<
  [Harness B] ---|--> [统一 Runtime 平台]
  [Harness C] --->
  • 适用场景:大型企业,多团队共享基础设施,需统一治理
  • 优点:统一安全和监控,资源利用率高,治理效率高
  • 缺点:Runtime 成为单点,需要成熟的平台团队

在部署时,Harness 通常以应用服务形式存在(托管在云服务器或容器中),通过 API 或消息队列与前端通信;而 Runtime 则可能是容器集群、Serverless 函数平台或微 VM 托管服务。例如:

  • AWS AgentCore Runtime:按需启动微 VM 的托管服务
  • Azure Agent Service:以容器或函数形式部署
  • Google Gemini Enterprise:代理运行时以托管方式提供环境

十、性能与故障恢复

10.1 性能特征对比

维度 Harness 性能 Runtime 性能
主要影响因素 模型推理延迟和框架代码复杂度 底层执行效率和扩展能力
运行层级 应用层(Python/Node.js 服务) 容器、虚拟机、Serverless
典型开销 中间层延迟(对话管理、工具调用编排) 冷启动延迟、资源隔离开销
优化方向 并发队列、异步调用模型、对长对话适当压缩 自动扩缩容、预热实例、资源利用率优化
瓶颈所在 单次任务的响应速度与内部逻辑效率 总体吞吐和资源利用效率
扩展方式 逻辑优化(更好的提示、更短的工具链) 横向扩展(更多实例、更多节点)

简言之:Harness 更关注单次任务的响应速度与内部逻辑效率,Runtime 更关注总体吞吐和资源利用效率。

10.2 故障与恢复

Harness 故障:业务级失败

常见失败包括:模型返回格式错误、工具执行错误或超时、策略冲突等。

故障类型 恢复策略
模型输出格式错误 格式校验失败则重试或用不同模型
工具调用异常 重试、切换备用工具、请求人工介入
循环死循环/超时 根据策略限制终止
编译失败(代码智能体) 引导模型检查错误并修正
网络调用失败 稍后重试或跳过该步骤

良好的 Harness 会维护业务级别的状态快照,并在失败时保存上下文以便调查和重试。

Runtime 故障:基础设施级失败

主要是基础设施层面的故障,如容器崩溃、主机故障、网络中断等。

故障类型 恢复策略
容器/微 VM 崩溃 依赖持久化状态从上次检查点恢复
主机故障 在新节点重建环境,根据检查点和日志恢复
内存超限 (OOM) 在安全范围内终止进程并报告错误
网络中断 与 Harness 协调决定后续措施

关键结论:故障恢复由两层协同实现——Harness 负责业务级的重试与备选策略,Runtime 负责环境级的重启与状态恢复。

十一、深度对比:七个维度的全景拆解

把前面散落的点收拢成一张七维对比总表:

维度 Agent Harness Agent Runtime
本质角色 约束层 / 策略层 / 接口层 执行层 / 平台层
核心问题 “Agent 该看到什么?能做什么?谁批准?错了算谁的?” “任务怎么调度?进程怎么起?状态怎么存?崩了怎么救?”
关键产物 提示词、工具协议、记忆库、钩子、评估报告、审批记录 进程/线程、事件循环、checkpoint、沙箱、资源配额
替换成本 低——换人格、换工具集、换记忆策略,业务代码基本不动 高——换调度模型、换存储引擎、换部署拓扑,往往牵动全栈
典型关注人 Agent 产品经理、Prompt 工程师、业务方 SRE、基础架构、平台工程
变更频率 高——人格、技能、知识几乎每天都在改 低——运行时是"一次设计、长期稳定"的底座
失败的后果 Agent 变笨、越权、答非所问(功能错误 Agent 跑不动、OOM、数据丢失、不可恢复(系统故障

十二、三个最容易出错的地方

12.1 状态管理:两个截然不同的"状态"

这是概念混淆的重灾区,也是最容易在生产事故中互相甩锅的一维。

Harness 的状态是"认知状态",跨会话存活。 它回答"这个 Agent 长期是谁"。典型内容:长期记忆、技能库、知识图谱、用户画像、人格设定。它的生命周期以"天/月/年"计,持久化在文件、向量库、Git 仓库里,不依赖进程存活

Runtime 的状态是"执行状态",会话内存活。 它回答"这次任务进行到哪"。典型内容:当前消息队列、未完成的子任务 DAG、临时 checkpoint、活跃沙箱、连接池。它的生命周期以"秒/分钟"计,持久化在内存、本地盘、Redis 里,高度依赖进程或进程组存活

生产环境最经典的事故就发生在这里:Runtime 挂了,checkpoint 还在,但 Harness 层的审批记录丢了——重启后 Agent 不知道自己刚才批准过什么,于是要么重复申请(骚扰用户),要么直接执行(安全事故)。反向也有:Harness 层的记忆库迁移了,但 Runtime 的沙箱状态还指向旧路径——Agent 记忆完好但现场全失,用户看着 Agent"失忆"。

这类问题的根因从来不是代码 bug,而是把两种状态混在同一个存储、同一条清理策略里。

12.2 钩子(Hook)属于哪一层?

一个极易出错的地方:很多人以为"钩子"是 Runtime 的东西,因为 Runtime 里确实有 Pod Lifecycle HooksK8s init container

关键在于钩子挂载在什么事件上

  • Harness 钩子挂在语义事件上:before_inference(注入上下文)、after_tool_call(做安全审查)、on_memory_flush(沉淀记忆)、on_evaluation(打分归档)。
  • Runtime 钩子挂在系统事件上:pre_starton_oompost_commiton_crash_restart

一个反直觉但极重要的例子:工具审批钩子属于 Harness,哪怕它的实现里真的会起一个异步线程等用户点按钮。 因为线程只是实现手段,钩子的语义是"这个工具调用是否被允许"——这是策略问题,不是调度问题。

结论:判断钩子的归属,看它回答的问题,不看它用了多少代码。

12.3 工具(Tool)到底算谁的?

工具横跨两层,必须拆开看:

工具 = 工具 Schema(Harness) + 工具执行器(Runtime)
  • Harness 拥有:工具的 JSON Schema 定义、工具选择策略、工具结果的摘要与格式化、工具调用的审计记录、工具的权限白名单
  • Runtime 拥有:工具进程的实际执行、并发控制、超时与重试、沙箱隔离、返回值的大对象落盘、执行环境的凭据注入。

再看 QwenPaw 的 capabilities/ 子包,它做的是双向投影:把自己的 Skills 与 MCP 服务器投影进第三方运行时,反向把 Provider 自有的 Skills / MCP 只读发现回来。这里的 MCP 服务器密钥在内存里是 SecretStr,投影到第三方进程时以指纹哈希做隔离与去重、绝不落盘。Schema 与凭据的治理是 Harness 的事;而第三方 CLI 进程本身能不能起、起在哪个 cwd,是 Runtime 的事。

十三、一张图:Agent 系统分层全景

把上面所有维度收拢成一张分层视图。记住:箭头从下往上,下层为上层提供服务,上层从不修改下层。

+----------------------------------------------------------------+
|                    (1) 业务层 / 应用层                           |
|      产品逻辑、用户交互、场景 Skill、业务 API 编排                 |
+----------------------------------------------------------------+
|                    (2) 编排层 / Loop(循环)                      |
|   Plan -> Act -> Observe -> Evaluate -> Revise 的迭代循环         |
|   * 目标函数与停止条件 * 子 Agent 委派 * 评估器 * 预算护栏         |
+----------------------------------------------------------------+
|                    (3) HARNESS 层  ** 本文主角之一                |
  |  上下文工程   |   工具治理    |   记忆与状态   |  安全与评估 |  
  | * system prompt| * Schema 定义 | * 长期记忆     | * 权限白名单 |  
  | * 知识注入     | * 选择策略    | * 工作区 SoT   | * 审批钩子   |  
  | * 压缩/裁剪    | * 结果格式化  | * 事实提炼     | * 评估与审计 |  
  | * 上下文窗口   | * 能力投影    | * 混合检索     | * 纵深防御   |  
+----------------------------------------------------------------+
|                    (4) RUNTIME 层  ** 本文主角之二                |
  |  进程与调度   |   执行沙箱    |  状态与检查点  |  资源与网络 |  
  | * 进程管理     | * 容器/微 VM  | * checkpoint   | * 资源配额   |  
  | * 事件循环     | * 凭据注入    | * 会话恢复     | * 重试/超时  |  
  | * 并发隔离     | * 逃逸防护    | * 持久化后端   | * 可观测埋点 |  
  | * 故障重启     | * 环境镜像    | * 分布式同步   | * SLO 监控   |  
+----------------------------------------------------------------+
|                    (5) 基础设施层                                |
|      计算 / 存储 / 网络 / 模型网关 / 向量库 / 容器编排             |
+----------------------------------------------------------------+

三点关键读法:

  1. Loop(编排层)是第三类,不要把它塞进前两者。 循环决定"下一步干什么",是策略;Harness 决定"这一步能干什么",是约束;Runtime 决定"这一步在哪儿干",是执行。三者是正交的。
  2. 第 3 层和第 4 层之间的边界是整篇文章的核心。 一条粗线,上边全是"语义",下边全是"系统"。
  3. 编排层与 Harness 层的边界也会随框架不同而移动——有的框架把评估器放进 Harness,有的放进 Loop。这不重要,重要的是你要在自己的系统里明确划线

十四、真实开源框架对照表

抽象讲完,落到实际项目上。这张表可以直接用于技术选型。

项目 主要归属 它强在哪一层 备注
OpenClaw / Hermes / Claude Code Harness 工作区 + 技能 + 长期记忆 + 本地 Shell 约定 个人助手形态的 Harness 标杆
AgentScope Java 1.1.0 两者兼备 HarnessAgent 不替换 ReActAgent 的推理循环,在循环关键时机插入 Hook AbstractFilesystem 实现"一套逻辑、多种部署形态"
QwenPaw v2.1.0 harnesses/ Harness(集成他人 Runtime) 生命周期编排、信封归一化、能力投影、安全审批 把"用哪个 Agent 干活"变成配置而非架构
LangGraph 两者兼备 状态机编排(Loop)+ Checkpointer(Runtime)+ interrupt(Harness 审批) 边界最模糊的一档
CrewAI / AutoGen 偏 Harness 角色定义、任务分配、协作协议 执行底座通常交给外部 Runtime
Microsoft Agent Framework Harness create_harness_agent / AsHarnessAgent 工厂方法 微软称 Harness 为"runtime 脚手架 (scaffolding)"
AWS AgentCore 两者兼备 InvokeHarness CLI + 微 VM 托管 Runtime 需对 Harness 和 Runtime 资源都有权限
Azure Agent Service 两者兼备 Prompt Agent / Hosted Agent 提交到托管环境 将 Harness 逻辑提交到 Runtime 执行
Google Gemini Runtime Runtime 托管方式提供环境 Google 称"代理运行时是代理的应用逻辑运行所在的计算环境"
Devin / Codex / Trae Agent 产品级整体 Harness + Runtime + UI 一体交付 你拿不到分层,只有黑盒
Erlang VM / JVM / Node.js 纯 Runtime 进程隔离、调度、GC 无 Harness 语义,Agent 场景需自建上层
Kubernetes 纯 Runtime 编排、隔离、自愈 常见误区是把它当 Agent 的 Harness——它只管"跑在哪",不管"跑什么"

选型前务必问自己:我需要的是 Harness 能力还是 Runtime 能力?如果两者都需要,这个项目在两层的边界划在哪里?

十五、典型用例

用例 1:复杂多步骤任务(重 Harness)

自动化编程辅助、报表生成或数据分析等需要多轮交互的任务,通常依赖全面的 Harness。此类场景要求对话、上下文和外部工具(编译器、数据库、搜索等)的紧密协同,强调容错和长期记忆。

典型产品:Anthropic 的 Claude Code、OpenAI 的 Codex。这些是带有强大 Harness 的代码智能体实例。Harness 的设计细节(如测试失败时的回退策略、分布式缓存等)直接决定智能体的效果。

用例 2:轻量级自动化任务(重 Runtime)

简单的自动化场景,如批量客服回复、报警监控触发等,可能更关注稳定执行而不需要过多定制的对话逻辑。这时可以主要依赖 Runtime 平台:将模型调用和逻辑打包成函数或容器,由云平台负责扩容与运维。

典型场景:在 Azure Functions 或 AWS Lambda 上部署的简单问答或数据查询智能体,将更多任务交给了 Runtime。此时,Harness 只需提供最基本的提示和异常处理,复杂度较低。

用例 3:企业多智能体场景(多 Harness + 共享 Runtime)

需要同时管理多个不同目的智能体的大型系统,通常会采用多个 Harness + 共享 Runtime 的方案。不同团队开发各自业务逻辑(各自的 Harness),而底层执行环境统一使用同一平台(共用 Runtime),以便统一管理安全、监控和资源。

这在大企业中尤为常见,能提高治理效率并保证隔离度。

十六、边界地带:五个高频混淆场景

下面这五个场景是实践中最容易出错的地方,逐个给结论。

场景 1:上下文压缩属于哪一层?

结论:Harness。 压缩解决的是"模型该看到哪部分历史"。哪怕压缩操作本身耗时耗 CPU、需要 Runtime 提供计算资源与临时落盘空间——那是它借用的 Runtime 能力,不改变它的归属。

场景 2:人工审批(Human-in-the-Loop)属于哪一层?

结论:跨层,但语义归属 Harness。 审批的决策是 Harness 的(什么操作需要审批、审批粒度、被拒绝后如何调整),审批的通道是 Runtime 的(阻塞任务、挂起协程、等待推送、超时取消)。正确做法是在 Harness 层定义审批策略,向 Runtime 只发出"挂起当前任务直到某事件"的原子指令。

场景 3:Checkpoint 是 Harness 还是 Runtime?

结论:分两个 checkpoint,别混。 语义 checkpoint(跑到哪一步了、已批准过哪些操作)属于 Harness;执行 checkpoint(进程状态、沙箱快照、连接池状态)属于 Runtime。两者必须分开存储、分开恢复。

场景 4:Agent 的"工作区文件系统"是 Harness 还是 Runtime?

结论:两层共享的最佳实践。 工作区是 Harness 的真相源(人格、记忆、技能),但它的物理实现是 Runtime 提供的基础设施。AbstractFilesystem 抽象定义了契约:上层 Harness 只面向语义接口编程,下层 Runtime 自由选择后端实现。契约稳定,实现可换。

场景 5:MCP Server 属于哪一层?

结论:取决于它承载什么。 只提供工具 Schema 与语义定义的 MCP Server 更接近 Harness;在本地常驻进程、持有凭据、管理连接池的 MCP Server 更接近 Runtime;现实中大多是混合体。通用原则:MCP 不改变分层,它只是让分层跨越了进程边界。

十七、设计实践:五个必须守住的边界规则

规则 1:Harness 不碰调度,Runtime 不碰语义

Harness 层不写线程池、不写重试策略、不写容器配置。Runtime 层不写提示词、不写工具 Schema、不写记忆提取逻辑。Harness 需要"挂起任务"这类能力时,向 Runtime 发原子指令。

规则 2:Harness 的错误要能被"看见"

Harness 的错误不会自己冒出来——Agent 依然返回 200,日志依然漂亮,但结果是错的。所以 Harness 层必须自建:评估器(决定上一步是否更接近目标)、轨迹留存(整条推理行动链用于事后复盘)、审批与审计记录(谁批准了什么、依据是什么)。

规则 3:状态分家,生命周期分家

Harness 状态(认知)与 Runtime 状态(执行)必须使用不同的存储、不同的保留周期、不同的清理策略、不同的备份机制。检查清单:长期记忆存哪里?审批记录存哪里?执行 checkpoint 存哪里?沙箱快照存哪里?两者的 TTL 和备份策略各是什么?任何一个格子填不出来,就是一次未来事故的预演。

规则 4:能力要"投影",不要"复制"

集成第三方 Agent 运行时(Codex、Qoder、Claude Code 等)时,正确姿势是投影与桥接。能力差异必须由能力注册表静态声明,不能靠运行时 try-catch 兜。配套的降级适配器让可选依赖缺失时不破坏启动。"用哪个 Agent 干活"应当变成一种配置,而不是一种架构。

规则 5:Loop 不要塞进任何一层

Loop(编排循环)是第三类东西。把 Loop 当成 Runtime 会让调度器永远在"业务语义"里打转;把 Loop 当成 Harness 会让循环无法被测试和替换。正确做法:Loop 是独立的一层,它对 Harness 提出约束请求,对 Runtime 提出执行请求,自己不实现任何一方的能力。

十八、一个最小可运行示例:把分层写进代码

光讲概念不够,给一段能跑的最小代码,让分层结构落到具体行号上。

# ============================================================
# Layer 5: INFRASTRUCTURE  - 基础设施(本例省略,用本机资源)
# ============================================================

# ============================================================
# Layer 4: AGENT RUNTIME  ** Runtime 层:只关心"跑"
# ============================================================

class AgentRuntime:
    """Agent 运行时:进程、调度、沙箱、状态、资源。
    铁律:本层不出现任何 prompt 文本、工具语义、记忆策略。"""

    def __init__(self, sandbox=None, checkpoint_dir="./ckpt"):
        self.sandbox = sandbox or LocalSandbox()      # 执行沙箱
        self.checkpoint_dir = checkpoint_dir          # 执行 checkpoint

    def spawn_worker(self, task_id):
        """创建隔离执行单元。Harness 完全不感知这个方法。"""
        ...

    def suspend(self, task_id, reason):
        """挂起一个任务,等待外部事件唤醒。
        注意:"为什么挂起" 由 Harness 决定,这里只负责"怎么挂起"。"""
        ...

    def resume(self, task_id):
        """从执行 checkpoint 恢复任务现场(进程状态、沙箱快照)。"""
        ...

    def enforce_budget(self, task_id, tokens_used, deadline):
        """资源与时间预算硬约束。语义无关。"""
        ...

# ============================================================
# Layer 3: AGENT HARNESS  ** Harness 层:只关心"能做什么"
# ============================================================

class AgentHarness:
    """Agent 线束:上下文、工具治理、记忆、安全、评估。
    铁律:本层不写线程池、不写重试、不写进程管理。"""

    def __init__(self, workspace, allowed_tools, evaluator):
        self.workspace = workspace        # 唯一事实来源
        self.allowed_tools = allowed_tools  # 工具权限白名单
        self.evaluator = evaluator          # 评估器
        self.audit_log = []                 # 审批与审计记录

    def build_context(self, session) -> str:
        """上下文工程:注入人格、知识、长期记忆,必要时压缩历史。""
        system = self.workspace.read("AGENTS.md")
        memory = self.workspace.grep("MEMORY.md", session.user_id)
        history = self._compress(session.history)   # 压缩仍是 Harness
        return system + "\n" + memory + "\n" + history

    def gate_tool_call(self, name, args) -> bool:
        """工具治理 + 安全审批。语义问题,不是调度问题。"""
        if name not in self.allowed_tools:
            return False
        if self._risk_level(name) == "HIGH":
            return self._request_human_approval(name, args)
        return True

    def evaluate(self, trajectory) -> str:
        """评估这条轨迹是否逼近目标。Runtime 永远看不到语义对错。"""
        return self.evaluator.score(trajectory)

    def flush_memory(self, session):
        """运行结束后提炼新事实写回工作区。Harness 的认知状态。"""
        self.workspace.append("MEMORY.md", self._extract_facts(session))

# ============================================================
# Layer 2: LOOP  ** 编排层:只关心"下一步干什么"
# ============================================================

class AgentLoop:
    """标准循环:Plan -> Act -> Observe -> Evaluate -> Revise。
    铁律:向 Harness 要约束,向 Runtime 要执行,自己不实现任何一方的能力。"""

    def __init__(self, harness, runtime, goal, max_steps=8, token_budget=50_000):
        self.h, self.r = harness, runtime
        self.goal = goal
        self.max_steps = max_steps
        self.token_budget = token_budget

    def run(self, session):
        trajectory = []
        for step in range(self.max_steps):
            # (1) 上下文由 Harness 提供
            ctx = self.h.build_context(session)
            # (2) 模型推理 + 工具调用决策
            decision = self._think(ctx, trajectory)
            # (3) 执行前过 Harness 的闸门
            if not self.h.gate_tool_call(decision.tool, decision.args):
                self.r.suspend(session.task_id, "waiting_human_approval")
                self.r.resume(session.task_id)
                continue
            # (4) 真正的执行交给 Runtime
            observation = self.r.spawn_worker(session.task_id).execute(
                decision.tool, decision.args
            )
            # (5) 预算硬约束由 Runtime 兜底
            self.r.enforce_budget(session.task_id, decision.tokens, None)
            trajectory.append(observation)
            session.history.append(observation)
            # (6) 评估是否达标
            if self.h.evaluate(trajectory) == "GOAL_MET":
                break
        # (7) 收尾:认知状态回写 Harness,执行状态由 Runtime 清理
        self.h.flush_memory(session)
        self.h.audit_log.append({"goal": self.goal, "steps": len(trajectory)})
        return trajectory

# ============================================================
# 装配:两层解耦,可独立替换
# ============================================================

harness = AgentHarness(workspace=Workspace("./ws"), allowed_tools={"read", "write", "grep"})
runtime = AgentRuntime(sandbox=Sandbox())                # <- 换成 K8s 也没关系
loop    = AgentLoop(harness, runtime, goal="重构 auth.py 为 JWT 且保持 100% 测试覆盖率")
loop.run(session)

# 换 Harness(换人格/换工具集):runtime 不动
harness2 = AgentHarness(workspace=Workspace("./ws-analyst"), allowed_tools={"read", "grep"})
# 换 Runtime(单机 -> 分布式):harness 不动
runtime2 = AgentRuntime(sandbox=K8sSandbox(), checkpoint_dir="redis://ckpt")

看这段代码时请特别留意三点:

  1. AgentRuntime没有任何一行提示词文本、没有任何工具语义判断。这就是"Runtime 不碰语义"。
  2. AgentHarness.gate_tool_call 内部会调用 self.r.suspend(...)——Harness 借用 Runtime 能力,但语义归属仍在 Harness。这是跨层协作的正确姿势:借用机制,不搬移职责。
  3. AgentLoop 是纯粘合层。它向 Harness 要上下文和约束,向 Runtime 要执行和预算,自己不实现任何一方的能力。Loop 是第三类,不要塞进任何一层。

十九、一句话收尾,和一张速查卡

回到最开始那个命名事故。它其实有一个非常优雅的答案:

Harness 和 Runtime 不是同一件事的两种叫法,而是同一件事的两半。

Runtime 让 Agent 做事;Harness 让 Agent 做对事。

只有 Runtime 的 Agent 是一个快而乱的机器人;只有 Harness 的 Agent 是一个懂而慢的手册。两者合起来,才是能上线的智能体。

更准确地说:Harness 定义了智能体"思考"和"行动"的方式,Runtime 负责在哪儿和怎样安全地执行这些动作。两者相辅相成,缺一不可。

速查卡(建议打印贴工位)

  Harness = 约束 / 策略 / 接口     决定"能做什么、被允许做什么"
  Runtime = 执行 / 平台 / 环境     决定"在哪儿跑、跑多快、怎么恢复"
  Loop    = 编排 / 循环 / 策略序列   决定"下一步干什么"

  判别三问:
   1. 改了它,Agent 的性格会变吗?  -> 会 = Harness
   2. 产出是内容还是进程?          -> 内容 = Harness
   3. 删掉它会变笨还是跑不起来?     -> 变笨 = Harness

  归属速记:
   Harness <- 上下文压缩 / 工具 Schema / 长期记忆 /
              审批语义 / 评估器 / 工作区真相源
  Runtime <- 进程调度 / 沙箱 / 执行 checkpoint / 资源配额 /
              持久化后端 / 监控告警
   跨层    <- 工具(Schema+执行器)/ MCP / 工作区文件系统

  安全分工:
   Harness <- 工具调用权限 / 输出验证 / 人工审批策略
   Runtime <- 网络出口控制 / 执行沙箱 / 凭证管理

  部署模式:
   模式 1: 一 Harness 一 Runtime (紧耦合,初创团队)
   模式 2: 一 Harness 多 Runtime (多环境,开发/测试/生产)
   模式 3: 多 Harness 共用一 Runtime (平台化,大企业)