Quickstart

Install BitRouter and get your agent routing in under a minute — pick self-host or Cloud, then onboard via the Agent Skill, the CLI wizard, or manual env keys.

9 min readEdit this page

This page gets BitRouter routing for your agent in under a minute. There are two deployment modes, and three ways to onboard either one — the Agent Skill, the CLI wizard, or manual env keys.

  • BitRouter Cloud (default). Hosted endpoint at api.bitrouter.ai. No upstream keys to manage; per-request billing, or BYOK on top.
  • Local proxy. A single binary on your machine, BYOK with your own provider keys. Basic routing requires no external service.

Both modes use the same open-source routing core (Apache 2.0). The deployment boundary changes, but the client protocol does not, so you can switch modes without rewriting your harness.

Self-host or Cloud?

The routing contract is shared, while operational surfaces follow the deployment boundary:

  • Self-host if you already have provider keys, run local/private models, have data-residency rules, or are prototyping solo.
  • Cloud if you want no key management, per-request billing, and a managed provider network without upstream provider signups.
CapabilitySelf-hosted (OSS)Cloud
Universal API + cross-protocol routing
BYOK (bring your own provider keys)
Local / private model endpoints
Model fallback & provider selection
Model variants & presets
Adaptive routing policies
Guardrails
OTLP trace + metric export
Local MCP gateway & server tools
Local ACP adapters
Structured outputs
Namespace isolation primitive
Managed provider network (no upstream keys needed)
Hosted activity and request receipts
Managed billing (one wallet, per-request)

BitRouter does not package a separate enterprise suite today. Teams with deployment, security, procurement, or support requirements can contact the founders and help shape the team offering.

Do you need your own provider keys? Only if you self-host with BYOK — a Cloud account needs no upstream keys: one sign-in covers the whole hosted network, billed per request, failed requests not charged. You can also attach Cloud to a self-hosted binary and use both.

Install the binary

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/bitrouter/bitrouter/releases/latest/download/bitrouter-installer.sh | sh
brew install bitrouter/tap/bitrouter
npm install -g bitrouter
cargo install bitrouter

Onboard via the Agent Skill

For agent runtimes that support skills (Claude Code, Cursor, Codex, Copilot, etc.). BitRouter ships a /bitrouter Agent Skill so the agent can install, configure, migrate to, and troubleshoot BitRouter on its own — the skill carries the facts that drift easily (the listen port, env var names, the provider/model slash form, which subcommands exist), and it lives in the main repo at skills/bitrouter/, kept in sync with the code in the same change. Install once:

npx skills add bitrouter/bitrouter    # via the generic skills CLI

Then ask your agent: "Set up BitRouter for me." — the agent runs the wizard, picks Cloud by default, and verifies the connection autonomously.

The /bitrouter Skill explains which structured bro command to use. The agent host still owns approval and execution; BitRouter does not publish the local skill directory as an MCP origin server.

Onboard via the CLI wizard

For terminal-first setup, launch the wizard:

bro

Bare bro runs a network-free credential probe — BYOK env keys, the cloud session file, and the local credential store — then launches the wizard when nothing is configured. After setup, it opens the configured TUI conversation. The wizard walks three steps:

  1. Credentials — sign in to BitRouter Cloud (default), log in to a provider, or paste a BYOK key.
  2. Harnessclaude or codex, installed via the native installer when missing.
  3. Finish — launch the harness, start the proxy at http://127.0.0.1:4356, or exit.

Every step maps to a flag, so an agent (or CI) can run the whole flow without a human. --yes never blocks: it consumes flag-supplied credentials, reports-and-skips anything that would need interactive OAuth, and emits a JSON result envelope on stdout:

bro init --yes --provider openai --provider-api-key "sk-..." --harness claude --after serve
bro init --yes --use-detected --harness claude --after serve   # accept env keys, run proxy
bro init --yes --api-key "brk_..." --after exit                # Cloud key, no launch
bro init --reset                                               # clear credentials, start over

Every flag is documented in the bro init reference. The wizard never writes bitrouter.yaml beyond the canned starter template — your routing config stays yours to edit.

Run self-hosted

Set your provider keys in the environment and start the proxy:

export OPENAI_API_KEY=sk-...    # ANTHROPIC_API_KEY / GEMINI_API_KEY also work
bro start
# Proxy running at http://127.0.0.1:4356

BitRouter auto-detects any key set in the environment — no config file needed. Any provider whose key is present is immediately available. See BYOK for the full list of recognized variables, or local & private models to point BitRouter at Ollama, vLLM, or LM Studio for free.

For advanced routing rules, guardrails, or multi-account failover, scaffold a config file:

bro init          # writes ./bitrouter.yaml (override with `-c <path>`)
bro start

Use BitRouter Cloud

Sign in to a BitRouter Cloud account from the terminal — one account covers every model the hosted network offers, with no upstream provider keys required:

bro cloud login   # RFC 8628 device flow against api.bitrouter.ai
bro start         # the `bitrouter` provider auto-enables once signed in

Cloud is not a different binary — it's an account you attach. Signing in from a self-hosted binary routes Cloud-managed models alongside your BYOK keys, and you can add or remove the Cloud account at any time without affecting the binary's self-hosted capabilities. You can also point an agent straight at the hosted endpoint without running a local binary at all. See the Supported Models catalog for pricing.

Point your agent at the proxy

However you start it, BitRouter is a drop-in proxy. Point your agent runtime at the proxy base URL — http://127.0.0.1:4356 when self-hosting — and every model call routes through BitRouter with no harness changes.

Verify with a request:

curl http://127.0.0.1:4356/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-4o",
    "messages": [{"role": "user", "content": "Hello!"}]
  }'

Point any OpenAI-compatible runtime at http://127.0.0.1:4356/v1 to route through BitRouter.

Two commands make the routing decision itself legible:

bro models                            # every model id routable right now
bro route anthropic/claude-opus-4.8   # preview the routing decision

Model selectors use two similar-looking forms for different jobs:

FormMeaningExample
provider/modelStable logical model id; BitRouter may route it through any eligible provideranthropic/claude-opus-4.8
provider:modelExplicit provider pin for local routinganthropic:anthropic/claude-opus-4.8

Use the slash form by default. Use the colon form only when you intentionally need one configured provider, such as a subscription-backed route. See Routing for the complete resolution order.

Adaptive routing

Everything above is a static router. The adaptive half — the learn step of the act → observe → evaluate → learn loop — is opt-in, deterministic, and adds no LLM call to the path. Its artifact is policy-lock.yaml, living next to bitrouter.yaml: Git owns its history; the local database owns the evidence.

One command scaffolds everything:

bro policy init coding --preset coding --economy moonshotai/kimi-k2.7-code

That writes a two-tier table (strong = your preset's model, economy = the cheap one), clamps tool-carrying requests to the strong tier so a downgrade never strands a tool call, and binds the policy to the preset in bitrouter.yaml with writeback: locked. Selecting the preset as the model is the entire opt-in boundary — bare model requests are never touched by a policy:

curl http://127.0.0.1:4356/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model": "@coding", "messages": [{"role": "user", "content": "..."}]}'

Each request is fingerprinted by loop step (opening, after_<tool>, midstream) and resolved fingerprint → tier → model. An unmatched fingerprint falls back to default_tier, and the table starts conservative: everything routes strong until evidence says otherwise.

Learning from live traffic

With adequacy enabled, every request through a policy-bound route is classified by outcome and recorded against its fingerprint — deterministically, with no LLM judge in the path. Two halves act on that signal:

  • Escalation (the safety half) — a downgraded fingerprint that hard-fails escalation_threshold consecutive times is pinned up to the strong tier. Pins decay after a cooldown.
  • Exploration (the aggressive half) — with explore_enabled, roughly 1-in-explore_interval candidate requests is trialed on the economy tier; explore_threshold consecutive adequate trials qualify that fingerprint for the cheap tier. A failed trial escalates and stops.
# policy-lock.yaml
adequacy:
  enabled: true
  escalation_tier: strong
  escalation_threshold: 2
  pin_cooldown_secs: 1800
  explore_enabled: true
  explore_tier: economy
  explore_threshold: 3
  explore_interval: 5

The evidence rule is asymmetric: negative evidence escalates immediately, while a cheaper route needs repeated success before it becomes effective. A policy with adequacy off behaves exactly like its deterministic table.

The signal itself — the outcome classes it records, the per-request cost metering alongside it, and the objective-scored eval engine landing on top — is Evaluation.

Publishing what it learns

Qualified downgrades live in the database until you publish them. The cycle is explicit and digest-checked:

bro policy status          # path, digest, writeback mode, bindings
bro policy evolve          # dry-run: which routes would materialize
bro policy unlock          # permit programmatic writeback
bro policy evolve --apply  # atomically republish policy-lock.yaml
bro policy reload          # daemon picks it up — no restart
bro policy lock            # forbid programmatic writes again

evolve --apply only adds qualified routes — it never overwrites or removes anything you or Git wrote, and a detected intervening edit aborts the publish instead of clobbering it. Commit the result and the improved table is in Git, where a policy belongs.

bro policy create + bro key sign are a different surface — per-key access control (allowed models, budgets, rate limits), not routing. See Guardrails.

Next steps

How is this guide?

On this page