Configure OpenCode's Router One provider and model IDs
OpenCode is the open-source terminal coding agent from Anomaly, and it takes custom model providers straight from opencode.json. One provider block pointing at Router One's OpenAI-compatible endpoint puts GPT, Claude, Gemini, and Grok family models in its model picker behind a single key — and because agent sessions burn tokens unattended, every call lands in a per-request cost trace on the gateway, with a maxSpend cap on the key as the hard stop.
Configure OpenCode to use the Router One base URL
Add an entry under provider in opencode.json (project-level, or ~/.config/opencode/opencode.json globally) with npm set to @ai-sdk/openai-compatible, options.baseURL on the gateway, and one models entry per catalog model you want in the picker. The key can be read from an environment variable with the {env:VAR} syntax so it never sits in the file. Select a model as provider-id/model-id — router-one/<model-id> here — from the /models command in the TUI, or pin it in the top-level model field:
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"router-one": {
"npm": "@ai-sdk/openai-compatible",
"name": "Router One",
"options": {
"baseURL": "https://api.router.one/v1",
"apiKey": "{env:ROUTER_ONE_API_KEY}"
},
"models": {
"<model-id-from-/models>": {
"name": "<label shown in the picker>"
}
}
}
},
"model": "router-one/<model-id-from-/models>"
}Which model ID should OpenCode send?
Copy the exact model ID from /models, preserving case, hyphens, and version suffixes; do not substitute a display name. Open its detail page and match the supported API endpoints, context window, and capabilities such as tool calling to the provider and features selected in OpenCode. A catalog listing does not mean the client can use every feature of that model. Give each tool a dedicated API key with a maxSpend cap.
Which API protocol is OpenCode using?
OpenAI-compatible describes an interface format; it does not make Chat Completions (/v1/chat/completions), Responses (/v1/responses), and Anthropic Messages (/v1/messages) interchangeable. Check the installed client version, provider configuration, and actual request path against the model detail page and API compatibility fact sheet. A successful plain-text chat does not establish support for hosted tools, conversation state, or file-editing features.
Verify the OpenCode call in your request trace
Send a simple text request from OpenCode, then match its trace in Dashboard → Logs by time, model, and request_id: tokens, cost, latency, and status. Next, test streaming, tool calls, and multi-turn history separately. For failures, retain the actual request path, full error message, and request_id. If there is no matching log, check client configuration and connectivity before attributing the error to the gateway or upstream.
FAQ
Why does OpenCode report the model as unknown or fail to authenticate?
Check three things in order: the provider id in the model string must match the key you used under provider (router-one/<model-id>), every model must be listed in that provider's models map with the exact ID from /models, and options.apiKey must resolve — with {env:ROUTER_ONE_API_KEY} the variable has to be exported in the shell that launches opencode, because an unset variable is replaced with an empty string rather than raising an error.
Can OpenCode use Router One's Anthropic-compatible endpoint for Claude models?
Yes, optionally. The OpenAI-compatible block above already serves the Claude family; if you want the native Messages API for those models, add a second provider with npm set to @ai-sdk/anthropic and options.baseURL set to https://api.router.one/v1 — the gateway serves Claude models natively on /v1/messages and accepts the same key in the x-api-key header that package sends. Keep the two providers under different ids so their model lists stay separate.
Which models can OpenCode use through the gateway?
Choose a current catalog model that supports both the endpoint and the features OpenCode uses. Check /models and the model detail page for the exact ID, current rates, and capabilities; a family name such as GPT or Claude is not a compatibility guarantee. Seeing a model in the picker confirms discovery, so verify an actual request too.
Models are listed, but requests fail with 400 or 404. What should I check?
Record the actual request path and error message, then check the exact model ID. A 400 can indicate invalid parameters, unsupported tools, or a model/endpoint mismatch; a 404 can indicate an incorrect path or missing resource, so it does not by itself establish that a model was retired. If the error says must be called via, use the named endpoint or select a model supported on the current endpoint. Do not add or remove /v1 or /chat/completions across all clients indiscriminately.
Does this work from Mainland China?
Yes. The gateway is reachable from Mainland China without a VPN, and the configuration is identical to the global setup.
How do I debug a 401/402/403/429?
Match the request and error message in Dashboard → Logs. For 401, check whether the key was sent and is valid; for 402, check wallet balance and maxSpend; for 403, check key permissions and access restrictions. For 429, distinguish request/token limits from upstream throttling using the error details. Keep the request_id and follow the error-codes reference.