
刚接触 Agent 相关工程的时候很多人都被Agent Harness和Agent Runtime这两个词绕晕过。尤其当终端里出现一条类似error: agent harness runtime codex is unavailable because its plugin registration is incomplete的报错时第一反应往往是这俩到底谁出了问题是运行时崩了还是载体没搭好如果你也遇到过这种困惑这篇内容就是为你准备的。我会从概念边界、职责分工、配置实操和常见报错四个维度把这两个容易混淆的组件彻底讲清楚。适合正在接触 Agent 框架源码、做智能体二次开发或者只是被 CLI 工具报错卡住但想弄明白原因的朋友。先说结论方便你带着框架往下看Harness 管的是“怎么想怎么决策”Runtime 管的是“怎么落地怎么执行”。一个是控制大脑的驾驶舱一个是真正把动作做出来的机械臂。下面展开讲。1. 从一个报错开始Harness 和 Runtime 到底谁出了错1.1 报错现场unavailable 的含义我自己第一次认真去查这两个概念就是因为一条报错。当时在配置一个类似 Codex 的 AI 编程代理工具启动后直接抛了这么一句error: agent harness runtime codex is unavailable because its plugin registration is incomplete翻译成人话就是Agent 的外层载体Harness尝试去加载一个叫codex的底层执行运行时Runtime结果发现这个 Runtime 没有在插件注册表中完成注册或者注册信息不完整于是拒绝启动。这里的unavailable不是“运行时崩溃了”而是“运行时压根没有被正确登记”。打个比方就像你到了公司发现工牌刷不开门不是门锁坏了而是行政那边根本没给你录入工牌权限。报错信息里的plugin registration指的就是这种“登记动作”——Harness 和 Runtime 之间不是直接硬编码绑定的而是通过一个插件注册表来互相发现。1.2 报错背后的组件边界谁在“调用”谁要读懂这条报错得先搞清楚一句话肯定是 Harness 去找 Runtime而不是反过来。这既是工程上的架构约定也是理解二者关系的第一把钥匙。在一个典型的 Agent 系统里Harness 是启动入口。它负责加载配置、初始化会话、维护上下文、调度模型调用还要处理工具调用的循环。而 Runtime 是 Harness 手里的一把“执行工具”负责真正把动作做出来执行一段 Shell 命令、跑一段 Python 脚本、读写文件、发一个 HTTP 请求。所以报错出现时实际上是 Harness 启动流程走到“初始化执行环境”这一步发现它点名的 Runtime 不在服务名单里。理解了这个调用方向你再去看各种 Agent 框架的源码就会觉得清晰很多。Harness 通常有一个 runtime registry 或者 plugin managerRuntime 则对外暴露统一的接口比如execute_command、run_python、read_file。Harness 通过接口调用 RuntimeRuntime 通过注册实现被 Harness 发现。1.3 为什么要分清这两个概念有人会问不就是一个工具吗我随便用用搞清楚这两个概念有啥实际价值我的体会是分不清它们的区别你连一个配置文件都改不明白。绝大多数 Agent 工装的配置界面都会同时出现 harness 和 runtime 相关的配置项。比如你会看到harness.max_iterations这种参数也会看到runtime.sandbox_mode这种参数。如果你不知道前者控制的是“Agent 最多思考多少轮”后者控制的是“命令在哪种沙箱里执行”那就很容易把参数填到错误的区块里导致配置不生效。更进一步当你开始设计自己的 Agent 应用时这个边界会直接影响你的架构选型。你是想让 Agent 跑在本地 Docker 沙箱里还是跑在远端容器里你是想用官方默认的执行后端还是想接入自己团队内部的任务执行系统这些决策本质上都是在回答同一个问题你要换哪个 Runtime或者你自己写一个 Runtime但它必须满足 Harness 的接口约定。2. 核心概念拆解Harness 是“驾驶舱”Runtime 是“机械臂”2.1 Agent Harness编排者与治理者Agent Harness 承担的角色用一句话概括就是负责让 Agent “有脑子地工作”。它不关心一条命令具体是怎么被操作系统执行的它关心的是这条命令该不该执行、什么时候执行、执行之后的结果如何回到模型上下文里。具体来说Harness 至少包含以下几块职责会话与状态管理维护多轮对话的历史记录保存和恢复 Agent 的执行上下文。你做一次任务中途断了能不能接着上次的状态继续跑就是 Harness 的事。模型调用与上下文组装把系统提示、工具描述、历史消息编排成模型可接受的格式处理流式输出和函数调用结果返回。工具与权限治理定义哪些工具可以用、哪些路径可以访问、哪些命令需要人工审批。AI 编程工具里常见的“执行危险命令前询问用户”就是 Harness 层实现的安全策略。循环控制决定 Agent 是继续思考还是结束任务。max_iterations、early_stop这类参数都归 Harness 管。用一个驾驶舱做类比Harness 是那个握着方向盘的飞行员。他负责看仪表盘读状态、定航线做计划、决定什么时候拉操纵杆发起工具调用但他自己并不直接产生推力——那是发动机的事。发动机就是 Runtime。还有一个容易忽略的点Harness 往往决定了一个 Agent 工具给开发者呈现出来的“体感”。同一个底层执行 Runtime可以有不同的 Harness。有的 Harness 偏命令行交互适合快速验证有的 Harness 偏 API 服务化适合集成到 CI/CD 流水线有的 Harness 偏图形界面适合非技术用户操作。你选择哪种 Harness就是选择哪种编程模型和交互方式这是 Runtime 层面不关心的。2.2 Agent Runtime真正的执行后端如果说 Harness 是大脑那 Agent Runtime 就是小脑加四肢。它直接对接到操作系统、容器或远端执行环境负责把 Harness 下发的“意图”变成系统里的真实动作。Runtime 的核心能力包括命令执行在指定的工作目录里执行 Shell 命令捕获标准输出、标准错误和退出码。看似简单但背后的进程管理、环境变量注入、PATH 解析、超时杀进程都是 Runtime 的活。代码解释执行比如提供一个内置 Python 解释器让模型可以边写代码边执行拿到运行结果后修正方案。这个能力在数据分析、脚本生成类 Agent 里尤其关键。文件系统访问读写相对路径和绝对路径的文件并遵循 Harness 下发的权限边界。一个合格的文件访问实现还需要处理软链接、权限位、路径穿越等安全问题。沙箱隔离很多 Runtime 会把命令执行放到 Docker 容器、Firecracker 微虚拟机或者独立的用户命名空间里避免 Agent 的误操作影响宿主机。Runtime 和 Harness 的另一个关键区别是Runtime 往往是无状态的或者说它的状态管理更简单。每一条命令的执行结果都是独立的运行完就返回一堆输出字节而 Harness 需要把这些输出再整理进上下文让模型判断下一步怎么走。这也是为什么很多运行时抽象都长得特别像“函数”输入一段代码或命令返回执行结果。这种设计让 Runtime 很容易被替换、测试和横向扩展。2.3 一张表看清 Harness 与 Runtime 的职责边界为了让你更直观地对照我把常见的职责项整理成表格能力维度Agent HarnessAgent Runtime核心使命编排决策流程执行实际动作是否调用大模型是负责模型推理和上下文管理否只负责动作落地会话状态负责保存和恢复多轮状态通常无状态或轻量状态工具定义负责声明可用工具及参数格式负责实现具体工具逻辑权限审批负责人工审批、安全策略负责在底层遵守隔离约束典型故障表现会话丢失、上下文溢出、循环卡死命令超时、依赖缺失、沙箱创建失败类比驾驶舱/指挥官发动机/机械臂2.4 为什么插件注册机制如此关键回到文章开头那条报错你会发现有一个反复出现的关键词plugin registration。为什么 Harness 和 Runtime 之间非要加一层插件注册的间接层而不是直接写死调用关系我的理解是这跟 Agent 生态的快速迭代有关。Runtime 是变化最频繁的部分今天用官方沙箱明天想换成云上容器后天想接入内部任务调度系统。如果 Harness 代码里硬编码了所有 Runtime那每接入一个新执行后端都要改 Harness 主程序风险太大迭代也太慢。插件机制让 Runtime 可以独立开发、独立发布只要实现了约定好的接口并在注册表中登记自己的名称和元数据Harness 就能在运行时动态发现并加载。这套思路其实在 IDE、构建工具、浏览器扩展里已经很成熟了。比如你在 VS Code 里装语言插件本质上就是向编辑器注册一个“我能处理这种语言”的信号。Agent 框架把同样的模式搬过来只不过注册的对象从“语法高亮器”变成了“执行运行时”。了解了这一点再遇到registration is incomplete这类报错时你就不会再把它当成一个黑盒错误而是会自然地去检查注册表里到底有没有这个条目条目里的字段是不是齐全版本是否兼容3. 实操对比配置一个可用的 Harness Runtime3.1 一个典型的插件式架构长什么样纸上谈兵告一段落下面进入动手环节。虽然不同的 Agent 框架在具体配置语法上有差异但底层逻辑是共通的。我用一个简化的 YAML 配置示例来展示 Harness 和 Runtime 是如何在工程里配合的这个结构你可以直接迁移到自己用的工具上。# agent.yaml agent: name: my-coding-agent harness: type: agentkit/terminal-harness options: interactive: true max_iterations: 20 auto_approve: false workspace: ./project runtime: type: codex options: sandbox: docker image: python:3.11-slim timeout_seconds: 120 workdir: /workspace上面对应关系非常明确harness区块定义的是决策控制层的参数runtime区块定义的是执行后端层的参数。你以后照这个结构去查文档、改配置心里就有数了。3.2 关键配置字段逐个看我挑几个经常被搞混的字段展开说它们最能体现 Harness 与 Runtime 的差异。先看harness.max_iterations。这个字段的意思是Agent 在结束任务前最多允许执行多少轮“思考-行动-观察”循环。它控制的是决策深度而不是执行时间。就算单条命令执行只要一秒如果模型一直在循环里反复试错任务也可能很久才结束。调大这个值能让 Agent 更耐心但也更烧 token调小则偏向快速收敛适合任务很明确的场景。再看runtime.sandbox。这个是 Runtime 层的核心配置。docker表示每条命令都在独立的 Docker 容器里运行资源隔离和文件系统隔离都相对干净。备选值通常还有local直接在宿主机上跑快但有风险和remote连接远端执行服务适合大型计算任务。选择哪一种考验的是你对执行速度、安全性和资源消耗三者平衡的把握。千万不要把harness.interactive和runtime.sandbox搞混。前者决定要不要在每一步之前弹窗征求用户确认例如执行rm -rf之前先问一嘴后者决定命令实际跑在哪里。一个管流程一个管环境互相独立。3.3 实操查看当前可用的 Runtime 列表配置文件里写明了要使用某个 Runtime但实际能不能用取决于这个 Runtime 有没有成功注册到 Harness 的插件系统里。绝大多数框架都会提供一个 CLI 命令来查看注册状态我习惯把它当作“体检”的第一步。命令大概是这样的# 列出当前 Harness 能发现的所有已注册 Runtime agent harness runtime list # 检查某个 Runtime 的注册元数据是否完整 agent runtime validate codex如果输出显示codex不在列表里或者validate命令报告注册信息缺失那配置文件写得再漂亮也白搭——Harness 根本找不到执行后端。这时候就要进入下一节的排查流程了。如果validate通过了但实际启动还是报错那就要考虑运行环境层面的问题。比如 Runtime 依赖了本机的 Python 解释器但当前PATH里没有或者 Runtime 需要 Docker 守护进程但 Docker 没有启动。记住一个原则Harness 层面的问题看日志Runtime 层面的问题看环境。日志会告诉你注册和发现的流程走到哪一步断了环境检查会告诉你执行依赖缺了什么。4. 排查实录Runtime 不可用时怎么处理4.1 常见报错速查表在实际使用中unavailable只是众多 Runtime 相关报错的一种。我把最常见的几种整理成一张速查表你遇到类似报错可以对照着看报错现象可能原因排查方向runtime codex is unavailable because its plugin registration is incompleteRuntime 插件的注册元数据缺失或校验失败检查插件安装目录、重新运行注册脚本runtime codex not found配置里写了 codex但注册表里根本没有这个条目列出已注册 Runtime确认插件是否安装plugin registration failed: duplicate name同一个 Runtime 名被注册了两次检查多个插件目录是否存在重复安装runtime initialization failed注册是成功的但启动时报环境依赖错误检查 Docker 进程、Python 路径、系统资源version mismatch between harness and runtimeHarness 主程序与 Runtime 插件版本不兼容升级或降级其中一方到锁定的兼容版本4.2 三步定位法从日志到环境拿到一条 Runtime 类报错我建议按以下三步来排查避免上来就乱试。第一步开启详细日志确认报错发生的阶段。大多数框架都支持--verbose或--debug参数。你要重点看报错之前那几行日志是发生在“加载插件清单”阶段还是“解析插件元数据”阶段还是“初始化运行时进程”阶段三个阶段对应的处理方式完全不同。注册元数据有问题就重装插件运行时进程起不来就检查系统服务。第二步用验证命令直接探测注册状态。像前文提到的agent runtime validate codex这种命令会主动检查插件入口文件、注册表条目、接口实现是否齐全。它能立刻告诉你到底是“插件没装”还是“装了但没注册”还是“注册了但格式不对”。第三步检查 Runtime 的执行依赖。如果注册没有问题那大概率是 Runtime 真正要启动执行环境的时候缺了东西。最常见的三类依赖是Docker 守护进程、特定版本的编程语言解释器、网络访问权限。逐一确认速度很快。4.3 独家避坑经验这里分享几个我在实际项目里踩过、也帮朋友排查过的坑希望能帮你省点时间。避坑一重装插件时不要只删目录。有些框架的插件安装会往全局注册表里写元数据。你只删了插件目录注册表里的残留条目还在下一次安装会提示重复甚至直接拒绝注册。正确的做法是先卸载uninstall再安装install让工具清理注册表。避坑二全局工具链和项目级依赖要分清。我遇到过一次特别迷的报错同一个项目在 A 机器上正常在 B 机器上死活跑不起来。后来发现 B 机器上存在两个 Python 版本Runtime 在全局目录里找到的是一个旧版本解释器缺了某个依赖包。这个问题的本质是 Runtime 的依赖搜索路径和 Harness 的当前工作目录没有对齐。解决方法是把 Runtime 路径或虚拟环境路径显式写进配置不要让工具自动探测。避坑三升级要谨慎锁定版本更安心。“这周还能用升级完就废了”是 Agent 工具链里最常见的悲剧。因为 Harness 和 Runtime 的接口耦合度很高升级 Harness 往往需要同步升级 Runtime 插件甚至迁移配置格式。我在生产环境里的做法是把 Harness 主程序和 Runtime 插件的版本写进项目的 lock 文件统一升级而不是单独升某一个。这样能大幅降低莫名其妙的兼容性 bug。避坑四权限审批配错表现骗人。还有一个容易被误判为 Runtime 故障的场景Harness 卡在某条命令前等待用户确认如果你设置了auto_approve: false但终端没有触发交互提示看起来就像“Agent 假死”。实际上不是 Runtime 挂了是 Harness 的交互通道没打通。检查一下是不是在非交互式终端里运行了需要交互的命令要么改成auto_approve: true要么换到能弹出交互提示的终端。5. 认清边界后的一些实际体会5.1 这个边界如何指导日常开发弄清楚 Harness 和 Runtime 的区别不只是为了看懂报错它对你在真实项目里做技术决策很有帮助。当你的 Agent 任务执行变得很慢时你可以先判断瓶颈在哪个层如果是模型在反复思考那是 Harness 的循环策略和上下文管理需要优化比如减少遗留的历史消息、降低max_iterations如果是命令执行本身慢那是 Runtime 的问题可以考虑换更强的沙箱机器、优化执行路径或者用并行执行能力更强的 Runtime。当你想给 Agent 增加新能力时这个边界帮你决定代码应该写在哪。让模型多一个“决策维度”比如能根据代码结构选择不同编译命令这是 Harness 层的工具定义问题让 Agent 能在全新的运行环境里干活比如接入一个 GPU 计算集群这是 Runtime 层的对接问题。想清楚这件事团队协作时就不会出现“我让你加沙箱能力你怎么去改提示词”的尴尬。5.2 如果自己设计 Agent怎么选型最后给想自己动手搭 Agent 的朋友一些选型建议。如果你只是想在本地快速验证想法优先选一个默认配置开箱即用、Harness 内置了交互终端的工具把 Runtime 先用本地无沙箱模式跑通逻辑再考虑安全加固。如果你的目标是做一个长期运行的自动化服务那从一开始就要把 Harness 的会话恢复能力和 Runtime 的沙箱隔离能力当成硬指标。宁可前期慢一点也要确保任务中断后能恢复命令执行不会污染宿主机。如果你的团队里有成熟的执行平台比如内部的任务调度系统或云端沙箱服务那最合适的路线是保留现成的 Harness自己封装一个满足接口约定的 Runtime 插件。这也是插件注册机制最值钱的地方——不用从零造轮子只要实现好统一接口就能把整套执行后端替换成自己团队的方案。我在实际接触这套体系的过程中最大的体会是很多看似晦涩的 Agent 工具都只是把过去工程界的优秀实践搬了过来Harness 和 Runtime 的分离就是典型的“控制面与数据面分离”思想在智能体领域的一次迁移。理解了它你以后读任何一个 Agent 框架的源代码都会觉得路径清晰、不再迷茫。