HarnessRouter/harnessrouter · 上手攻略
- 仓库:HarnessRouter/harnessrouter
- 链接:https://github.com/HarnessRouter/harnessrouter
- 分类:trending · agent-harness / 自托管 LLM 网关
- 作者:spark
- 更新:2026-09-08
1. 这是什么
HarnessRouter Community Edition 是一个 Apache-2.0 自托管的 agent harness 统一网关,把市面上几款主流的 AI 编程 / Agent CLI(Codex、Claude Code、Hermes、Pi、DeepSeek Harness / DSH)封装成同一套 HTTP API。开发者不再为每个 harness 单独写一遍「启动子进程 / 解析 stdout / 截断流 / 取消任务 / 拿文件产物」那一坨胶水代码,而是用一个端点把任务扔进去,让 HarnessRouter 在容器里替你拉起对应的 harness CLI。
它的官网(https://harnessrouter.ai)写得很直白:「LLM 返回 token,harness 给它一个沙箱、工具和循环,让它返回真实的工作」。GPT-5.2 / Claude Opus 4.8 是模型,Codex / Claude Code 才是 harness。HarnessRouter 介于两者与你的产品之间,是 execution & runtime 层,而不是又一个 AI 封装。
⚠️ 注意:仓库 README 和官网都强调,HarnessRouter Cloud(托管版)和 Community Edition(开源自托管)共用同一个开源协议 UHP(Unified Harness Protocol),后者的实现就是这个仓库。换句话说,自托管跑的是 UHP 的参考实现,不存在「Cloud 版更高级」。
1.1 它解决了什么问题
写一个对接 Claude Code CLI 的 Python 客户端已经要处理:
- 启动一个子进程、设置工作目录、注入 stdin;
- 解析它那种带 ANSI 色码 / 控制字符的 stream-json 输出;
- 处理「任务运行到一半要取消」(kill 子进程但保留 transcript);
- 把 harness 在工作目录里写出的文件回传到调用方;
- 让多个用户/会话之间彼此隔离(文件系统、密钥、环境变量)。
每换一个 harness(Codex、Claude Code、Hermes、DSH…),以上逻辑几乎全部要重写一遍。HarnessRouter 的承诺是:写一次 UHP 客户端,就能切换 harness。在它 2026-09-04 跑过的内部 benchmark 中,同一个任务在不同 harness × model 组合下的成本差异最高约 475×(Claude Code × claude-opus-4.8 vs Hermes × gpt-5.2)—— 而切换本身只是后端配置,不是代码改动。
1.2 协议:UHP 是什么
Unified Harness Protocol(UHP)是 HarnessRouter 团队推动的开放标准,目前规范版本 2026-08-11。它不绑定 HarnessRouter:任何人都可以基于规范实现服务端(用 OpenAPI 3.1 + JSON Schema 2020-12 机器可读),然后用 protocol/conformance 目录下的 64 项 conformance 测试证明自己合规。
测试套件(suite version 2026.8.11.post1)分三类:
- Core(40 项):发现 / 版本协商 / 鉴权 / 错误信封 / harnesses / models / 任务执行(流式 + 非流式)/ 事件流 / sessions / 取消 / 保留请求字段;
- Extended(+8):session 列表与查看 / 文件输入 / artifacts / 下载头 / 路径遍历探针;
- Full(+15):harness 增删改查 / 拒绝不支持的 base / skill 文件夹往返 / MCP 与禁用工具持久化 / session 共享。
⚠️ 一条有趣的工程教训:测试 S-09 「the stream is progressive」专门检测「服务端把流全部缓冲、结束后才一次性 flush」这种最常见的部署错误——通常是被某层反向代理吃掉了。它不是看 schema,而是统计事件到达时间的离散度来抓这个坑。schema 校验发现不了。
社区版在 2026-09-04 用 2026.8.11.post1 套件跑过自托管实例:64/64 通过、0 失败、0 跳过、0 错误,报告公开。
2. 快速安装
2.1 先决条件
- Docker(任何 20.10+ 都行)
- 约 4 GB 磁盘(含镜像体积与首次启动下载的 harness CLI)
- 一家模型供应商的 API key(Anthropic / OpenAI / OpenRouter / Bedrock / Azure AI Foundry / Vercel / llmtr / TokenRouter 之一);没有 key 也能跑起来,但什么任务都做不了
2.2 三步跑起来
Step 1:拉镜像(约 700 MB)
docker pull harnessrouter/harnessrouter
Step 2:启动容器(仅 loopback 监听,密码走默认稍后改)
docker run -d --name harnessrouter \
-p 127.0.0.1:3000:3000 \
-v harnessrouter:/data \
harnessrouter/harnessrouter
⚠️ 不要加 --user。容器必须以 root 启动,因为每个 agent session 会用各自的用户身份跑(隔离工作目录与密钥)。从 0.8.2 起,root 不是默认而是强制要求:检测到 --user 就拒绝启动并明确报错。容器内部自己会 drop privileges。
-p 127.0.0.1:3000:3000 让控制台只在本机可访问,这正是「默认账号上线安全」的来源。-v harnessrouter:/data 把 SQLite 数据库、文件、首次启动下载的 harness CLI 全部持久化在 named volume 里,删掉 volume 实例就归零。
Step 3:等首次启动完成(约 30 秒),再打开浏览器
docker logs -f harnessrouter
首次启动会看到类似这样的几行(README 引用原文):
[harnessrouter] installing Claude Code (Anthropic's terms apply)…
[harnessrouter] installing Codex (Apache-2.0)…
[harnessrouter] installing Pi (MIT) and its MCP adapter (MIT)…
[harnessrouter] installing DeepSeek Harness (MIT, developer preview — version-pinned)…
[harnessrouter] installing Hermes (check its upstream license before use)…
[harnessrouter] data=/data backends available: claude codex hermes pi dsh
[harnessrouter] ready on :3000
⚠️ 首次启动 ~30 秒不要慌。如果立刻访问 http://localhost:3000 看到连接被拒绝,是正常的——容器还在装 harness CLI。一旦看到 ready on :3000 再开浏览器。这一行 WARNING: using the DEFAULT password 每次启动都会出现,直到你在 Profile 改了密码为止。
打开浏览器,用以下默认账号登录:
- 用户名:
harnessrouter - 密码:
harnessrouter
进去后第一件事:Profile → 改密码。如果你的机器是脚本化的、希望无人值守,可以在 docker run 阶段预设:
-e HR_AUTH_USER=you \
-e HR_AUTH_PASSWORD=the-password-you-chose
2.3 不想用 docker run?Compose 也行
cp .env.example .env
docker compose up -d
⚠️ README 明确警告:docker-compose.yml 默认把 3000 端口发布到所有网卡(3000:3000),不是 loopback。生产部署前必改这一行,否则默认密码直接暴露在网络上。
2.4 Docker 资源回收与迁移
- 删实例:
docker rm -f harnessrouter && docker volume rm harnessrouter(volume 必须显式删) - 迁移:复制
/datavolume 即可,整个状态(SQLite、文件、转写、所有 harness 安装)一起搬走
3. 核心用法
3.1 配 Provider(必做)
控制台 → Integrations → Add Integration,三个字段:
- 名字(自取)
- Provider(Anthropic / OpenAI / OpenRouter / Bedrock / Azure AI Foundry / Vercel / llmtr / TokenRouter)
- API key
不用告诉 HarnessRouter 模型清单:产品自己维护各 Provider 的模型列表,Provider 一加,对应行的模型就出来了。
⚠️ 想用 OpenAI 兼容的自托管 endpoint(比如本地 vLLM / llama.cpp)?在 Provider 里选 openai 而不是 .env.example 里那个 openai-api 字段名,并加 base_url。Provider × 后端不是随便组合的,对照表(README 列出):
| Connection provider | 能配给哪些 backend |
|---|---|
| anthropic | Claude Code, Hermes, Pi |
| openai | Codex, Hermes, Pi |
| openrouter | Codex, Hermes, Pi, DeepSeek Harness |
| azure-foundry | Codex, Hermes, Pi |
| bedrock | Claude Code, Hermes |
| tokenrouter | Claude Code, Codex, Hermes, Pi, DSH |
| vercel | Claude Code, Codex, Hermes, Pi, DSH |
| llmtr | Claude Code, Codex, Hermes, Pi, DSH |
配错时不会报错,而是任务「跑超长时间然后 turn 为空」。从控制台加 Integration 不会遇到这个问题——UI 只会列出能用的 Provider。
3.2 用环境变量跳过浏览器(脚本化部署)
适合 CI 或无人值守:
-e HR_SECRET_GLOBAL_HARNESS_CONN_ANTHROPIC='{"name":"anthropic","provider":"anthropic","api_key":"sk-ant-…"}'
-e HR_SECRET_GLOBAL_HARNESS_POLICY_CLAUDE='{"chain":["anthropic"]}'
每个 backend 一条 …_POLICY_<BACKEND> 变量(CLAUDE / CODEX / HERMES / PI / DSH)。chain 是 fallback 顺序,可以填多个 provider。
3.3 发起一个 Agent 任务
控制台走的是「Agent harnesses → 选 harness → New task」,填提示词 → 在消息框下方的 chip 选模型 → 发送。转写(transcript)会流式回来:每个 harness 跑的命令、碰过的文件、最终答案都看得到,可以整段带走或单文件下载。
⚠️ README 强调:「启动时不带 --user」「首次启动慢是因为要装 5 个 harness CLI」、「装完只显示实际装上的 backend,没装的会显式列出而不是悄悄缺席」。这些是社区版从根上想清楚的设计选择,不要在生产环境「优化」掉。
3.4 通过 UHP 直接调 API(不走控制台)
社区版本身实现了 UHP 服务端,端口应该是网关 :8080(loopback)。你可以用 OpenAPI 客户端生成器生成任意语言的 SDK,或直接 curl:
# 列出可用 harnesses(端点路径以 UHP 规范为准)
curl -H "Authorization: Bearer $UHP_API_KEY" \
http://localhost:8080/v1/harnesses
⚠️ 准确的 :8080 vs :3000 端口分工、HTTPS 接入与 token 申请流程在 README 没有完整展开;如果你准备在 CI 接入,以仓库 docs/ 目录的实际版本为准。这里不给伪造的命令。
3.5 Starter Kits:拿来即用的小产品
控制台首页有 Starter Kits 列表。每个 kit = 一个完整的 agent 产品(不是代码片段):一个 app、一个配置好的 agent、一份教它写什么的 skill。点 Launch 即可。每个卡片会显示要消耗哪个 base × 哪个 model,让你动手前就能估算成本。已连接的 Provider 才有可选项,没连的会标灰并说明「Add a provider that serves this model to use it」。
README 提到的两个示例 kit:
- Deck kit:一句提示词("A 5-slide deck explaining what a container image is, for new engineers.")出 PPT,边做边出 slide,发现形状错了可以中途打断;
- Sheet kit:表格的每一行是一个 harness run,左侧列当输入,按 Run 后逐格填,带 Stop 按钮。
4. 典型适用场景
- 多 harness 评测:同一个任务在 Codex / Claude Code / Hermes / Pi / DSH 之间跑,比成本与质量。改一行配置即可切,实测成本差异最高 ~475×(官网公开数字)。
- CI 里跑 agent 任务:在 GitHub Actions / GitLab CI 里拉镜像 → 起容器 → 用 UHP 提交任务 → 拿 artifacts → 关掉。比把每个 harness CLI 装到 runner 上干净很多。
- 不想让 agent 进程碰到产品密钥:容器启动后以 root 起来,内部为每个 session 切换到一个独立 Unix 用户,session 间文件路径属于不同 uid,「读了不该读的东西」不是被「劝阻」而是被文件系统阻止。README 把这点写得很重。
- 想在本地/私有云里跑 coding agent:跳过 Anthropic / OpenAI 的 cloud agent 套件,自己掌握 key、文件、telemetry。
- 做一个 agent 产品但不想重写 harness 集成:官网把 Readily 当作示例客户——「24 小时内从想法到生产里的 agent」。
⚠️ 不适合的场景:纯 LLM 路由(只想要「按 prompt 选模型」)。那是 LiteLLM / LLMRouter / OpenRouter 这类 LLM router 的领域。HarnessRouter 是 harness router——目标是把 harness(带沙箱 / 工具 / 循环)作为不可拆的整体来调度。
5. 坑与注意
- 首次启动 ~30 秒不要关掉容器。30 秒只是安装 5 个 CLI 的耗时,不是卡死。看
docker logs里的ready on :3000才是真信号。 --user必删。0.8.2 起容器检测到就拒启动。如果你之前用自定义user:跑过,升级前必删。- 默认密码上线:每个新 volume 在改密码前,每次启动都会打 WARNING。本机 loopback 部署时这是提醒,不是事故。
- Provider × backend 错配不会报错。会空转非常久然后 turn 为空。线上最好用控制台加 Integration,避开环境变量暗坑。
- HERMES / Claude Code 许可证问题:hermes-agent 上游未声明 license,Claude Code 走 Anthropic 自家条款——README 把它们从镜像里移到了「首次启动由你亲自从上游拉」,原因是镜像内再分发违反各自条款。社区版镜像只内嵌了明确可再分发的:Codex(Apache-2.0)、Pi(MIT + MIT MCP adapter)、DSH(MIT,开发预览,版本 pin)。⚠️ 这意味着 hermes / Claude Code 第一次启动需要外网访问上游仓库,没网就跑不起来这两个 backend。
- Docker Compose 默认 3000:3000 暴露所有网卡。线上部署必改回
127.0.0.1:3000:3000或前置反向代理。 - 端口冲突:宿主机 3000 被占,只改
-p左半(如-p 127.0.0.1:3100:3000)。容器内始终听 3000。 - 忘记密码:删除
/data/selfhost-auth.json重启,回落到HR_AUTH_USER/HR_AUTH_PASSWORD环境变量或默认账号。没有邮件重置路径——这是自托管设计,不是 bug。 - 跨 session 文件隔离靠 Unix 用户,不是 SELinux / AppArmor。没跑在 Docker 默认 capability 上没问题,但若自己加
--privileged/--cap-add/ 自定义 seccomp,就破坏了原有隔离模型。 - UHP 规范与实现都在快迭代。conformance 套件 2026.8.11.post1 / 协议 2026-08-11 / 自托管实现在 2026-09-04 跑 64/64 通过。短期内版本号变化可能快,生产部署前请确认 suite_version 与 generated_at 时间戳。
- Statshub / Cloud 路径不在本仓库。HarnessRouter 官网还有 Cloud 版(managed,Y Combinator 背书,2026-07-24 首发)。Community Edition 不包含 Cloud 的 dashboard / 计费 / SSO 等能力。
- 企业条款自检:用 Cloud 版的话注意「$20/月起的 plan 把 plan 金额全部计入 usage」这句话——月费是预付 credit,不是订阅。
6. 与同类对比
| 维度 | HarnessRouter CE | LiteLLM | OpenRouter | LLMRouter | NVIDIA llm-router |
|---|---|---|---|---|---|
| 抽象对象 | harness(沙箱 + 工具 + 循环) | 模型请求 | 模型请求 | 模型请求(评测 + 部署) | 模型请求 |
| 自托管 | ✅ Docker 单镜像 | ✅ Python lib + proxy | ❌(托管为主) | ✅ Python lib | ⚠️ Notebook 形式 |
| 接入成本 | 一次集成,5 个 harness 即用 | 一次集成,~100 provider | API key | 一次集成 | 仅 notebook demo |
| 隔离模型 | 每 session 一个 Unix 用户 | 不适用 | 不适用 | 不适用 | 不适用 |
| 标准 | UHP(自定开放标准) | 无 | OpenAI 兼容 | 自研 router API | 无 |
| Conformance 套件 | 64 项 HTTP 测试 | 无 | 无 | xRouteBench(路由评测) | 无 |
| 流式 + 取消 + artifacts | ✅(UHP 规范强约束) | 仅 chat completion | 仅 chat completion | 部分 | 否 |
| License | Apache-2.0 | MIT | 服务条款 | MIT | Jupyter |
| Stars(公开近似) | 669 | 30K+ | 巨大 | ~1K | 343 |
结论:如果你的需求是「在 N 个不同模型之间挑一个」——LiteLLM / OpenRouter / LLMRouter 都是更轻的选择。只有当你需要让 agent harness(带 shell / 文件系统 / 工具循环的那种 CLI)作为统一后端被调度,HarnessRouter 的「harness × model」矩阵才有意义:它的 475× 成本差异正来自这种矩阵的可路由性,这是 LLM router 给不了的。
7. 一句话推荐
如果你想搭「一个能跑 Codex / Claude Code / Hermes / Pi / DSH 的本地/私有 agent 网关」,并且能接受 700 MB Docker 镜像、首次启动 ~30 秒、且 hermes/Claude Code 首次启动需要外网拉上游 —— HarnessRouter Community Edition 是 2026 年这个细分里最完整的选择;如果你只是想让同一个 prompt 在不同模型间选一个,别绕弯,去 LiteLLM 或 OpenRouter。
⚠️ 不确定 / 已知边界
:8080网关端口与:3000UI 端口分工、/v1/...UHP 端点的精确路径在 README 没有完整列出(README 主要讲控制台流),自动化接入前请直接看docs/目录或protocol/下的规范。- 各 harness 的当前 pinned 版本、license 状态可能在 PR 间变化(hermes 至今未声明 license 是一个已知的上游问题);本文引用的 backend 列表以 2026-09 仓库
main分支为准。 - 官网公开的「≈475× 成本差异」是单任务测量值,README 没声明是不是典型值或最大极值;本文按官网措辞如实标注「实测最高 ~475×」,不要当普遍结论。
- 「第一行 WARNING 提示」「首次 30 秒」这些体验数字来自 README 与 2026-09-04 self-host 报告,没有在我自己的环境复跑——本文不复现。