OpenCode

OpenCode is a terminal coding assistant. It talks to any OpenAI-compatible endpoint through a custom provider entry, which is what LowRouter exposes.

Verified against OpenCode 1.18.32. The config below is re-run against that release every week; if you are on a much newer version and it stops working, check the OpenCode provider docs for a schema change and let us know.

Configure

OpenCode reads ~/.config/opencode/opencode.json (or an opencode.json in the project directory; the two are merged). Declare LowRouter as a provider, list the models you want to use, and set the default model:

JSON
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "lowrouter": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "LowRouter",
      "options": {
        "baseURL": "https://api.lowrouter.ai/v1",
        "apiKey": "sk-lr-..."
      },
      "models": {
        "auto/mistralai/mistral-large-2512": {
          "name": "Mistral Large (auto-routed)",
          "tool_call": true,
          "limit": { "context": 256000, "output": 16384 }
        }
      }
    }
  },
  "model": "lowrouter/auto/mistralai/mistral-large-2512"
}

Restart OpenCode after editing the file. Four things in this block are easy to get wrong:

  • Models must be declared. OpenCode does not discover models from GET /v1/models; a model that is not listed under models does not exist as far as OpenCode is concerned. Each key is a LowRouter model ID, exactly as the model browser shows it. tool_call: true tells OpenCode the model can drive its file and shell tools; check the function-calling tag on the model’s page, or filter the model browser to models that have it, before setting it.
  • Declare limit. OpenCode asks for 32,000 output tokens unless the model entry says otherwise, and a model that caps lower rejects the request outright (max_tokens is too large: 32000. This model supports at most 16384… on gpt-4o-mini, for instance). Copy context and the max output from the model’s page; when the page shows no max output, 16384 is a safe ceiling for the models listed today.
  • The model is addressed as lowrouter/<model id>. The first segment is the provider key you chose above (lowrouter), the rest is the LowRouter ID. That applies to the model field, to /model inside the TUI and to opencode run -m ....
  • baseURL ends in /v1, with no trailing slash. OpenCode appends /chat/completions itself. This is the opposite of Goose, whose host must not include /v1. Each tool decides for itself how much of the path it adds.

To check the wiring without opening the TUI:

Bash
opencode run -m lowrouter/auto/mistralai/mistral-large-2512 "Reply with the single word pong"

Picking a model

Any model on the model browser is routable. Add it under models first, then pick it with /model in the TUI. For coding tasks, name a capable model and let LowRouter pick where it runs, as with auto/mistralai/mistral-large-2512. You still choose the model:

  • For long contexts: a model with ≥128K context window. The model browser tags context length per model.
  • For latency-sensitive iteration: an *-mini or *-haiku-* variant.
  • For careful reasoning: a top-tier reasoning model.
  • For agentic work: a model whose page carries the function-calling tag (filtered list). Without it OpenCode’s tools cannot be invoked.
  • Use a dedicated key. OpenCode is interactive and it’s easy to lose track of how many tokens you spent in an afternoon; a key of its own shows that on the Activity page.
  • Disable shell-execution tools by default. OpenCode supports letting the model run shell commands; turn that off until you’ve reviewed the prompts the agent sends. Enable it per-session for the workflow that needs it.
  • Keep streaming on. It is the default in OpenCode.

Troubleshooting

  • Unexpected server error… ref err_… on the first prompt, and nothing in your Activity: the request never left your machine. This is what a legacy config looks like: older guides (including an earlier version of this page) used a providers / defaultModel block that OpenCode 1.18 silently drops, leaving it with no provider at all. Replace it with the block above. If the request is not in Activity, LowRouter never saw it.
  • Model “not found”: it is not declared under models. There is no autocomplete from the gateway; add the ID and restart.
  • 404 on every request: baseURL is missing /v1, or has a trailing slash.
  • 401: confirm the key under options.apiKey.

If tool calls are auto-rejected

OpenCode asks before each file read or edit, and in a non-interactive run (opencode run) there is nobody to ask, so it rejects and reports the tool call as failed. That is OpenCode’s sandbox, not a routing problem. Grant the permissions in the same config file:

JSON
{
  "permission": { "read": "allow", "edit": "allow", "bash": "allow" }
}

Verified with the real CLI against LowRouter, agentic loop included: it reads a file, edits it, and the change lands on disk. Works with both an explicit {provider}/{creator}/{model} id and an auto/ id.