harnessrouter

HarnessRouterApache-2.0活跃维护

自托管的统一 Agent Harness 接口,用一套 API 就能跑 Codex、Claude Code、Hermes 等多个编码智能体,统一处理会话、流式输出、文件和失败重试。

HarnessRouter Community Edition: the self-hosted, Apache-2.0 edition of the unified interface for agent harnesses. Run Codex, Claude Code, Hermes, PI, DSH, and more through one API, with sessions, streaming, files, cancellation, and failure handling. Implements the Unified Harness Protocol (UHP), an open standard. Your keys, your infrastructure.

v0.40.3发布于 2026-11-09 19:35 UTC4,317star +35 / 7 天478fork同步于 2026-11-10 11:38 UTC

怎么上手

由 README 提炼,执行前请确认
docker run -d --name harnessrouter -p 127.0.0.1:3000:3000 -v harnessrouter:/data harnessrouter/harnessrouter
硬件要求按 README 说明

需要 Docker 和约 4 GB 磁盘空间,README 未说明 GPU 或显存要求;首次启动会安装已启用的 harness CLI,需要自备模型供应商 API key。

有 Docker 镜像
下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

自托管统一接口,把 Codex、Claude Code 等 agent harness 变成可切换的 API 后端

自托管的统一 Agent Harness 接口,用一套 API 就能跑 Codex、Claude Code、Hermes 等多个编码智能体,统一处理会话、流式输出、文件和失败重试。

核心能力

  • 用 OpenAI Responses 兼容 API 调用,通过 metadata.harness_id 切换 harness
  • 实现 Unified Harness Protocol(UHP),统一会话、流式、文件、取消与结构化失败
  • 内置 31 种 harness 基座,含 Codex、Claude Code、Hermes、Pi、Gemini CLI 等
  • 支持 Idempotency-Key 重试不重复执行,并透传 W3C traceparent 串联链路
  • Docker 单命令自托管,自带 Console 管理密钥、模型供应商与工作区

容易踩的坑

首次启动要等日志出现 ready on :3000 才算就绪,期间 harness CLI 还在安装;初始密码在容器内 /data/selfhost-initial-password,需登录后自行改密;不要加 --user,入口和 Runner 需要 root 管理会话用户,3000 端口被占时改映射到 3100 并保持回环绑定。

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

5 个版本v0.40.3
  1. v0.40.3最新正式版2026-11-09 · 2026-11-09 19:35 UTC

    A task's prompt is no longer on the agent's command line. It reaches the agent's CLI by stdin, a pipe or a file of the session's own, and no longer shows in the process list.

    What changed (#661)

    • 17 agent harnesses take the prompt off the command line:

      • from stdin: Claude Code, Codex, Pi, Oh My Pi, Gemini CLI, OpenCode, MiMo Code, Kilo, MiniMax Code and docker-agent;
      • from a pipe: Cline;
      • by a prompt file: Grok Build, goose and Vibe;
      • through a small read-only launcher that reads the file inside the process: Hermes, OpenSquilla and Qwen Code.

      The note about changed instructions on a continued task goes the same way.

    • The prompt file is the session's own (readable only by it, in a folder only it can open). It is removed as soon as the CLI has read it, and in any case when the turn ends. The folder goes too once it's empty, so no agent lists it in the workspace it shows the model.

    • What each agent stores is unchanged, so a resumed or restored conversation reads exactly as before.

    • Kimi Code and jcode take the prompt only as an argument today. On a self-hosted instance, their setup and Settings say so: "With this agent, other tasks on the same machine can see what it's asked while it works."

    • The shared-document integration is removed from the gateway and the runner. It served a component this image doesn't ship.

    Checked

    • The same requests as before. Every converted agent was recorded on 0.40.2's runner and this one side by side, against a stand-in model. Each ran four turns, with and without a checkpoint and restore before the last; OpenCode and Qwen Code also switched model mid-task. Every model request is identical (system prompts, history and workspace listings included), except MiMo Code: one newline moves from the end of the stored message to the start.
    • Nothing on any command line. The root-only tests read the command line of every process a session owns while a turn runs, for every converted agent, on first and continued turns. They run as root in CI, and they fail against copies with each safeguard removed.
    • Real turns on the release candidate's image: the five usual scenarios (first turn, follow-up, model switch, artifact, recycle) on 18 agent harnesses. A recycle check on Qwen Code, Pi and OpenCode sometimes answers with a later turn's word; 0.40.2 does the same, and the requests are identical.
    • Release gate: on a fresh volume on amd64 and arm64, every default harness installs and the credential canary is clean. The release's tree is identical to the candidate's.

    Full Changelog: https://github.com/HarnessRouter/harnessrouter/compare/v0.40.2...v0.40.3

  2. v0.40.22026-11-09 · 2026-11-09 13:17 UTC
    查看更新说明

    Runner hardening, with its tests now running in CI.

    Upgrading

    Nothing to do.

    Changed (#660)

    • More of the runner's work in a session's folder is done as the session. That covers:

      • reading Hermes's state database, OpenSquilla's transcript, Vibe's export and Kimi Code's log;
      • checking whether a conversation can be resumed, on every agent;
      • making the shared blackboard's files.

      A link in a session's folder then leads nowhere the session couldn't reach itself, as the rest of the runner's work there already does.

    • Every per-turn configuration write is now tested against a link planted at its path: Claude Code, Gemini CLI and Qwen Code settings, Cline's settings files, Codex's config and rollout, Hermes's config and database, the fast-agent session file, and the instruction file.

    • The runner's root-only tests run as root in CI, and the step fails rather than skips if it isn't root.

    Checked

    • Root-only runner tests: 46 passed, as root.
    • Real turns on a running instance: the five usual scenarios (first turn, follow-up, model switch, artifact, recycle) on Codex, OpenCode, Gemini CLI, Claude Code, Pi, Qwen Code, Roder, Hermes, Kimi Code, Vibe and OpenSquilla.
    • Release gate: on a fresh volume on amd64 and arm64, every default harness installs, a second start installs nothing, and the credential canary is clean. The release's tree is identical to the candidate's.

    Full Changelog: https://github.com/HarnessRouter/harnessrouter/compare/v0.40.1...v0.40.2

  3. v0.40.12026-11-09 · 2026-11-09 12:05 UTC
    查看更新说明

    Bug fixes: tool switches, instructions on a continued task, one memory per agent, and new setups on Harness Studio.

    Upgrading

    Nothing to do. Existing setups keep their tool switches; they now take effect as the console describes.

    Fixed (#659)

    • Tool switches (Setup Settings › Tools). A switched-off tool is now withheld from the model through each agent's own setting:

      • Qwen Code: permissions.deny. Its background memory, dream and skill agents go off while a file or shell tool is off.
      • Gemini CLI: tools.exclude.
      • Cline: disabledTools. apply_patch goes with Editor, and Cline's team tools go off with any tool, since a teammate starts with every tool.
      • Codex: its shell tool, through features.shell_tool.
      • Hermes: whole toolsets.
      • dsh: single-tool rows.

      Where an agent can only be asked not to use a tool, the switch now says so: "This agent can't switch it off. Off asks it not to use it, and it may still use it."

    • Claude Code writes its tool settings fresh every turn, so a tool switched back on is available again on the next task.

    • An edit to a setup's instructions reaches a task you continue. Hermes, fast-agent, Kimi Code, Grok Build, MiMo Code, dcode, OpenHands and Qoder used to keep the instructions a conversation started with. Hermes and fast-agent now rebuild from the current instructions. The others are given the current instructions with the next message, marked as replacing the earlier copy. This happens only when the instructions actually changed.

    • One memory per agent. With this instance's memory attached, Claude Code's auto memory and Qwen Code's managed memory no longer keep a second, private memory beside it. Codex's memories and Gemini CLI's experimental auto memory are off too.

    • Harness Studio shows a setup built while you were away. If you left the build page before the build finished, the new setup now appears on Harness Studio a few seconds after it's saved, without a reload.

    • Codex: an option Codex no longer reads is no longer written into its configuration.

    Checked

    Real CLI turns inside the release candidate's image against a recording stand-in model (scripts/tools-off-check.py, scripts/continued-instructions-check.py), compared with 0.40.0:

    • With every tool switched off:
      • Qwen Code, Gemini CLI and Cline offer none of them.
      • Codex, Hermes and dsh offer only what they can't switch off, and the agent is asked not to use it.
    • An edit to the instructions reaches the next turn of a continued task on every agent, and the conversation still remembers its first turn.
    • With this instance's memory attached, Claude Code and Qwen Code keep no second memory.

    Real turns on a running instance:

    • the memories end-to-end check, 24 of 24;
    • the five usual scenarios (first turn, follow-up, model switch, artifact, recycle) on Codex, OpenCode, Gemini CLI, Claude Code, Pi, Qwen Code and Roder;
    • a setup built while you're on another page shows on Harness Studio a few seconds after it's saved.

    Release gate: on a fresh volume on amd64 and arm64, every default harness installs, a second start installs nothing, and the credential canary is clean. The release's tree is identical to the candidate's.

    Full Changelog: https://github.com/HarnessRouter/harnessrouter/compare/v0.40.0...v0.40.1

  4. v0.40.02026-11-09 · 2026-11-09 09:16 UTC
    查看更新说明

    Memories: every new agent remembers what matters for its job, from its first task, with no setup.

    Upgrading

    • Hermes agents no longer read their private built-in memory files. Each agent now keeps one memory, the one you can see and edit in the console. The old files are not deleted.
    • If you already run the memory engines, rerun deploy/memories/up.sh once, so they get the new relay credential.
    • With more than one replica, set HR_MEMORY_GRANTS_TTL_S=0 so a revoked grant takes effect at once.

    What's new (#658, building on #378)

    • Memory is chosen for each agent. A new agent gets memory unless you say otherwise. What the agent is for decides which engine:

      • Mem0 for an agent that serves people, kept separately for each person;
      • Graphiti for an agent that tracks things that change and relate;
      • Hindsight for an agent that learns from its own work;
      • ReMe for notes people read and edit;
      • none for one-shot transforms, such as translating.

      The agent's page shows the engine and why it was chosen, with "Change" next to it. In the API, POST /v1/harnesses takes memory ("auto", "none", {"engine": …} or {"id": …}), and PUT /v1/harnesses/{id}/memory changes it later.

    • Each person's memory is their own. An agent that serves people keeps a separate memory for each person, keyed by the task's user.

      • A task reads its person's memory and the agent's shared knowledge, never another person's.
      • A task writes only to its own person's memory.
      • A task an API key starts without user runs with memory off, and says so.
    • Remembering just works.

      • What the agent knows is recalled at the start of each turn, so it remembers even when the model doesn't think to look.
      • What matters is kept after each task. The turn says "Remembered N things", and a save that fails says so in plain words.
      • Credentials are redacted before anything is stored.
    • One command for the engines. deploy/memories/up.sh starts them and connects them to your instance. They call models through your existing connections, so there is no second model key to paste. On a single-operator instance, running engines are found on their own.

    • Deleting is safe.

      • A deleted agent's memory, and each person's memory under it, is kept for the agent's 30-day restore window, then deleted.
      • Restoring the agent brings back its memory.
      • A read that fails deletes nothing.
    • Share links show only that memory was used: no recalled content, no remembered facts, no ids.

    • Console:

      • "Remember" is one switch.
      • The Memories page has search, recently used, and "Used by".
      • Records read as text, Schema moves under More, and the graph appears only when a memory has links.
      • Every page is laid out for phone, tablet and desktop widths.

    Checked

    Real turns on a running instance, on the release candidate's image:

    • Engine choice:
      • a hotel concierge got Mem0, kept for each person;
      • a repository fixer got Hindsight;
      • an account researcher got Graphiti;
      • a team wiki got ReMe;
      • a translator got none, with its reason.
    • Recall in a new session, with no instruction to use memory, on Claude Code (Mem0), Codex (Hindsight), Hermes (Graphiti) and Pi (ReMe).
    • Per person:
      • another person's new session didn't get the first person's fact;
      • a task an API key started without user ran with memory off and said so.
    • Delete and restore: deleting the agent kept its memory, and after a restore the person's new session still remembered.
    • Share links showed memory steps only as "memory", with no names, arguments or ids.
    • Regression: the five usual scenarios (first turn, follow-up, model switch, artifact, recycle) passed on seven agent harnesses with memory on by default: Codex, OpenCode, Gemini CLI, Claude Code, Pi, Qwen Code and Roder.
    • Release gate: on a fresh volume on amd64 and arm64, every default harness installs, a second start insta
  5. v0.39.12026-11-09 · 2026-11-09 04:39 UTC
    查看更新说明

    Bug fix: instances connected to HarnessRouter Cloud no longer ask Cloud's model list without a key, and no longer pull you into connecting again and again.

    What was wrong (#657)

    • The model list was asked without a key. It used the first HarnessRouter connection's key, and asked with none when that connection held no key. That included instances connected only for Deploy to Cloud, whose key is never a connection. Cloud answers that with "not authorized", and nothing remembered the failure, so every screen with a model picker asked again: hundreds of times a day on one instance.
    • A key Cloud refused looked like "no models". The console offered a new connection, which put the new key behind the refused one, so the problem stayed.
    • Deploy to Cloud started a new sign-in when it simply couldn't read your saved workspaces.
    • A key Cloud refused during a deploy signed you out of your own console.

    Now

    • The model list is asked with a key or not at all, using the first connection whose key Cloud accepts.
    • A failed read waits 10 minutes before it's asked again, and it's logged once.
    • A key Cloud refused says so on its connection, with Reconnect, which replaces that key.
    • Deploy to Cloud starts no sign-in when it couldn't read, and says so when Cloud refused the saved key.
    • A deploy Cloud turns down names what it refused (the agent harness or the model), in Cloud's words.

    Affects 0.16.0 through 0.39.0.

    Checked

    On 0.39.1-rc.1, in a fresh instance:

    • with no HarnessRouter key, reading the connections five times asked Cloud nothing;
    • with a key Cloud refuses, Cloud was asked once, the key showed as refused and was logged once, and six more reads asked nothing. Release gate on a fresh volume: amd64 and arm64 install every default harness, the second start installs nothing, and the credential canary is clean. The release's tree is identical to the candidate's.

    Full Changelog: https://github.com/HarnessRouter/harnessrouter/compare/v0.39.0...v0.39.1

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    Build agent products without handling harness engineering. HarnessRouter is the infrastructure layer that turns existing harnesses like Codex and Claude Code into plug-and-play agent backends, letting your product run tasks, retrieve results, and switch harnesses through one API.

    HarnessRouter implements the Unified Harness Protocol (UHP) and provides an OpenAI Responses-compatible API, handling persistent sessions, streaming progress, files, artifacts, cancellation, and structured failures.

    Switch harnesses. Optimize cost and latency.

    Eight harness × model configurations on the same task. Each metric compares its best and worst results. The lowest-cost and fastest configurations vary by task. Methodology

    31 harness bases today: Codex, Claude Code, Hermes, Pi, DeepSeek Harness, OpenCode, Kilo Code, Qwen Code, Gemini CLI, Cline, Oh My Pi, goose, Kimi Code CLI, MiniMax Code, Aider, OpenHands, CheetahClaws, Grok Build, Agent Zero, System One, Qoder Cloud Agent, MiMo Code, jcode, OpenSquilla, nanobot, ZeroClaw, Mistral Vibe, Docker Agent, fast-agent, Deep Agents Code and Roder. The support matrix shows which run on which provider.

    [!TIP] Get started: Run locally · Integrate into your product · Starter kits · Use managed Cloud

    Quickstart

    Self-host Community Edition with your own provider keys, on infrastructure you control.

    Start with one Docker command, wait for the first launch, then connect a model provider and run your first task.

    You need: Docker · About 4 GB of disk · A provider API key

    No HarnessRouter account required. No bundled model or trial key.

    1. Start HarnessRouter

    docker run -d --name harnessrouter \
      -p 127.0.0.1:3000:3000 \
      -v harnessrouter:/data \
      harnessrouter/harnessrouter
    

    Docker pulls the image if needed. The named volume preserves your database, files, installed harness CLIs, and workspaces between restarts.

    Already installed? docker pull harnessrouter/harnessrouter downloads the latest image but does not upgrade a running container. Follow the upgrade and backup guide.

    Port 3000 busy? Use -p 127.0.0.1:3100:3000 and open port 3100 instead. Keep the loopback binding while using the initial credentials.

    Do not add --user. The entrypoint and Runner need root to manage per-session users. The Console and Gateway run unprivileged; agent processes run as their session’s user.

    For version pinning, Compose, and scripted setup, see the setup guide.

    2. Wait for the first launch

    docker logs -f harnessrouter
    

    The first launch installs the enabled harness CLIs. Continue when the logs show:

    [harnessrouter] ready on :3000
    

    Press Ctrl+C to stop following logs. The container keeps running.

    If the browser refuses the connection, retry after a few seconds while the Console finishes starting. For a missing harness, check backends available: and any requested but not installed warning in the logs.

    3. Open the console

    Open http://localhost:3000, or your chosen host port, and sign in as harnessrouter. Your instance made its own password at first start; read it with:

    docker exec harnessrouter cat /data/selfhost-initial-password
    

    If you set HR_AUTH_PASSWORD when you started the container, sign in with that instead.

    [!WARNING] Set your own password in Profile. Keep the instance local until you do. Saving briefly restarts the Console and signs out other browsers.

    HarnessRouter Community Edition sign-in screen

    Using an existing volume or custom credentials? Check credential precedence and setup.

    These credentials sign you into the Console. You do not need a HarnessRouter API key to run tasks here.

    4. Connect a model provider

    Open the account menu at the bottom of the rail and choose Bring your own key. Find your provider, press Add key, and paste its API key. Its supported models become available in the Console.

    This provider key authorizes model requests. It is separate from the HarnessRouter API key used for product integration below.

    Adding an OpenAI key under Bring your own key

    5. Set up your first agent

    Open Start, say what your agent should do for your users, and press Continue. In Set up an agent harness, leave the agent harness and model on Auto or choose them, then save. HarnessRouter builds the setup on one of your own models: it writes the agent's instructions, picks the harness, model, skills, plugins and tools the job needs, and leaves an example request in the box. Send it to run the first task.

    A setup HarnessRouter built from one sentence, with its example request waiting in the box

    Try an example first. Under Start in HarnessRouter, pick one of the three example jobs. Its request plays back a recorded run, so you see a finished task without spending tokens. Write under it to carry on with your own model.

    The product image example: a recorded run and the image it made

    Change a setup (optional)

    Open the setup in Studio and choose Settings to change its model, instructions, skills, plugins, tools, environment and limits. Add plugins, skills, MCP servers and environments for the whole workspace under Add-ons. The agent harness is fixed once a setup is saved: make a new setup to use another.

    Set up an agent harness: one sentence, with the agent harness and model on Auto

    Integrate your harness into your product backend with one API

    Run product tasks with built-in or custom harnesses as pluggable agent backends. Call your self-hosted instance’s OpenAI Responses-compatible API and select the harness with metadata.harness_id. No Cloud deployment is required.

    Once your harness runs successfully in the Console:

    1. Open API Keys in the Console rail of the same CE instance (default local address), name the key, and press Create.
    2. Store the secret shown once as HARNESSROUTER_API_KEY in your product backend. Never expose it in browser code. This CE-issued key is separate from your Console password and provider key.
    3. Call the API with the Harness ID shown in the Console and a model served by your connected provider.
    export HARNESSROUTER_BASE_URL=http://localhost:3000/api/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
      }'
    

    The task and its transcript appear in the same workspace in the Console. Set "stream": true to receive server-sent events.

    Join a caller's trace to the task.

    Send the W3C Trace Context headers traceparent and tracestate on the request, and the task's model calls carry a child of that trace: the same trace id, a new span id and the sampled flag, so the provider's log and yours are one trace. A value that is not valid W3C syntax is dropped, never refused: a broken tracing header does not fail a task. baggage is never read and never leaves the instance.

    Retry a task without running it twice.

    Send the same request with the same Idempotency-Key when retrying a task. For example, send this request twice using the URL and API key above (key generation needs Python 3):

    IDEMPOTENCY_KEY=$(python3 -c 'import uuid; print(uuid.uuid4())')
    
    for attempt in 1 2; do
      curl --fail-with-body -sS "$HARNESSROUTER_BASE_URL/v1/responses" \
        -H "Authorization: Bearer ${HARNESSROUTER_API_KEY:?}" \
        -H 'content-type: application/json' \
        -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
        -d '{
          "input":"Reply with exactly: it works.",
          "metadata":{"harness_id":"codex"},
          "model":"gpt-5.4-mini",
          "stream":false
        }'
      printf '\n'
    done
    

    Both responses have the same id, and the session contains one turn: the retry returns the first request's result without starting another execution. If the first request is still running, the retry waits for it. Use a new key for each new logical request. Reusing a key with a different request body returns 409; changing only stream still counts as the same request. See Tasks §6: Idempotency.

    Never put a long exact value such as a token, an id or a hash in the prompt: the agent retypes what it reads, and a model drops and swaps characters in strings like that. Attach it as a file (POST /v1/files, then an input_file block; the file lands in the agent's working directory under its filename before every turn that carries it) or hand it to the agent through the harness's environment. A harness takes an env map whose values resolve on every turn: $headers.X-Name takes that header from the request (declare it in additional_headers), vault:name takes a stored secret, anything else is used as written. The agent's shell and tools start with those variables set, so a task can say "the token is in $DEPLOY_TOKEN", and a value that came through a reference is redacted from everything that leaves the sandbox, the response, the stream, the trace and the stored record, even when the agent prints it. A vault: reference reads only a secret your own workspace stored through PUT /v1/mcp-secrets/{ref}. The redaction protects the record, not the agent: a value the agent can read it can also send elsewhere if a prompt or a page tells it to, so hand it a token scoped to the user and the task, short-lived and least privilege.

    The whole API is described at $HARNESSROUTER_BASE_URL/v1/openapi.json, generated from the routes, with a browsable copy at /v1/docs.

    The default URL works when your backend and CE run on the same computer. From another machine or container, use a reachable URL for the CE instance. Read the complete self-hosted API and networking guide →

    Agent harnesses as pluggable backends for your product

    Power agentic features in your product with agent harnesses, including knowledge-work tasks such as creating content and analyzing data. Explore these ready-to-use kits to see harnesses in action as pluggable backends.

    Explore the Starter Kits →

    Start: Open Shop in the Console, pick a kit, and select a harness and model supported by your connected providers.

    Dashboards: use a reachable database and a read-only database account, and review the sample-row setting before connecting. Stored connections are encrypted at rest; set HR_SECRET_KEY to keep the key apart from the data volume.

    Licensing: Starter Kits use different terms from Community Edition.

    Setup guide →

    Deployment choices

    Self-host for control

    • Your infrastructure. One Docker deployment for the Console, Gateway, and Runner.
    • Your credentials and state. Provider keys, sessions, files, and workspaces stay under your control. Model requests still go to your configured provider.
    • Real workspaces. Native filesystem, shell, and Git workflows, with separate session workspaces.
    • No Console product analytics. Community Edition disables the Console analytics pipeline.

    Choose your path to Cloud

    Choose HarnessRouter Cloud for managed deployment, maintenance, and scaling, with tasks running in serverless, isolated sandboxes through the same API contract.

    Local → CloudStart directly in Cloud
    Bring a custom harness you’ve configured locally.Follow the upload guide →Create and run harnesses without a local deployment.Open HarnessRouter Cloud →

    For local uploads: save your custom harness in Settings, select Upload to Cloud, then connect a destination using its Cloud workspace API key. The saved destination key is encrypted at rest like every stored credential (set HR_SECRET_KEY to keep the key apart from the data volume).

    Uploads copy harness configuration, not provider keys, sessions, or generated files. Uploading again replaces that destination’s hosted copy.

    Inside Community Edition

    ┌─ HarnessRouter container ─────────────────────────────────┐
    │  Console :3000   ← only published port                    │
    │       │ same-origin proxy                                 │
    │       ▼                                                   │
    │  Gateway :8080   Responses API + harness lifecycle        │
    │       │ loopback                                          │
    │       ▼                                                   │
    │  Runner  :8081   runs harnesses in session workspaces     │
    │                                                           │
    │  /data volume   database · files · secrets · workspaces   │
    └───────────────────────────────────────────────────────────┘
    

    The Gateway and Runner listen on loopback inside the container. Sessions use separate workspaces and operating-system users, not separate containers. The Console is the entry point for both UI and API.

    See configuration, upgrades and backups, and public deployment with TLS.

    The Unified Harness Protocol

    Unified Harness Protocol (UHP) is the public, versioned contract implemented by Community Edition and HarnessRouter Cloud. Its task surface is deliberately compatible with the OpenAI Responses API, so existing Responses SDKs, streaming parsers, and UI components can work with a UHP server. UHP defines harness execution semantics for harness selection, persistent sessions, files, cancellation, and harness-managed tools and skills.

    This repository contains the Apache 2.0 reference implementation, machine-readable schemas, and the conformance suite.

    Resources

    GoalResources
    BuildCloud & integration docs · API guide · Starter kits
    DeploySetup & operations · Local → Cloud · HarnessRouter Cloud
    ProtocolUnified Harness Protocol (UHP)
    CommunityJoin the community (Discord) · Contribute · LinkedIn · X · Security

    Star History

    License

    HarnessRouter Community Edition is licensed under Apache 2.0. Agent harness CLIs are installed on first launch and remain subject to their respective upstream licenses. See NOTICE for third-party notices and the Starter Kits repository for its separate licensing terms.