尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Agent Harness 与 Runtime 的区别:决策层与执行层的边界解析

Agent Harness 与 Runtime 的区别:决策层与执行层的边界解析 最近我在技术社区里看到两类提问画风完全不一样。一类是“deepseek harness 怎么装”“codex harness 怎么用”明显是开发者在找一种能接管 Agent 行为的外层控制工具另一类是“could not find the webview2 runtime”“oci runtime create failed: container_linux.go: ...”报错来自桌面应用、容器、部署环境属于典型的“东西跑不起来”问题。把它们放在同一条时间线里看你会发现问题其实是同一个我们天天在说开发 AI Agent但 Agent 应用到底分了几层哪些问题归模型编排管哪些问题归执行底座管这个边界理不清开发时就会出现非常低效的互相甩锅。这篇文章想把 Agent Harness 和 Agent Runtime 这两个词彻底拆开。它们不是同一层次里的两个竞品而是 Agent 应用中的两个不同角色——一个负责“思考着编排”一个负责“真正跑起来”。把这个边界刻在脑子里团队里的低效讨论能少一大半。1. 先给一个不绕圈子的分层结论驾驶舱与发动机舱把 Agent 想象成一辆出租车Harness 是驾驶员那一整套操作逻辑看路、判断要不要转弯、踩油门还是刹车、什么时候到目的地停车Runtime 是发动机、变速箱、油路、底盘它不负责“去哪儿”只负责让车真正动起来。这个类比能解决很多争论。Harness 处理的是“下一步该做什么”Runtime 处理的是“这个动作怎么被执行”。模型产生的判断只是方向盘的角度真正让车轮转动的是运行时那一层基础能力。1.1 技术社区里两个方向相反的搜索诉求你去看这些热搜词会发现用户意图有明显的两极分化。搜“deepseek harness”“codex harness”“agent框架”的人脑子里的问题是我想让 Agent 按我的规则行动想自定义工具想限定循环次数想让模型在调用工具之后把上下文处理好。这类需求本质上是在找或改 Agent 的决策骨架也就是 Harness 层。搜“could not find the webview2 runtime”“oci runtime create failed”“the agent execution provider did not respond in time”的人问题是另一类程序装好了但起不来容器创建不了某个后台服务超时。这类问题跟模型聪不聪明毫无关系是执行基座缺了东西、权限不够、或者网络不通。这就落到了 Runtime 层。很多团队项目延期不是模型能力不够而是这两层永远搅在一起。前端说“Agent 没做对”后端说“Agent 没执行”一查日志两边都没有统一的层概念。1.2 一个可以带到任何项目的分层判据我在代码评审时经常问一句话这一段逻辑是在决定模型“下一步做什么”还是在让某个动作“真正发生”如果答案是前者它属于 Harness。如果答案是后者它属于 Runtime。举个例子Agent 被要求给客户发一封跟进邮件。模型决定“我需要调用 send_email 工具收件人是张三内容是……”这个决策反馈循环属于 Harness。代码真正构造 HTTP 请求、连接邮件服务商、处理 TLS、拿到响应、解析状态码这部分属于 Runtime。如果模型选择调 send_email 但收件人字段填错了那是模型或 Harness 的决策质量问题。如果模型决策完全正确但工具执行时发现 API Key 没有权限、网络超时、沙箱禁止出网这就是 Runtime 的问题。这个判据不要求你熟悉任何特定框架拿到任何一段 Agent 代码都能立刻分层。1.3 用一份最小伪代码把边界钉死为了不让概念飘在空中我一般会给团队看一段极简 Agent 循环伪代码。注意看注释里每一行属于哪层。# 伪代码一个极简 Agent 循环 def run_agent(task: str): messages [ {role: user, content: task} ] for step in range(max_steps): # max_steps 是 Harness 的边界条件 response llm_client.chat(messages) # Runtime 提供网络、重试、超时 action parse_model_output(response) # Harness 解析模型输出为结构化动作 if action.type final_answer: # Harness 判断终止 return action.output if action.type tool_call: # Harness 决定调用哪个工具并把工具执行权交给 Runtime result runtime.execute(action) # Runtime 真正执行工具沙箱/API messages.append({ role: tool, tool_call_id: action.id, content: result, }) # Harness 维护上下文回填 raise MaxStepExceededError() # Harness 的护栏机制这段代码里llm_client.chat和runtime.execute都是 Runtime 的入口围绕 response 的解析、工具选择、循环、终止都是 Harness 的职责。很多入门教程把 Agent 实现成一段几十行的脚本好像 Harness 和 Runtime 不需要区分。项目一上生产你就会发现脚本里的网络重试逻辑、工具执行权限、上下文持久化、并发调度全部写在一起最后哪个层都改不动。2. 为什么 Harness 会被单独讨论它是 Agent 的决策骨架Harness 翻译成“套件”或“脚手架”都不够传神我更愿意叫它“决策骨架”。Agent 和普通 API 调用最大的不同是它有循环模型反复接收状态、产生动作、看到结果、再产生下一个动作。真正把这个循环撑起来的那套代码就是 Harness。2.1 控制循环看似简单真实项目往往死在状态恢复上每个 Agent 框架的核心都有一个 loop。ReAct、Plan-and-Execute、Reflexion这些不同的 agent 模式本质上是不同结构的 Harness。最容易被低估的问题是状态恢复。线上 Agent 一旦跑起来可能要执行十几步工具调用如果中途崩溃下一步该从哪一步继续模型已经产生的消息列表要不要存工具执行的中间结果重放会不会污染新会话这些都属于 Harness 要回答的问题。我在生产环境里踩过最大的坑就是循环里每一步只在内存中维护 messages进程一重启所有上下文丢失。用户看到的现象是“Agent 忘了之前做过什么”看起来像模型记忆力不行实际上是 Harness 没有接持久化状态层。2.2 工具结果回填策略决定 Agent 看起来聪不聪明Agent 调用完工具后工具返回的经常是一大段 JSON、Markdown、甚至整个文件的全文。如果把这些内容原封不动塞回模型上下文几轮下来 token 直接爆炸如果粗暴截断又可能导致模型缺少关键信息。这块处理逻辑就在 Harness 里。成熟的做法是给工具结果做结构化摘要、字段筛选、大段内容折叠甚至让另一个小模型先把结果压缩成对当前任务有意义的结论再放回主循环。我见过不少团队把全部精力用在调 prompt 上却忽略了 Harness 的工具结果回填逻辑。同样的 prompt工具结果处理得好不好Agent 的表现可以差一个档次。2.3 边界、护栏与评测Harness 的三个隐藏组件Harness 不只是“循环执行器”它还是 Agent 的边界执行者。比如最大循环次数、单次任务耗时上限、敏感工具的双人确认、用户可随时中断的外部信号这些机制都属于 Harness。还有一个容易混淆的词叫 eval harness。评测 Agent 时我们会写一套测试管线把一批任务灌进 Agent比较输出质量。这套评测管线和 Agent 在线的 harness 并不是同一个东西但思路一脉相承通过标准化流程控制模型的输入输出让开发者能对比不同 prompt、不同工具定义的效果。Harness 做得好Agent 的行为是可回放、可比较、可测试的做得不好Agent 就是一团不可控的黑盒每次跑出来的行为都随缘。3. Agent Runtime 不是一个 Runtime三层基础设施要分清很多聊 Runtime 的文档喜欢把“Python 运行时”和“Agent Runtime”混在一起导致读者以为 Runtime 就是解释器。实际上Runtie 是一个层级概念Agent 项目里至少会出现三层 Runtime。3.1 语言运行时、应用运行时、容器运行时管辖范围各不相同我用一个表格说明容易对照Runtime 层次常见代表主要职责语言/宿主运行时CPython、Node.js、V8、.NET CLR管理进程、内存、事件循环、基础 I/OAgent 应用运行时LangGraph runtime、AutoGen、Agents SDK 内置调度层提供 Agent 状态存储、并发执行、消息路由、任务恢复沙箱/容器运行时Docker、OCI runtime、Firecracker限制 Agent 工具可以访问的文件、网络、系统调用这里面最容易踩的坑是把三层 Runtime 的问题混在一个报警里排查。比如 Agent 工具要跑一段 Python 脚本报错说ModuleNotFoundError这是语言运行时缺依赖如果你把脚本放进容器报oci runtime create failed那就是容器运行时或镜像问题如果脚本能跑但 Agent 的两个并发任务互相覆盖了同一个数据库记录这是 Agent 应用运行时里的并发调度问题。我一般会要求团队先把 Agent 应用运行时和底层基础设施运行时分开监控因为它们的升级节奏完全不同。底层容器运行时可能由平台团队统一升级而 Agent 应用运行时的版本往往跟着框架走。3.2 Agent Runtime 真正要关心的部署形态常驻与沙箱调度一旦 Agent 上了生产应用运行时需要处理的事情会复杂很多。单个 Agent 调用一个公共 API 简单但当你有几百个 Agent 任务并发执行时Runtime 要负责排队、限流、隔离、失败重试。每个任务跑在一个什么环境里任务结束后沙箱怎么销毁临时文件是否会泄漏到下一个任务审计日志记到哪一级这些都不是 Harness 层能回答的它太关注“决策”了。我倾向于把 Runtime 看作一个“受控的执行环境协议”。Harness 对着协议说“我要执行工具 A参数是这些”Runtime 负责找到资源、安排沙箱、执行、返回结果。如果你发现 Harness 里手写了大量并发控制、文件锁、沙箱管理代码说明Runtime 层没有接好或者说你的 Harness 正在被拉去做 Runtime 的活儿。3.3 热搜里的典型 Runtime 报错翻译成人话“could not find the webview2 runtime”本质是桌面端宿主环境缺少 WebView2 运行时。做 Windows 桌面 Agent 时如果你用 WebView 承载 UI安装包没带上 WebView2 Bootstrapper就会在用户机器上报这个错。它跟 Agent 逻辑无关纯粹是宿主层依赖缺失。“oci runtime create failed: container_linux.go: ...”这是容器运行时没有成功创建用户进程。常见原因是 cgroup 配置、内核权限、seccomp 限制或容器镜像损坏。注意这段报错里的“runtime”和 Python 运行时也不是一回事它指 OCI 兼容的容器运行时组件。“the agent execution provider did not respond in time”看字面像 Runtime 超时但实际有可能是 Agent 后端服务在等待一个外部模型响应或者是网关侧的流式超时配置太短。这类问题要先把超时时间、网络链路、provider 健康状态三个指标拉出来才能判断是谁的锅。理解 Runtime 这一层别把“runtime”三个字母当成单一对象而是看作一条从进程到容器到外部依赖的完整执行链。4. 五个边界场景不掰扯清楚开发两天就得吵一架定义好 Harness 和 Runtime 之后难的是面对真实项目里的模糊地带。下面五个场景是我在实际工作中遇到频率最高的争论点。4.1 工具该不该被调用与工具能不能被调用“Agent 调用了删除接口这是谁的错”要看错在哪一步。如果模型决定删除文件但它没有权限去删执行被 Runtime 拦截这是 Runtime 做了正确的事。真正要反思的是 Harness 里的权限规则为什么不拦。反过来如果模型在不需要删文件的场景下仍然决定删这是 Harness 的工具选择机制和系统提示出了问题不能怪 Runtime。这两个问题的修复手段完全不同。前者你去改 Runtime 的授权配置后者要去调 Harness 里的工具描述、决策策略或加一层规则过滤。4.2 Agent 说“我做了”但实际没做故障在哪这是最经典的“幻觉背锅”。Agent 最终回复“已完成”但用户去看系统发现数据根本没变。以我排查过的案例为例Agent 调用了一个create_order工具工具日志显示执行成功但数据库事务没有提交。这种错误在工具代码内部它不在 Harness 的决策范围内因为决策已经正确也不在容器 Runtime 内因为进程正常运行。问题出在 Runtime 和业务系统之间的执行适配层。你需要检查的是工具函数的实现它是否默认开启事务、是否真的连接到了生产库、返回的“成功”是来自底层 API 还是被某段 catch 吞掉后的伪造结果。最容易误判的是把责任推给模型实际业务代码里的事务边界写错了。4.3 同样的对话第二次结果不一样是随机性还是状态恢复问题用户报告同一个问题Agent 第一次做对了第二次做错了。很多人第一反应是“大模型有随机性”于是拼命调 temperature。但在生产级 Agent 里更常见的原因是 Harness 没有把上一次会话的中间状态完整恢复或者 Runtime 把任务分到了不同的沙箱环境。如果两次跑在同一个 prompt、同一个模型版本、同一个工具版本下结果出现显著差异先检查 Harness 的会话快照是否完整。再看 Runtime 是不是把状态存在了本地临时文件里多实例部署时没有共享存储。真正的随机性当然存在但不能把所有不一致都归因到随机性上。把 state 重放一遍很多“玄学问题”会立刻现形。4.4 上下文太长被截断时两层各有各的处理办法Agent 一轮里工具结果太多超过了模型的 context window系统会做截断或摘要。这看起来像模型能力问题但处理和预防要跨两层。Harness 层要做的是优化回填策略每次工具结果进上下文前先压缩及时归档旧消息避免上下文无限膨胀。Runtime 层要做的是在 API 请求层面对消息体大小做监控超过阈值时告警必要时把调用切换到支持更大上下文的模型端点。一个偏策略一个偏通道。两层都要有方案只靠一层挡不住。4.5 超时重试到底是 Harness 改还是 Runtime 改工具调用超时是重试一次还是放弃这个决定放哪一层不同框架没有统一标准。我的经验是网络抖动和临时 5xx 错误由 Runtime 处理重试最合适因为它是无状态的通道层可以看幂等性但如果某个工具已经实际生效比如“创建订单”返回超时无脑重试可能产生重复订单这时候必须由 Harness 感知工具语义决定是否需要查重或进入人工确认。所以Harness 负责“该不该重试”Runtime 负责“怎么重试”。把一个超时逻辑硬塞在任意一层都会在后面出问题。5. 从一堆“XX harness”封装热词看 Harness 的独立价值社区最近大量出现以“harness”为后缀的项目比如很多人搜 deepseek harness、codex harness。这个现象很有意思它说明 Harness 正在变成可独立定制的一层。5.1 用户在意的不是“某个模型”而是“我的工具链能跑起来”当人们搜“deepseek harness”时他们真正想问的往往是这个模型能不能接入到我自己定义的循环里命令行客户端默认帮我做的那些决策我可不可以改比如默认是否允许模型修改文件、最大执行步数是多少、工具怎么注册、执行到哪一步需要人工确认。这些需求恰恰都是 Harness 层的东西。模型本身可以很强但如果外层 Harness 不允许你插入私有工具或者不允许你控制模型输出到代码的解析方式那它在实际业务场景里就不够用。开源社区里做得好的“XX harness”本质上是在重新实现或扩展某个 Agent 的控制循环。它们没有另起炉灶去造一个 Runtime而是在已有模型和工具之上给开发者一个更透明的决策骨架。5.2 codex harness 这类项目改的通常是决策闭环Codex 是 OpenAI 的命令行编程 Agent设计得再完善也未必适配你团队内部的权限体系和代码评审流程。很多人想加的其实是模型在修改文件之前自动跑测试、模型要访问外网时必须先申请、某些分支禁止 Agent 直接 push。这种修改如果能落到 Harness 层就不用动模型、不用动执行沙箱改动成本和风险都小得多。你可以把 Harness 看成 Agent 的“策略层”在这里加规则、加中间步骤、加回调钩子。我见过团队为了让 Agent 遵守公司规范跑去改底层工具函数甚至在模型 prompt 里反复强调。这种思路不是不对而是维护成本高。更稳妥的方式是把规则前置到 Harness 的决策节点里形成硬性代码约束而不是指望模型每次都“想对”。毕竟 runtime 环境再稳定模型决策不经校验线上风险就一直在。5.3 为什么很少有人做“XX Runtime”的封装留心观察你会发现叫“runtime”的开源项目通常不是个人开发者能轻易做的。Runtime 要处理并发、隔离、进程管理、沙箱、资源配额开发门槛高部署重个人项目玩不太动。反而是大公司和云厂商更愿意做 Runtime要么是托管的 Agent 执行环境要么是标准化的沙箱协议。因为它们有基础设施积累也知道 Runtime 是规模化必须过的那道坎。所以“XX harness”项目多“XX runtime”项目少不是 Runtime 不重要而是它太重。Harness 可以在一个周末写出原型Runtime 要稳定到生产级别往往需要长期投入。理解这个行业分工对选型很有帮助。6. 选型时如何利用这一层边界四种组合和两条铁律当你真正开始落地 Agent 项目最关心的应该是我该用现成框架还是自己写循环要不要把执行环境托管出去这里没有绝对答案但利用 Harness 和 Runtime 的边界可以把选型问题拆得很清晰。6.1 四种常见组合方式组合模式Harness 层Runtime 层适合场景全托管用框架默认控制循环用框架自带运行时原型验证、短流程任务自研 Harness 托管 Runtime自己写决策循环和工具注册用云厂商或框架的沙箱执行需要定制 Agent 行为但不想碰基础设施托管 Harness 自研 Runtime用可视化流程或现成 Agent 编排自建容器、权限、审计体系编排由产品团队把握执行环境要严格合规全自研自研循环、状态、护栏自建沙箱调度、队列、存储核心团队有平台能力场景高度特殊我最常建议的是第二种Harness 尽量自研或用轻量框架Runtime 尽量用成熟方案。原因是 Harness 承载着你对业务场景的理解是 Agent 输出的质量关键而 Runtime 是通用能力除非有硬性合规要求否则没有理由从零造轮子。6.2 铁律一别用模型能力评估掩盖 Harness 的缺陷很多人选型时只对比模型的智商跑几个 benchmark 觉得不错就开工。到生产环境发现 Agent 经常“乱来”就开始怀疑模型不行。实际上大部分生产问题出在 Harness 没有对工具的调用边界做约束没有给模型提供足够清晰的动作空间。一个质量合格的 Harness应该让模型在合理的动作集合里做选择而不是给一个巨大开放的自由度。你选模型之前先搭建一个最小 Harness把工具调用、状态回填、终止判断跑通再来评判模型。否则你把所有问题都算到模型头上换再强的模型也填不了 Harness 的坑。6.3 铁律二别用 Runtime 的工程复杂度掩盖 Harness 的缺失另一类团队走的是反方向。他们花了几个月把 Runtime 做得很重Kubernetes、容器沙箱、消息队列、可观测平台齐活了。结果一跑Agent 连“循环里保存中间状态”都没实现工具结果也没有压缩机制Agent 经常在第三步就因为上下文太长而崩溃。这种投入产出的错配非常可惜。Runtime 能保证系统稳定但不能保证 Agent 智能。先把 Harness 做稳定再考虑把 Runtime 规模化这个顺序不能反。有一个很实用的信号如果单个 Agent 在单机单进程场景下都经常行为异常你缺的不是更牛的 Runtime而是 Harness 的决策质量。7. 线上排错案例什么情况该怀疑 Harness什么情况该怀疑 Runtime最后分享三个真实项目的排查思路。这些案例能帮你理解前面所有理论在报警时到底怎么用。7.1 案例一Agent 说完成了数据却不存在现象Agent 在处理客户退货单时回复“退货单创建成功”客服去后台查不到。排查链路先看模型最后的决策它确实调用了创建退单工具参数正确再看工具执行日志显示 200 OK最后查了数据库事务发现工具函数在order_service里开启了一个事务但返回前没有 commit异常时也没有回滚导致数据丢失。这是典型的 Harness 决策正常、Runtime 通道正常、但执行适配层有 bug 的场景。修复方式不是调 prompt而是修业务工具函数的事务逻辑并给工具加上“执行成功 落库成功”的校验。7.2 案例二Agent 总是重复调用同一个查询工具现象Agent 在回答库存问题时反复调用get_inventory共执行了 7 次最后才给出答案。用户觉得回答很慢。排查链路打开 Harness 的会话消息回放发现第一次工具结果返回到消息列表后内容格式不符合 Harness 的解析规则。Harness 没有把这条工具消息注入下一步的模型请求中模型随后感知不到自己已经查过库存于是再次发起同一次查询。问题根本在 Harness 的工具结果回填逻辑里缺了某种 content-type 的兼容处理。修完之后同样的任务只调用 1 次工具就能完成。7.3 案例三容器运行时偶尔报错Agent 也跟着崩现象Agent 在沙箱内跑用户上传的代码偶发oci runtime create failed。每次报错这条 Agent 任务直接失败。排查链路错误并不是 Agent 决策导致的因为同样的任务重试后经常成功。查宿主机的dmesg发现内核报 cgroup 相关异常最后定位到容器 Runtime 和宿主内核版本的兼容性问题升级运行时版本后解决。这里最怕的就是盲目重试或修改 Harness 逻辑。Runtime 的故障有强烈的环境耦合性必须先看宿主层报告。7.4 给两层分别打日志是效率最高的投入前面三个案例背后有一个共同点如果 Harness 日志和 Runtime 日志混在一起排查会非常痛苦。我的习惯是硬性要求两边打不同的字段。Harness 日志要记录决策链本轮系统提示词版本、模型输出原文、解析出来的动作、选择该工具的理由、当前步骤数、上下文窗口占用。Runtime 日志要记录执行链实际请求的目标地址、入参、出参、耗时、状态码、重试次数、沙箱资源使用、进程退出码。这两类日志分开索引比打在一个 log 流里再靠关键字模糊搜索强得多。排查问题时先按 trace_id 串联两条链再明确故障落在哪一层。我自己接手任何 Agent 项目第一件事永远是先问一句这段行为是模型这一步没走对还是工具这一步没跑通。没走对去 Harness没跑通去 Runtime。这句话听起来简单但它能省下后面无数个小时的扯皮和试错。先把层分清楚再谈优化模型、再谈扩容沙箱否则你追求的一切 Agent 稳定性都是在大雾里开车。
返回列表