Self-host in a few minutes, mint an agent key, and point any OpenAI- or Anthropic-compatible SDK at your instance. Requires Docker with Compose v2.
One command checks Docker, fetches a source archive at a single ref, generates secrets into a mode-600 .env, and boots the stack. The first build takes a few minutes; set POLYROUTER_IMAGE=ghcr.io/izzoa/polyrouter:<version> and the installer pulls that published image instead, skipping the build. The ref defaults to main — pipe through POLYROUTER_REF=<commit-sha> to pin it, which the installer recommends for a reproducible install.
# or from a checkout — uses your working tree, downloads nothing
git clone https://github.com/izzoa/polyrouter.git
cd polyrouter && ./install.sh
Create a key in the dashboard (Agents → New agent — shown once), then point your client at your instance. Any tool that lets you set a base URL and API key works with no other changes.
| OpenAI SDK | https://<your-instance>/v1 |
|---|---|
| Anthropic SDK | https://<your-instance> |
| API key | Authorization: Bearer poly_… or x-api-key: poly_… |
curl https://you/v1/chat/completions \
-H "Authorization: Bearer poly_…" \
-H "Content-Type: application/json" \
-d '{"model":"auto",
"messages":[{"role":"user",
"content":"hi"}]}'
curl https://you/v1/messages \
-H "x-api-key: poly_…" \
-H "Content-Type: application/json" \
-d '{"model":"claude-sonnet-5",
"max_tokens":256,
"messages":[{"role":"user",
"content":"hi"}]}'
Any coding harness or agent works — it's just a base URL and a poly_ key. polyrouter is built for them: the L1 structural router excludes the harness system preamble from its features, so a huge OpenClaw or Hermes system prompt can't skew model:"auto" toward the top tier.
Harness traffic also carries a workload class. Fenced code above the configured thresholds — 30% of the scanned window and at least 200 characters by default — reads as code; an image reads as vision, a declared JSON output format as structured. Point a Workload target at a tier or model under Routing → Auto and that class claims its auto requests before band targets, Layer 2 and the cascade — an explicit model or the tier header still wins, and unset classes change nothing. How routing decides →
// ~/.openclaw/openclaw.json (JSON5)
{
models: {
providers: {
polyrouter: {
baseUrl: "https://<your-instance>/v1",
apiKey: "poly_…",
api: "openai-completions",
models: [{ id: "auto" }],
},
},
},
agents: { defaults: { model: { primary: "polyrouter/auto" } } },
}
# ~/.hermes/config.yaml
model:
default: auto
provider: custom
base_url: "https://<your-instance>/v1"
api_key: "poly_…"
# any tool that lets you set an OpenAI base URL and key
export OPENAI_BASE_URL="https://<your-instance>/v1"
export OPENAI_API_KEY="poly_…" # then run with model: auto
Six focused guides for going deeper — how routing decides, how providers connect, the wire API, the security posture, every config knob, and day-two operations.