Model routing
Understand model selectors, candidate eligibility, fallback behavior, and compatibility across provider protocols.
Model routing determines what a requested model id means after model sources are connected. Use Supported Models to browse the public catalog and Providers to connect keys, private endpoints, or custom model declarations.
Model resolution turns the request's model into an ordered chain of eligible provider endpoints. Most policies need only a logical model id or a named fallback chain.
Model selector forms
The separator carries selection meaning:
| Form | Meaning | Example |
|---|---|---|
provider/model | A stable logical model id from the registry; every eligible provider that declares it can join the route | anthropic/claude-opus-4.8 |
provider:model | A direct local route through one configured provider | anthropic:anthropic/claude-opus-4.8 |
Prefer the slash form in application code. Use the colon form when the provider itself is part of the decision, such as a subscription-backed account or a specific custom endpoint.
Resolution order
BitRouter resolves a request in four stages:
- Apply a known
@presetand optional:variant. - Treat
provider:modelas an explicit provider route. - Resolve a matching entry under
modelsas a virtual model. - Otherwise, build a cascade from active providers that declare the bare model.
Subscription-backed providers are explicit-route-only. A bare model never silently consumes a personal Claude or Codex subscription.
| Selector | Use it for |
|---|---|
openai:openai/gpt-5.4 | Pin one provider and logical model |
openai/gpt-5.4 | Route a logical model through eligible providers |
coding | Use a named chain from models |
@fast | Apply a reusable preset |
@fast:cost | Apply a preset, then a known variant |
bitrouter/auto | Use the routing policy bound to the auto preset |
Candidate eligibility
For a bare model, BitRouter filters active providers by only, ignore, required tags, request capabilities, and protocol compatibility. It then orders candidates by explicit provider priority or the registry's provider-class priority, followed by provider ID.
Presets and variants accept three sort values:
| Value | alpha.31 behavior |
|---|---|
alphabetical | Provider priority, then provider ID |
cost | Accepted, but currently uses the same deterministic fallback order |
latency | Accepted, but currently uses the same deterministic fallback order |
Cost- and latency-based live scoring are not active in alpha.31. Do not describe :cost or :latency as measured optimization until a release provides the corresponding metrics-backed recommender.
Use routing.only, routing.ignore, or provider priority when the order must be explicit today.
Fallback chains
A virtual model selects an ordered chain of endpoints. With strategy: priority, requests try endpoints in YAML order. BitRouter advances after retryable upstream failures: 5xx, 408, 429, transport or timeout failures, invalid upstream responses, and exhausted provider credit. Other client-side 4xx errors fail immediately.
strategy: cascade allows selection preferences to reorder or filter interchangeable endpoints. Current cost and latency sorts still use deterministic ordering. Define the chain in Model routes.
Presets
A preset combines model substitution, prompt defaults, parameters, routing-policy binding, and candidate filters behind a name such as @fast. Request fields win over preset defaults.
bitrouter/auto is the public spelling of the auto preset and requires a routing-policy binding. Its walkthrough covers sending traffic, inspecting the settled route, and publishing reviewed policy changes. See preset configuration to author ordinary reusable defaults.
Variants
A known variant changes candidate preferences when appended to a model or preset, such as coding:private or @fast:primary. An unknown suffix remains part of the selector.
Variants do not grant access, bypass guardrails, or change virtual-key policy. Define filters in variant configuration.
Protocol compatibility
A model route can receive one API shape and call an upstream provider that speaks another. BitRouter handles that boundary in four steps:
- Normalize the inbound request into a canonical representation.
- Derive requirements such as tool calling or structured outputs.
- Remove model/provider routes that explicitly lack a required capability.
- Render the selected route in its outbound provider protocol.
Protocol translation and model selection are related but separate: translation preserves the caller's intent, while capability filtering determines which routes are eligible to receive it.
Structured outputs across protocols
Structured output is a request-time constraint, not a global router setting. Supply a JSON Schema in the client's native request shape:
| Inbound API | Schema field |
|---|---|
| OpenAI Chat Completions | response_format.json_schema |
| OpenAI Responses | text.format |
| Anthropic Messages | output_config.format |
| Google Generate Content | generationConfig.responseSchema |
BitRouter promotes these fields into one canonical response-format constraint, then renders the corresponding outbound field after model resolution. The same request can therefore resolve to a Messages or Generate Content upstream without the caller rewriting the schema field.
curl http://127.0.0.1:4356/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "openai:gpt-5",
"messages": [{"role": "user", "content": "Return the issue priority."}],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "issue_priority",
"strict": true,
"schema": {
"type": "object",
"properties": {
"priority": {"type": "string", "enum": ["low", "medium", "high"]}
},
"required": ["priority"],
"additionalProperties": false
}
}
}
}'There is no router-wide schema or enable switch. Presets can supply ordinary request defaults, but the response constraint belongs to each request.
Declare custom capabilities
Explicit capability declarations must include every capability required by the request. The public registry provides declarations for built-in routes; private endpoints need verified declarations in Providers.
Compatibility limits
BitRouter preserves and translates the constraint across supported wire protocols. The upstream model and provider remain responsible for producing schema-conforming output.
JSON Schema support differs by upstream. Use the subset accepted by every provider in a fallback chain, and test the exact models you deploy. If the selected outbound protocol cannot represent the response format, BitRouter fails the request instead of silently dropping the schema.
| Canonical field | Chat Completions | Responses | Messages | Generate Content |
|---|---|---|---|---|
| Name | json_schema.name | text.format.name | Not represented | Not represented |
| Description | json_schema.description | text.format.description | Not represented | Not represented |
| Strict | json_schema.strict | text.format.strict | Provider behavior | Provider behavior |
| Schema | json_schema.schema | text.format.schema | format.schema | responseSchema |
Fields a destination protocol cannot represent are not invented. Keep portable behavior in the schema itself.
Inspect and verify
bro config validate -c bitrouter.yaml
bro models --provider openai
bro route coding -c bitrouter.yaml
bro route @fast:primary -c bitrouter.yamlbro route uses the running daemon when available and otherwise resolves from the selected policy file. It is the authoritative way to review the candidate chain before sending traffic.
Model routes
Author virtual models, presets, variants, and fallback chains.
Configuration
Understand how model settings fit into the complete desired-state contract.
Supported Models
Browse the public model catalog and current hosted pricing.
Providers
Connect credentials, private endpoints, and custom model declarations.
API reference
Use the request shape for your chosen inbound protocol.
How is this guide?