Pi
Add RouteMux to Pi's models.json — it can speak all four of our protocol families.
Pi keeps providers in ~/.pi/agent/models.json, and each provider declares which wire
protocol it speaks. That makes it one of the few clients that can reach every RouteMux
protocol family from one config file.
Configure
{
"providers": {
"routemux": {
"name": "routemux",
"baseUrl": "https://api.routemux.com/v1",
"api": "openai-responses",
"apiKey": "sk-...",
"models": [
{
"id": "openai/gpt-5.5",
"name": "GPT-5.5",
"reasoning": true,
"input": ["text", "image"],
"contextWindow": 1000000,
"maxTokens": 128000
}
]
}
}
}Run it with the provider and a fully-qualified model:
pi --provider routemux --model routemux/openai/gpt-5.5 "hello"The api field decides the base URL
api takes one of four values, and each one implies a different base URL, because Pi bundles
a different client for each:
api | RouteMux baseUrl | Lands on |
|---|---|---|
openai-completions | https://api.routemux.com/v1 | /v1/chat/completions |
openai-responses | https://api.routemux.com/v1 | /v1/responses |
anthropic-messages | https://api.routemux.com — bare origin | /v1/messages |
google-generative-ai | https://api.routemux.com/vertex-ai | Vertex operations |
Why anthropic-messages drops the /v1
Pi bundles the official Anthropic SDK, whose base URL is the bare origin and which appends
/v1/messages itself. Other agents that speak the same protocol do the opposite — OpenCode
uses the Vercel AI SDK, which appends only /messages and therefore needs the /v1. Same
protocol, opposite field conventions. See the compatibility matrix.
Claude models are only served on anthropic-messages; Grok models are not served on it at
all. Use one provider block per protocol if you want both.
Model entries
id must be exactly what GET /v1/models returns. contextWindow and maxTokens drive
Pi's own context accounting — wrong numbers produce wrong warnings, not just cosmetic ones.
reasoning and input describe the model's capabilities and belong on the model page.
Compatibility switches worth knowing
Pi sends a few things by default that a strict upstream can reject. If a provider rejects requests that work elsewhere, these are the knobs to look at:
- per-tool eager input streaming, which adds a field inside each tool definition
- a session-affinity header when caching is enabled
- long cache retention, which assumes a one-hour cache TTL is accepted
RouteMux forwards unknown anthropic-beta headers untouched and sanitises only the
parameters an upstream would hard-reject, so the usual symptom here is a clean upstream
error rather than a silent change in behaviour.
Troubleshooting
| Symptom | Cause |
|---|---|
| RouteMux missing from the model picker | A provider with no apiKey configured is hidden. This is almost never a URL problem. |
| 404 on every request | baseUrl has /v1 where the protocol wants a bare origin, or the reverse. See the table above. |
400 MODEL_PROTOCOL_UNSUPPORTED | The model is not served on the protocol this provider declares — e.g. a Claude id under openai-completions. |
| Model not found | id does not match GET /v1/models exactly. |
422 BILLING_INSUFFICIENT_CREDITS | Wallet lacks credit. Failed requests are not billed. |