# OpenCode and Kilo Code With Any OpenAI-Compatible Provider: Config Files That Work, and the Context Limit Trap

> Source: <https://dev.to/amankumar_apiclaw/opencode-and-kilo-code-with-any-openai-compatible-provider-config-files-that-work-and-the-context-4l1g>
> Published: 2026-10-09 04:02:40+00:00

OpenCode and Kilo Code both let you add your own OpenAI-compatible provider, and both configs look simple. The part that bit me wasn't the URL or the key. It was a missing `limit` block that made long sessions fall over an hour in, with no obvious cause.

Here are the configs I use and the mistakes I made getting there. My examples point at [APIClaw](https://apiclaw.biz), an OpenAI-compatible gateway I build, so weigh that accordingly. Swap in any provider's base URL and model IDs.

`/v1` (for example `https://apiclaw.biz/v1`). Don't add `/chat/completions`; the client adds the path.

```
export APICLAW_API_KEY="sk-your-key"
```

OpenCode's provider docs say any OpenAI-compatible API works through the `@ai-sdk/openai-compatible` package. Put this in `~/.config/opencode/opencode.json` (a project-level `opencode.json` also works):

```
{
  "$schema": "https://opencode.ai/config.json",
  "model": "apiclaw/YOUR_MODEL_ID",
  "provider": {
    "apiclaw": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "APIClaw",
      "options": {
        "baseURL": "https://apiclaw.biz/v1",
        "apiKey": "{env:APICLAW_API_KEY}"
      },
      "models": {
        "YOUR_MODEL_ID": {
          "name": "YOUR_MODEL_ID",
          "limit": { "context": 200000, "output": 16384 }
        }
      }
    }
  }
}
```

How the pieces connect:

`apiclaw` under `provider` is a provider ID you choose. The top-level `model` is that ID, a slash, then the model key: `apiclaw/YOUR_MODEL_ID`.` models` must match the ID the server returns from `GET /v1/models`. OpenCode's docs spell out the same rule in their local-server example.`{env:APICLAW_API_KEY}` reads the variable at runtime.
If you'd rather not use an environment variable, run `opencode auth login` (or `/connect` inside OpenCode), choose **Other**, and enter the same provider ID, `apiclaw`. That stores the key, but it doesn't ask for a base URL or models, so you still need the `opencode.json` block. The provider ID you type there has to match the key under `provider` exactly.

Verify with `/models`. Your model should be listed under the provider name. Then send a one-line prompt and check the provider's request log.

Kilo Code has two ways in.

**VS Code extension:** Settings, then the Providers tab, then **Custom provider** at the bottom. Give it a unique provider ID, choose **OpenAI Compatible** as the provider API, paste the `/v1` base URL and your key, then pick a model from the fetched list or paste the exact ID.

**Kilo CLI:** the provider block goes in the **global** `~/.config/kilo/kilo.jsonc`:

```
{
  "$schema": "https://app.kilo.ai/config.json",
  "model": "openai-compatible/YOUR_MODEL_ID",
  "provider": {
    "openai-compatible": {
      "options": {
        "baseURL": "https://apiclaw.biz/v1",
        "apiKey": "{env:APICLAW_API_KEY}"
      },
      "models": {
        "YOUR_MODEL_ID": {
          "name": "YOUR_MODEL_ID",
          "tool_call": true,
          "limit": { "context": 200000, "output": 16384 }
        }
      }
    }
  }
}
```

The global file matters. In my setup, `{env:...}` only resolved from the global config; the same block in a project file silently failed to authenticate. If Kilo says your key is invalid and curl says it's fine, check which file the block is in. `kilo models` confirms whether the provider loaded.

Both tools know the context window for models in their built-in catalogs. A custom provider's model isn't in that catalog, so the client only knows what you tell it in `limit`.

Leave `limit` out and the client doesn't know the context size; in Kilo a custom model with no limit resolves to zero. Compaction (the step where the agent summarizes old turns to make room) never triggers, the conversation keeps growing, and eventually the provider rejects a request for being too long. It looks like a random failure an hour into a session, and it has nothing to do with the provider being flaky.

Set `context` to the model's real window and `output` to its real max output tokens, from the vendor's model page. Setting them a bit lower than the real numbers is fine and leaves headroom. Setting them higher than the real numbers brings the same failure back.

**Invalid API key / 401.** Key pasted with a trailing space, key inactive, or (Kilo) the block is in a project file where `{env:...}` didn't resolve.

**Model not found / 404.** The model key isn't the exact server ID, or the base URL is missing `/v1` or has `/chat/completions` on the end.

**The model appears but tool calls are ignored.** The model doesn't support function calling well, or (Kilo) `tool_call` isn't set to `true` on the custom model entry. Try a model known for tool use before blaming the provider.

**Long sessions die with a context-length error.** Missing or inflated `limit`. See above.

**You need the Responses API.** For OpenCode, switch the `npm` package to `@ai-sdk/openai`; `@ai-sdk/openai-compatible` speaks Chat Completions. Only do this if your provider serves `/v1/responses`.

`{env:NAME}`.` providerid/modelkey`.` limit.context` and `limit.output` set to the model's real numbers.`~/.config/kilo/kilo.jsonc`.`/models` (OpenCode) or `kilo models` (Kilo) shows the model, and a test prompt shows up in the provider's log.
OpenCode's providers page at opencode.ai/docs and Kilo's own docs are the source of truth if the config schema changes.
