Model Gateways
Route Agent Swarm harnesses through LiteLLM, Microsoft Foundry, Bedrock, Vertex, OpenRouter, OrcaRouter, or any OpenAI-compatible gateway
Agent Swarm's harness and its model gateway are separate choices. HARNESS_PROVIDER selects the coding agent that runs the task. Gateway settings tell that harness where to send model requests.
This page covers the stock worker image. A gateway that an upstream CLI supports is not necessarily supported by Agent Swarm until its credentials and configuration reach that CLI inside the worker.
Support matrix
| Gateway | Claude Code | Codex | OpenCode | pi-mono | Devin | Claude Managed |
|---|---|---|---|---|---|---|
| OpenRouter | Supported with environment variables (below) | Custom image/config and a swarm-recognized Codex credential required | Supported with environment variables | Supported with environment variables | Not configurable | Not configurable |
| Ramp Router | Accepted by the credential gate; not tested end to end | Custom image/config and a swarm-recognized Codex credential required | Not yet supported: Ramp's provider plugin is not in the image | Not yet supported: Ramp's provider plugin is not in the image | Not configurable | Not configurable |
| OrcaRouter | Not supported by OPENROUTER_BASE_URL | Not supported by OPENROUTER_BASE_URL | Supported | Supported | Not configurable | Not configurable |
| OpenAI-compatible gateway | Not supported by OPENROUTER_BASE_URL | Not supported by OPENROUTER_BASE_URL | Supported | Supported | Not configurable | Not configurable |
Supported means the stock image works with environment or swarm-config values. “Custom image” means the upstream harness can use the gateway, but the stock Agent Swarm image does not install the required provider configuration or plugin.
There is no per-vendor gateway adapter in Agent Swarm, and adding one is not required. OpenCode and pi-mono reach every gateway through the same seam: OPENROUTER_BASE_URL redirects the built-in OpenRouter provider at an arbitrary chat-completions endpoint. OrcaRouter is documented below as a worked example of that generic path, not as a special case.
OPENROUTER_BASE_URL is not a universal OpenAI base-URL switch. It only
redirects the swarm's existing OpenRouter consumers. The target must provide
the OpenRouter-compatible model-list and chat-completions routes described
below. It does not make Ramp Router work with OpenCode or pi-mono.
For the standard harness credentials, model defaults, and Docker examples, see Harness Configuration. For the contributor-facing adapter contract, see Harness Providers.
OpenRouter
OpenCode and pi-mono have first-class OpenRouter support in the stock image. Both use the same key and the same model slug after the harness-specific prefix.
OpenCode
# .env.docker
HARNESS_PROVIDER=opencode
OPENROUTER_API_KEY=sk-or-...
MODEL_OVERRIDE=openrouter/qwen/qwen3-coder-flash
API_KEY=your-swarm-api-key
MCP_BASE_URL=http://host.docker.internal:3013
AGENT_ID=your-worker-uuid- Base URL:
https://openrouter.ai/api/v1(built in) - Credential:
OPENROUTER_API_KEY - Model string:
openrouter/<openrouter-model-id>. For example, OpenRouter modelqwen/qwen3-coder-flashbecomesopenrouter/qwen/qwen3-coder-flash. - Config file: none. The adapter writes a per-task OpenCode config and injects the swarm plugin automatically.
Choose another ID from the OpenRouter model catalog, keeping the openrouter/ harness prefix.
pi-mono
# .env.docker
HARNESS_PROVIDER=pi
OPENROUTER_API_KEY=sk-or-...
MODEL_OVERRIDE=openrouter/moonshotai/kimi-k2.5
API_KEY=your-swarm-api-key
MCP_BASE_URL=http://host.docker.internal:3013
AGENT_ID=your-worker-uuid- Base URL:
https://openrouter.ai/api/v1(built in) - Credential:
OPENROUTER_API_KEY - Model string:
openrouter/<openrouter-model-id> - Config file: none for direct OpenRouter use. The adapter supplies the key through pi-mono's per-session
ModelRuntime.
Do not add CLAUDE_CODE_OAUTH_TOKEN to a pi worker. Keep only credentials used by the selected pi provider.
Claude Code
OpenRouter's Anthropic-compatible endpoint works as a Claude Code gateway. See Claude Code through a gateway or cloud provider for the OpenRouter snippet.
Codex: upstream-compatible, not in the stock image
OpenRouter's Codex setup uses the user-level ~/.codex/config.toml:
model = "openai/gpt-5.3-codex"
model_provider = "openrouter"
[model_providers.openrouter]
name = "OpenRouter"
base_url = "https://openrouter.ai/api/v1"
env_key = "OPENROUTER_API_KEY"
wire_api = "responses"The stock worker image bakes its own Codex config with the native provider and model, and Agent Swarm has no environment variable that adds this provider block. Its credential gate also does not recognize OPENROUTER_API_KEY; it waits for OPENAI_API_KEY, Codex OAuth, or an existing ~/.codex/auth.json before starting work.
An experimental derivative image therefore needs both the complete provider config and a credential state the swarm accepts, in addition to OPENROUTER_API_KEY in the worker process environment. Merely setting OPENROUTER_API_KEY, mounting the TOML block, or setting OPENROUTER_BASE_URL is not sufficient in the stock deployment. Do not disable the credential gate to hide this mismatch.
See OpenRouter's Codex CLI setup for the upstream configuration. This path has not been smoke-tested with the stock Agent Swarm worker.
Claude Code through a gateway or cloud provider
The claude harness passes its environment straight to Claude Code, so any endpoint Claude Code supports works without an Anthropic key. The worker derives one route from the environment, in this order:
CLAUDE_CODE_USE_FOUNDRY(Microsoft Foundry)CLAUDE_CODE_USE_BEDROCK(Amazon Bedrock)CLAUDE_CODE_USE_VERTEX(Google Vertex AI)ANTHROPIC_BASE_URLpointing anywhere exceptapi.anthropic.com(a gateway; it needsANTHROPIC_AUTH_TOKENorANTHROPIC_API_KEY)CLAUDE_CODE_OAUTH_TOKEN(Claude subscription)ANTHROPIC_API_KEY(Anthropic API)
The credential gate checks only the variables that route needs, so the worker leaves waiting_for_credentials as soon as they are set. On a gateway route, the live check calls the gateway's own GET /v1/models and never sends the gateway key to api.anthropic.com. Foundry, Bedrock, and Vertex have no free credential check, so the dashboard shows them as configured until a task runs.
On any route other than the Claude subscription, the worker blanks CLAUDE_CODE_OAUTH_TOKEN in Claude Code's environment, so a subscription token set for other agents never reaches a gateway or cloud endpoint.
Choosing models
Claude Code runs the swarm's model aliases (opus, sonnet, haiku). Map them to the names your endpoint serves:
ANTHROPIC_DEFAULT_OPUS_MODEL=<endpoint model id>
ANTHROPIC_DEFAULT_SONNET_MODEL=<endpoint model id>
ANTHROPIC_DEFAULT_HAIKU_MODEL=<endpoint model id> # also used for background callsTo pin one model for an agent, set MODEL_OVERRIDE to the endpoint's model id instead. An id with a non-Anthropic provider prefix (for example z-ai/glm-4.6) is treated as another harness's model and ignored; use the ANTHROPIC_DEFAULT_*_MODEL variables for those.
LiteLLM
HARNESS_PROVIDER=claude
ANTHROPIC_BASE_URL=http://litellm:4000
ANTHROPIC_AUTH_TOKEN=sk-litellm-... # or ANTHROPIC_API_KEY, sent as x-api-key
ANTHROPIC_DEFAULT_OPUS_MODEL=claude-opus
ANTHROPIC_DEFAULT_SONNET_MODEL=claude-sonnet
ANTHROPIC_DEFAULT_HAIKU_MODEL=claude-haikuThe base URL has no /v1; Claude Code appends it. The model names are model_name aliases from your LiteLLM config, so they can point at non-Anthropic models.
OpenRouter
HARNESS_PROVIDER=claude
ANTHROPIC_BASE_URL=https://openrouter.ai/api
ANTHROPIC_AUTH_TOKEN=sk-or-...
ANTHROPIC_API_KEY=
ANTHROPIC_DEFAULT_SONNET_MODEL=~anthropic/claude-sonnet-latestOpenRouter requires ANTHROPIC_API_KEY to be explicitly empty so it does not compete with the bearer token. See OpenRouter's Claude Code integration guide.
Microsoft Foundry
HARNESS_PROVIDER=claude
CLAUDE_CODE_USE_FOUNDRY=1
ANTHROPIC_FOUNDRY_RESOURCE=my-resource # or ANTHROPIC_FOUNDRY_BASE_URL
ANTHROPIC_FOUNDRY_API_KEY=... # omit to use Entra ID (DefaultAzureCredential)
ANTHROPIC_DEFAULT_OPUS_MODEL=<deployment name>
ANTHROPIC_DEFAULT_SONNET_MODEL=<deployment name>
ANTHROPIC_DEFAULT_HAIKU_MODEL=<deployment name>Amazon Bedrock
HARNESS_PROVIDER=claude
CLAUDE_CODE_USE_BEDROCK=1
AWS_REGION=us-east-1 # required; Claude Code does not read the region from ~/.aws/config
AWS_BEARER_TOKEN_BEDROCK=... # or any AWS credential chain source
ANTHROPIC_DEFAULT_SONNET_MODEL=<inference profile id>Google Vertex AI
HARNESS_PROVIDER=claude
CLAUDE_CODE_USE_VERTEX=1
CLOUD_ML_REGION=us-east5
ANTHROPIC_VERTEX_PROJECT_ID=my-project
# Credentials: Application Default Credentials (GOOGLE_APPLICATION_CREDENTIALS or workload identity)CLIProxyAPI and other Anthropic-compatible proxies
Any proxy that speaks the Anthropic Messages API is a gateway: set ANTHROPIC_BASE_URL and put the key the proxy expects in ANTHROPIC_AUTH_TOKEN. Headers the proxy needs go in ANTHROPIC_CUSTOM_HEADERS (one Name: value per line); the live check sends them too.
Do not put a Claude Pro or Max subscription behind a proxy to share it across users or agents. Anthropic's terms restrict how subscription credentials may be used. A gateway in front of an Anthropic API key, Foundry, Bedrock, or Vertex is the supported path.
A custom ANTHROPIC_BASE_URL requires a gateway key (ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY). With only CLAUDE_CODE_OAUTH_TOKEN set, the worker stays in waiting_for_credentials and names the missing gateway key, because Claude Code would otherwise send the subscription token to that URL. To send subscription traffic through an egress proxy, leave ANTHROPIC_BASE_URL unset and use Claude Code's HTTPS_PROXY setting (network configuration).
OpenAI-compatible gateways
OPENROUTER_BASE_URL redirects the OpenRouter provider used by OpenCode and pi-mono. It also redirects other OpenRouter consumers in the deployment, including model refreshes and internal summarizers. The variable name says OpenRouter, but the target does not have to be openrouter.ai — any gateway meeting the contract below works, and no swarm code path is vendor-specific.
The target must accept OPENROUTER_API_KEY as a bearer credential and provide, at minimum:
GET <base-url>/modelsfor model discoveryPOST <base-url>/chat/completionsfor OpenRouter-compatible inference and swarm summarizers- Model IDs the gateway resolves for the value you select through
MODEL_OVERRIDE
Set the variable on both API and worker processes if every OpenRouter call must use the gateway.
Setting it from the dashboard
OPENROUTER_BASE_URL is on Settings → Configuration under Harness & tools. A saved value is a global swarm_config row and reaches both sides without a container restart:
- API server — the debounced global-config reload re-injects the row over the server process environment, so model refreshes and internal summarizers pick it up within seconds.
- Workers — each worker fetches
GET /api/config/resolvedbefore it starts a task and passes the merged environment into the harness adapter, so the next task on that worker uses the new gateway.
A task already running keeps the gateway it started with. The gateway credential itself stays out of this page: put OPENROUTER_API_KEY on the Secrets/Integrations pages or in the worker environment.
OpenCode through a gateway
HARNESS_PROVIDER=opencode
OPENROUTER_API_KEY=your-gateway-credential
OPENROUTER_BASE_URL=https://gateway.example.com/v1
MODEL_OVERRIDE=openrouter/qwen/qwen3-coder-flashThe adapter writes provider.openrouter.options.baseURL into its per-task OpenCode config. It also mirrors the resolved value into the spawned OpenCode process environment so the bundled summarize plugin uses the same gateway instead of calling openrouter.ai directly.
pi-mono through a gateway
HARNESS_PROVIDER=pi
OPENROUTER_API_KEY=your-gateway-credential
OPENROUTER_BASE_URL=https://gateway.example.com/v1
MODEL_OVERRIDE=openrouter/moonshotai/kimi-k2.5The adapter writes the override to pi-mono's ~/.pi/agent/models.json before its per-session model runtime loads. Clearing the variable reverts that file to whatever it held before the swarm wrote the override.
OPENROUTER_BASE_URL does not affect Claude Code, Codex, Devin, or Claude Managed Agents. Claude Code uses ANTHROPIC_BASE_URL instead (above). It also cannot adapt a Responses-only gateway into the chat-completions shape expected by these OpenRouter-backed paths.
OrcaRouter (api.orcarouter.ai)
OrcaRouter is an OpenAI-compatible gateway, so it needs no new provider, adapter, or code path in Agent Swarm. It is configured exactly like any other gateway in the previous section: point OPENROUTER_BASE_URL at it and use an OrcaRouter key as OPENROUTER_API_KEY.
Its published contract matches the requirements above. Per OrcaRouter's documentation: the base URL is https://api.orcarouter.ai/v1 and must include /v1; authentication is a bearer API key (sk-orca-…); GET /v1/models returns the catalog for the authenticated key; and POST /v1/chat/completions serves OpenAI-compatible Chat Completions. Model IDs are provider-prefixed (openai/, anthropic/, google/, deepseek/, grok/, and others).
OpenCode through OrcaRouter
HARNESS_PROVIDER=opencode
OPENROUTER_API_KEY=sk-orca-...
OPENROUTER_BASE_URL=https://api.orcarouter.ai/v1
MODEL_OVERRIDE=openrouter/anthropic/claude-opus-4.7pi-mono through OrcaRouter
HARNESS_PROVIDER=pi
OPENROUTER_API_KEY=sk-orca-...
OPENROUTER_BASE_URL=https://api.orcarouter.ai/v1
MODEL_OVERRIDE=openrouter/anthropic/claude-opus-4.7Two details differ from OrcaRouter's own OpenCode and pi guides, which configure a dedicated orcarouter provider entry in opencode.json / models.json:
- Keep the
openrouter/harness prefix. Agent Swarm reuses the harness's built-in OpenRouter provider and redirects it, rather than registering a second provider.MODEL_OVERRIDEis thereforeopenrouter/followed by the full OrcaRouter model ID — including that ID's own provider prefix. OrcaRouter's routing alias becomesopenrouter/orcarouter/auto. - Do not hand-edit the harness config files. Both adapters generate their gateway configuration per task from
OPENROUTER_BASE_URL; a manualopencode.jsonor~/.pi/agent/models.jsonprovider block is not the supported path here and the pi-mono adapter actively manages its own override in that file.
These OrcaRouter values are taken from its public documentation
(docs.orcarouter.ai, read 2026-09-08). They have
not been authenticated end to end from an Agent Swarm worker, because no
OrcaRouter key was available during verification. What is verified is the swarm
side: OPENROUTER_BASE_URL reaches both the OpenCode and pi-mono adapters, and
a chat-completions gateway is the shape they expect.
Ramp Router (router.com)
Ramp Router is not supported by the stock Agent Swarm worker image today, except for Claude Code, whose variables form a gateway route. The current Ramp CLI has dedicated integrations for Claude Code, Codex, OpenCode, and Pi; the other three hit a swarm-side gap.
Ramp's public API endpoint documentation names https://api.router.com/v1. Its current CLI instead configures coding agents against https://router-api.ramp.com/v1; the Claude Code integration removes /v1 because Claude Code appends it. Follow the Ramp CLI source and installer for coding-agent configuration rather than substituting router.com as the model API host.
In a custom image that installs Ramp's CLI, the upstream configuration starts with:
RAMP_ROUTER_CONFIGURE_API_KEY='<router-key>' ramp router configureThat command writes client-specific files on a normal workstation. It does not resolve the Agent Swarm gaps in the table below.
No fixed model string is safe to copy into a Router deployment. Router returns the models available to the authenticated key from GET /v1/models, and ramp router configure writes the selected ID in the shape required by each client.
| Harness | Ramp configuration | Agent Swarm gap |
|---|---|---|
| Claude Code | ANTHROPIC_BASE_URL=https://router-api.ramp.com, ANTHROPIC_AUTH_TOKEN=<router-key>, ANTHROPIC_CUSTOM_HEADERS='X-Gateway-Client: claude-code', CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1, and an empty ANTHROPIC_API_KEY | None on the credential side: these variables form a gateway route. Not tested end to end |
| Codex | [model_providers.ramp-router] in ~/.codex/config.toml, base_url = "https://router-api.ramp.com/v1", wire_api = "responses", plus command-based auth and X-Gateway-Client = "codex" | The stock image does not contain this provider block, key file, generated model catalog, or Router hooks; the swarm credential gate also does not recognize the provider's command auth |
| OpenCode | Ramp's bundled local provider plugin in both opencode.json and tui.json; model string ramp-router/<discovered-model-id> | The plugin is bundled inside ramp-cli, is not published as an independently installable npm package, and is not in the worker image |
| pi-mono | Ramp's bundled local provider package, Router auth entry, and ramp-router-config.json; provider ramp-router with a discovered model ID | The package and configuration are not in the worker image, and the swarm adapter has no Ramp provider path |
Do not point OPENROUTER_BASE_URL at Ramp Router. Ramp's OpenCode and Pi integrations use the OpenAI Responses API through dedicated plugins, while the swarm's OpenRouter override also needs chat-completions compatibility.
These Ramp paths were verified from ramp-public/ramp-cli at commit
b71f7f12.
They have not been authenticated end to end from an Agent Swarm worker because
no Router key was available during verification.
Managed harnesses
Devin and Claude Managed Agents execute sessions in their vendors' clouds. Their adapters call vendor-managed session APIs directly and expose no model base-URL override. OPENROUTER_BASE_URL, ANTHROPIC_BASE_URL, and Codex provider files do not redirect them.
If gateway routing is mandatory, choose a supported local harness: Claude Code with an Anthropic-compatible gateway or cloud provider, or OpenCode or pi-mono with OpenRouter or another OpenAI-compatible gateway.
Troubleshooting
The worker is waiting for credentials
The selected harness did not find a credential type it recognizes. Check the support matrix before adding another variable. For Claude Code, the dashboard hint names the route the worker derived and the variable it still needs: ANTHROPIC_AUTH_TOKEN needs ANTHROPIC_BASE_URL next to it, Foundry needs ANTHROPIC_FOUNDRY_RESOURCE, Bedrock needs AWS_REGION, and Vertex needs CLOUD_ML_REGION and ANTHROPIC_VERTEX_PROJECT_ID.
The gateway receives model-list requests but no inference
Confirm the gateway supports POST /chat/completions, not only POST /responses. OPENROUTER_BASE_URL routes more than the harness session itself, so internal summarizers may also call the same base URL.
The model is not found
OpenCode and pi-mono require the openrouter/ harness prefix before the gateway's catalog ID, whichever gateway is behind OPENROUTER_BASE_URL. The prefix selects the harness provider; everything after it is passed through. For example:
OpenRouter ID: qwen/qwen3-coder-flash
MODEL_OVERRIDE: openrouter/qwen/qwen3-coder-flash
OrcaRouter ID: anthropic/claude-opus-4.7
MODEL_OVERRIDE: openrouter/anthropic/claude-opus-4.7Do not strip a gateway ID's own provider prefix to avoid the doubled-looking path — the gateway receives only the part after openrouter/, so removing it sends an ID the gateway does not know.
Ramp model IDs are key-specific. Discover them with Ramp's configuration flow instead of reusing an OpenRouter slug.
Related
- Harness Configuration — standard credentials, model selection, and worker examples
- Harness Providers — adapter architecture and contributor requirements
- Environment Variables — full variable reference
- Codex OAuth — native Codex authentication without a gateway