在一个接口下跑任意 agent harness
作者:Akshay Pachaar(@akshay_pachaar,Daily Dose of Data Science 联合创始人)
UHP 和 HarnessRouter 如何把 agent 执行在 Codex、Claude Code、Hermes 等运行时之间统一起来。
当一个 agent 产品直接集成某一个 harness 时,它的后端就开始依赖那个 harness 的任务格式、事件流、会话模型和文件系统行为。
不像模型路由,再加一个 harness 不是改个配置或者参数的事——你是在加入另一个运行时,它自己规划工作、调用工具、管理文件、决定任务何时算完成。
而支持多个运行时很关键,因为 harness 的构建方式各不相同。
正确的选择可能取决于任务、需要的工具、provider 访问权限、可用模型、成本、延迟或用量限制。就像模型一样,一个产品应该能做到增加或替换 harness,而不必围绕它重建功能。
模型路由解决不了这个问题。它选的是哪个模型处理一次推理请求,而 agent 循环本身没变。harness 路由选的是拥有整个任务的 agent 运行时。
今天我们讲第二种路由背后的工程。我们会理解为什么产品可能需要不同的 harness、它们之间必须标准化什么,以及统一 harness 协议(UHP)如何定义这份契约。
然后我们会用 HarnessRouter——UHP 的一个开源实现——把同一个工作流分别跑过 Codex 和 Claude Code。
一、为什么一个产品可能需要另一个 harness
harness 在工具执行、上下文管理、权限、技能和所支持模型上做出不同选择。同一个 harness 未必能为每个产品功能提供正确的工具或模型支持。
一个产品服务的客户也可能有不同的 provider 访问权限。有的客户已经在用 OpenAI 的模型,另一个客户整套环境是围绕 Anthropic 搭的。配额或者 provider 故障也可能让某个后端不可用。
评测是另一个原因。把同一个任务跑过两个 harness,它们的成本、延迟、工具使用和产出会更容易比较。而如果每个后端需要不同的任务和事件代码,这个比较就很难做。
目标不是每次会话都切换 harness,而是不要让产品依赖某一个运行时。
一个团队可以按功能选 harness、给客户提供受支持的选择,或者在不改动产品工作流的前提下替换后端。
二、一次模型调用并不能跑完整个任务
模型 API 接受输入、返回生成的输出。应用程序仍然要负责运行被请求的工具、发起后续的模型调用、管理文件、权限、重试和任务状态。
一个 agent harness 包含了这个控制循环。它可以检查文件、调用工具、编辑项目、运行命令、审查输出,并决定何时停止。
Codex 和 Claude Code 可以使用相似的模型但仍然表现不同。它们的指令、工具、上下文处理、权限和完成规则都会影响运行结果。
三、模型路由 vs harness 路由
模型路由发生在推理层内部。它根据价格、延迟、上下文长度、可用性或实测质量选一个端点。应用程序或 harness 仍然拥有 agent 循环。
harness 路由选的是拥有任务的运行时。这个选择会改变工具、技能、工作区、权限和事件流。
一个产品可以同时使用两层路由。在 UHP 里,model 选模型,而 metadata.harness_id 选配置好的 harness。
四、每个 harness 都要求产品自己处理什么
第一次集成往往是一个小适配器:启动一个进程,读取它的输出。但产品的 UI 还需要实时进度、会话连续性、文件上传、下载链接和访问规则。
取消需要一个定义好的路径,因为本地进程、远程任务和会话的停止方式各不相同。错误也需要足够结构化,好把 provider 故障、权限拒绝、时间限制、文件缺失和任务取消区分开。
在 Codex 旁边再加一个 Claude Code,意味着这些映射要重新构建和维护一遍。产品需要一个两个集成都能遵循的、统一的任务生命周期。
五、UHP 定义的任务生命周期
统一 harness 协议定义的是应用程序和 harness 服务器之间的 HTTP 契约。它覆盖任务创建、进度、会话、文件、取消和错误,但不定义 harness 如何做规划。
UHP 使用一个形状类似 OpenAI Responses API 的接口。客户端通过 POST /v1/responses 启动工作。请求里包含任务输入、模型、配置好的 Harness ID,以及可选的执行限制。
一个 response 记录一个任务。一个 session 把共享对话状态和工作目录的相关 response 归到一组。一个「配置好的 harness」把基础 harness 和它的模型、指令、技能、工具、MCP 服务器及限制组合在一起。
实时任务使用 Server-Sent Events(SSE)。每个事件带一个类型和序号,所以客户端可以按顺序处理这个流。
事件报告文本输出、工具活动、文件和任务状态。应用程序直接展示它们,不需要去逐行搜索原始终端输出来还原每个事件。
UHP 接受请求里的小文件,更大的文件走上传。生成的文件成为 artifact,应用程序可以列出并下载。这些操作由 files 规范定义。
后续任务用 previous_response_id。服务器在同一个会话里继续,带着它的对话、工作目录、文件和配置好的 harness。
你仍然可以把工作交接给另一个 harness。如果 Codex 开始了一个任务、你想让 Claude Code 接手,就用 Claude Code 起一个新 session,把相关上下文传给它——比如到目前为止的工作摘要、下一步指令,以及它需要的文件。把它当成把任务交给另一个开发者:工作可以继续,但 Claude Code 不是在恢复 Codex 的会话。
作为对比,应用程序起两个 session,给它们同一个 PDF 和同一个 prompt。每个 harness 收到的是明确的输入,而不是另一个运行时制造的隐藏状态。
六、HarnessRouter:一个可以自己跑的 UHP 实现
HarnessRouter 是 UHP 的实现,提供一个兼容 OpenAI Responses 的 API,负责持久会话、流式进度、文件、artifact、取消和结构化错误。
它对外的主张很清楚:在接入某一个 harness 之前,你的产品后端要处理的任务格式、事件流、会话模型、文件系统行为这些东西,现在都被这一层收走了。
可以在自己机器上跑社区版(Apache-2.0,Docker 一条命令):
docker run -d --name harnessrouter -p 127.0.0.1:3000:3000 -v harnessrouter:/data harnessrouter/harnessrouter
需要 Docker、大约 4GB 磁盘、一个 provider API key。不需要 HarnessRouter 账号,也不带试用 key。首次启动时会安装启用的 harness CLI,等日志出现 ready on :3000 就可以打开 localhost:3000(默认账号密码都是 harnessrouter,官方提醒先去 Profile 改掉)。
接自己产品的后端,就是调它的 Responses 兼容接口,用 metadata.harness_id 指定 harness:
curl --fail-with-body -sS "$HARNESSROUTER_BASE_URL/v1/responses" -H "Authorization: Bearer ${HARNESSROUTER_API_KEY:?}" -H 'content-type: application/json' -d '{"input":"Reply with exactly: it works.","metadata":{"harness_id":"codex"},"model":"gpt-5.4-mini","stream":false}'
流式就把 stream 设成 true。
他们给的对比数字值得记一下:八个 harness 与模型的配置跑在同一个任务上,每个指标比较最好和最差的结果——成本相差 99.8%(223 credits 对 0.47),端到端延迟相差 3.2 倍(4 分 36 秒对 1 分 25 秒)。而且他们注明:最低成本和最快的配置随任务而变。
七、这份协议的技术定位
UHP 是一个公开的、带版本号的契约,社区版和 HarnessRouter Cloud 都实现它。它的任务接口刻意做得兼容 OpenAI Responses API,所以现有的 Responses SDK、流式解析器和 UI 组件可以直接配合 UHP 服务器工作。
仓库里包含 Apache-2.0 的参考实现、机器可读的 schema,以及一致性测试套件。协议版本、OpenAPI/JSON Schema、治理方式都在仓库里公开。
架构上是三个进程:Console(:3000,唯一对外暴露的端口)、Gateway(:8080,Responses API 加 harness 生命周期)、Runner(:8081,在会话工作区里跑 harness)。会话之间用的是分开的工作区加分开的操作系统用户,而不是分开的容器。
要不要用,判断标准其实很简单:如果你在做的是一个要接入 agent 能力的产品,而不是给自己用的一次性脚本,那「支持第二个 harness」的成本现在是可以被收走的一层。 如果只是本地脚本,多装一个 CLI 就够了,不需要这层。
链接
原文(Akshay Pachaar):https://x.com/akshay_pachaar/article/2100888166219886818
HarnessRouter 仓库:https://github.com/HarnessRouter/harnessrouter
UHP 规范:https://unifiedharnessprotocol.org/
起手模板:https://github.com/HarnessRouter/starter-kit
#Agent工程 #协议 #自托管



