[Blog](https://excessionlabs.ai/blog/) · 4 November 2026 · [Excession Labs](https://excessionlabs.ai/about/)

# DeepSeek in OpenCode: Excession provider setup

Source page: https://excessionlabs.ai/blog/deepseek-opencode/

Add Excession as an OpenAI-compatible provider in OpenCode and select DeepSeek V4.1 Flash. This setup passed a configuration and streaming test with the real OpenCode client, run against a localhost fixture.

## Prepare OpenCode and your key

Install OpenCode using its [official instructions](https://opencode.ai/docs/). Create an Excession API key in the [dashboard](https://excessionlabs.ai/app), load it into `EXCESSION_API_KEY` through your usual secret manager, and check your available funds.

## Add the custom provider

Create `opencode.json` at your project root, or merge these fields into an existing file. OpenCode's [configuration documentation](https://opencode.ai/docs/config/) explains file precedence and environment substitution. The environment reference keeps the key value out of JSON.

```
{
  "$schema": "https://opencode.ai/config.json",
  "model": "excession/deepseek/deepseek-v4.1-flash-1017",
  "small_model": "excession/deepseek/deepseek-v4.1-flash-1017",
  "enabled_providers": [
    "excession"
  ],
  "permission": {
    "*": "deny"
  },
  "provider": {
    "excession": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Excession",
      "options": {
        "baseURL": "https://api.excessionlabs.ai/v1",
        "apiKey": "{env:EXCESSION_API_KEY}"
      },
      "models": {
        "deepseek/deepseek-v4.1-flash-1017": {
          "name": "DeepSeek V4.1 Flash"
        }
      }
    }
  }
}
```

The custom provider ID is `excession`. OpenCode prefixes it to the API model ID: the selection string `excession/deepseek/deepseek-v4.1-flash-1017` becomes `deepseek/deepseek-v4.1-flash-1017` on the wire. The example pins both the main and small models. `enabled_providers` restricts this example to Excession; merge it carefully if you use other providers.

Use `@ai-sdk/openai-compatible` and a base URL ending in `/v1`. That selects `POST /v1/chat/completions`, as described in OpenCode's [custom-provider documentation](https://opencode.ai/docs/providers/#custom-provider). Other adapters may select a different API format.

The example denies all tool permissions for the first text-only check, so OpenCode can exchange messages but cannot perform coding actions. Afterwards, replace the deny rule with permissions that suit your project, using the [OpenCode permission documentation](https://opencode.ai/docs/permissions/). Our test did not cover tool execution.

## Run a first text request

```
: "${EXCESSION_API_KEY:?Load your Excession API key first}"
opencode run --pure \
  --model "excession/deepseek/deepseek-v4.1-flash-1017" \
  --title "DeepSeek connection check" \
  "Reply with READY."
```

This [non-interactive run](https://opencode.ai/docs/cli/#run) selects the model explicitly and skips external plugins. A successful live run should print a short answer. Unlike our mock test, it uses metered inference on your account.

For interactive use, start `opencode` in the same project and terminal. Use `/models` to select the Excession entry. Try a small coding task in a disposable directory before you rely on tool calls or edits.

## Troubleshoot the provider

- **Model not found:** keep the provider prefix in OpenCode's selection string and the API ID inside `models`. Confirm the project configuration is loaded.

- **401 or missing credential:** confirm `EXCESSION_API_KEY` is available to the launching process. An unset environment reference becomes an empty value.

- **404 or unexpected response:** check the adapter and `https://api.excessionlabs.ai/v1` base URL.

- **Configuration seems unchanged:** check merged global, project and environment configuration. An explicit `OPENCODE_CONFIG` path helps isolate a problem.

- **Tools are denied:** review the example's `permission: {"*": "deny"}` rule when moving beyond the text check.

- **Funds, limits or empty output:** inspect the API error, dashboard usage and completion reason. A completed stream does not guarantee a complete generated answer.

## What we tested

On 4 November 2026 we ran the actual Claude Code 2.1.318 and OpenCode 1.19.5 clients against an isolated localhost fixture with fake credentials. Each sent the exact model ID, a Bearer credential and a streaming request to its expected endpoint. Both displayed `LOCAL_FIXTURE_OK` from the fixture and exited successfully.

**This was a mock client integration test with no live DeepSeek inference.** The fixture supplied the answer, and no model generated it. The test validates configuration, request routing and text-stream parsing. It does not establish production availability, model quality, billing, long conversations, or tool-call and file-edit compatibility.

Inspect the [recorded request metadata and results](https://excessionlabs.ai/blog/evidence/deepseek-clients-2026-11-04.json) or [download the local validation script](https://excessionlabs.ai/blog/evidence/deepseek-clients-2026-11-04.py). Run the script with `--claude /path/to/claude --opencode /path/to/opencode`, using official client executables. It starts a loopback endpoint, uses fake keys and temporary client configuration, and does not read a real API key. Package setup and client startup may contact public package or model metadata services.

## Continue reading

- [DeepSeek API: Python, streaming and tool calls](https://excessionlabs.ai/blog/deepseek-api-guide/)

- [Use DeepSeek in Claude Code](https://excessionlabs.ai/blog/deepseek-claude-code/)

- [Current API models and prices](https://excessionlabs.ai/api)
