同一个 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 Framework 对 Runtime 进行增强......"
一个句子里 Runtime 和 Harness 像同义词一样自由互换。评论区因此吵得不可开交。
这篇文章的目标只有一个:终结这场混淆。
读完之后你应当能做到三件事:
- 用一句话说清两者的本质区别;
- 拿到任何一个开源 Agent 框架,在 30 秒内判断它属于哪一类(或者兼具两者);
- 在设计自己的 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 混淆的真正原因
那为什么大家还是把这两个词混用?三个真实原因:
- Agent 是新兴物种,没有成熟范式。 Java 生态花了 30 年才把 Runtime / Container / Framework / Library 的边界吵清楚。Agent 生态现在连"框架"这个词都还在被 AgentScope、LangGraph、CrewAI 各自重新定义。
- 现代 Agent 框架是"打包交付"的。 LangGraph 同时给你循环引擎(Runtime 属性)和检查点存储+人工审批(Harness 属性)。你装了一个包,等于同时装了两层,于是描述它就必然混着两个词。
- 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 运行时集成)------注意它是在集成别人的 Runtime 。HarnessRuntime 接管的恰好是四件 QwenPaw 必须亲自管、但不属于 Codex 自己执行核心的事:
- 生命周期编排:第三方 CLI 进程的启动、复用、停止;
- 信封协议归一化 :把第三方流式输出翻译成自己的
AgentResponse / Message / Content流,让前端、会话、记忆对"后端是谁"无感知; - 能力投影:把自己的 Skills 与 MCP 服务器投影进第三方运行时,反向把对方自有的 Skills / MCP 只读发现回来;
- 安全审批 :第三方 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。
五、生命周期:从用户请求到任务结束
智能体从用户请求到任务结束的生命周期通常经历以下步骤:
- 用户发起请求 → Harness 接收
- Harness 加载 任务指令、上下文和策略
- Harness 调用模型 生成下一步行动
- 模型请求调用工具? → Harness 将调用分发到 Runtime
- Runtime 在隔离环境中执行 工具代码或命令
- Runtime 返回结果 → Harness 接收
- Harness 继续循环(可能再调模型或进一步工具)
- 达到终止条件? (任务完成 / 错误上限 / 超时)→ 结束
lua
用户 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(紧耦合)
应用逻辑与执行环境紧耦合,同一个仓库管理代码和基础设施。
css
[Harness A] <--> [Runtime A]
- 适用场景:初创团队快速迭代,单团队单项目
- 优点:部署简单,调试方便,无跨团队协调成本
- 缺点:无法独立扩展,环境差异难管理
模式 2:一 Harness 多 Runtime(多环境)
同一应用在不同环境(开发/测试/生产)中使用不同配置的 Runtime。
css
--> [Runtime: 开发沙箱]
[Harness A] ---|--> [Runtime: 测试集群]
--> [Runtime: 生产集群]
- 适用场景:需要在不同环境下应用不同网络或资源策略
- 优点:同一套代码在不同环境下独立配置,安全隔离
- 缺点:需要维护多套 Runtime 配置
模式 3:多 Harness 共用一 Runtime(平台化)
多个不同业务逻辑共用统一的执行平台,便于统一管理安全和监控。
css
[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 Hooks、K8s init container。
关键在于钩子挂载在什么事件上:
- Harness 钩子 挂在语义事件 上:
before_inference(注入上下文)、after_tool_call(做安全审查)、on_memory_flush(沉淀记忆)、on_evaluation(打分归档)。 - Runtime 钩子 挂在系统事件 上:
pre_start、on_oom、post_commit、on_crash_restart。
一个反直觉但极重要的例子:工具审批钩子属于 Harness,哪怕它的实现里真的会起一个异步线程等用户点按钮。 因为线程只是实现手段,钩子的语义是"这个工具调用是否被允许"------这是策略问题,不是调度问题。
结论:判断钩子的归属,看它回答的问题,不看它用了多少代码。
12.3 工具(Tool)到底算谁的?
工具横跨两层,必须拆开看:
bash
工具 = 工具 Schema(Harness) + 工具执行器(Runtime)
- Harness 拥有 :工具的 JSON Schema 定义、工具选择策略、工具结果的摘要与格式化、工具调用的审计记录、工具的权限白名单。
- Runtime 拥有:工具进程的实际执行、并发控制、超时与重试、沙箱隔离、返回值的大对象落盘、执行环境的凭据注入。
再看 QwenPaw 的 capabilities/ 子包,它做的是双向投影 :把自己的 Skills 与 MCP 服务器投影进第三方运行时,反向把 Provider 自有的 Skills / MCP 只读发现回来。这里的 MCP 服务器密钥在内存里是 SecretStr,投影到第三方进程时以指纹哈希做隔离与去重、绝不落盘。Schema 与凭据的治理是 Harness 的事;而第三方 CLI 进程本身能不能起、起在哪个 cwd,是 Runtime 的事。
十三、一张图:Agent 系统分层全景
把上面所有维度收拢成一张分层视图。记住:箭头从下往上,下层为上层提供服务,上层从不修改下层。
bash
+----------------------------------------------------------------+
| (1) 业务层 / 应用层 |
| 产品逻辑、用户交互、场景 Skill、业务 API 编排 |
+----------------------------------------------------------------+
| (2) 编排层 / Loop(循环) |
| Plan -> Act -> Observe -> Evaluate -> Revise 的迭代循环 |
| * 目标函数与停止条件 * 子 Agent 委派 * 评估器 * 预算护栏 |
+----------------------------------------------------------------+
| (3) HARNESS 层 ** 本文主角之一 |
| 上下文工程 | 工具治理 | 记忆与状态 | 安全与评估 |
| * system prompt| * Schema 定义 | * 长期记忆 | * 权限白名单 |
| * 知识注入 | * 选择策略 | * 工作区 SoT | * 审批钩子 |
| * 压缩/裁剪 | * 结果格式化 | * 事实提炼 | * 评估与审计 |
| * 上下文窗口 | * 能力投影 | * 混合检索 | * 纵深防御 |
+----------------------------------------------------------------+
| (4) RUNTIME 层 ** 本文主角之二 |
| 进程与调度 | 执行沙箱 | 状态与检查点 | 资源与网络 |
| * 进程管理 | * 容器/微 VM | * checkpoint | * 资源配额 |
| * 事件循环 | * 凭据注入 | * 会话恢复 | * 重试/超时 |
| * 并发隔离 | * 逃逸防护 | * 持久化后端 | * 可观测埋点 |
| * 故障重启 | * 环境镜像 | * 分布式同步 | * SLO 监控 |
+----------------------------------------------------------------+
| (5) 基础设施层 |
| 计算 / 存储 / 网络 / 模型网关 / 向量库 / 容器编排 |
+----------------------------------------------------------------+
三点关键读法:
- Loop(编排层)是第三类,不要把它塞进前两者。 循环决定"下一步干什么",是策略;Harness 决定"这一步能干什么",是约束;Runtime 决定"这一步在哪儿干",是执行。三者是正交的。
- 第 3 层和第 4 层之间的边界是整篇文章的核心。 一条粗线,上边全是"语义",下边全是"系统"。
- 编排层与 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 提出执行请求,自己不实现任何一方的能力。
十八、一个最小可运行示例:把分层写进代码
光讲概念不够,给一段能跑的最小代码,让分层结构落到具体行号上。
python
# ============================================================
# 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")
看这段代码时请特别留意三点:
AgentRuntime里没有任何一行提示词文本、没有任何工具语义判断。这就是"Runtime 不碰语义"。AgentHarness.gate_tool_call内部会调用self.r.suspend(...)------Harness 借用 Runtime 能力,但语义归属仍在 Harness。这是跨层协作的正确姿势:借用机制,不搬移职责。AgentLoop是纯粘合层。它向 Harness 要上下文和约束,向 Runtime 要执行和预算,自己不实现任何一方的能力。Loop 是第三类,不要塞进任何一层。
十九、一句话收尾,和一张速查卡
回到最开始那个命名事故。它其实有一个非常优雅的答案:
Harness 和 Runtime 不是同一件事的两种叫法,而是同一件事的两半。
Runtime 让 Agent 能 做事;Harness 让 Agent 做对事。
只有 Runtime 的 Agent 是一个快而乱的机器人;只有 Harness 的 Agent 是一个懂而慢的手册。两者合起来,才是能上线的智能体。
更准确地说:Harness 定义了智能体"思考"和"行动"的方式,Runtime 负责在哪儿和怎样安全地执行这些动作。两者相辅相成,缺一不可。
速查卡(建议打印贴工位)
bash
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 (平台化,大企业)