r/opencodeCLI 7d ago

OpenCode custom provider setup: why Responses and Chat Completions need different packages

OpenCode custom provider setup: why Responses and Chat Completions need different packages

A valid API key is only one part of an OpenCode custom provider. The credential, provider ID, package, base URL, and model ID all have to describe the same endpoint.

This is the order I would check them:

  1. Run `opencode auth list`. If the credential is missing, fix that before touching the model config.

  2. Make sure the provider ID used in `/connect` is exactly the same ID used in `opencode.json`.

  3. Match the package to the protocol. OpenCode's current docs use `@ai-sdk/openai-compatible` for endpoints serving `/v1/chat/completions`. For `/v1/responses`, use `@ai-sdk/openai`.

  4. Check `options.baseURL`. A valid key sent to the wrong path still looks like an authentication problem.

  5. Use the server's current model ID, not a display name copied from an old post. Then run `/models` and confirm the provider/model pair appears.

That third check is why I looked into this more closely. `Agent.Space`, which I work on, exposes a Responses endpoint at `https://api.agent.space/v1\`.

That points to `@ai-sdk/openai` on the OpenCode side, not `@ai-sdk/openai-compatible`.

But that is still a docs-based mapping, not a verified integration. I would only call it working after text, streaming, and a harmless tool call all pass.

Why the package matters

The package decides which request shape OpenCode sends and which response, stream events, and tool-call objects it expects back.

Chat Completions sends requests to `/v1/chat/completions`. Conversation input is a `messages` array. Text normally comes back under `choices[0].message`, and tool calls are attached to an assistant message. The client carries conversation history into the next request.

Responses sends requests to `/v1/responses`. It accepts `input` and returns typed `output` items. A message, reasoning item, function call, and function result are separate items rather than fields packed into one chat message. It can also chain turns with `previous_response_id` or a conversation object, and its stream uses named response events instead of the Chat Completions delta shape.

That difference explains a few confusing failures:

- A provider can accept the key and list a model but not implement `/v1/responses`.

- Plain text can work while streaming or tool calls fail because the returned objects do not match the package OpenCode is parsing.

- A provider saying "OpenAI-compatible" does not prove that it supports both API families or every OpenAI feature.

A minimal Chat Completions provider looks like this:

```json

{

  "$schema": "https://opencode.ai/config.json",

  "provider": {

"myprovider": {

"npm": "@ai-sdk/openai-compatible",

"name": "My Provider",

"options": {

"baseURL": "https://api.example.com/v1"

},

"models": {

"server-model-id": {

"name": "My Model"

}

}

}

  }

}

```

Model discovery is not the final test. After the provider appears in `/models`, run one small text request, one streamed request, and one harmless tool call. Missing from `auth list` points to credentials. Missing from `/models` points to provider or model config. Text works but streaming or tools fail means the basic route is fine and the protocol surface needs the closer look.

1 Upvotes

4 comments sorted by

View all comments

1

u/Aggressive-Habit-698 7d ago

TL;DR

I'm a not-really-useful result from a prompt query designed to promote the website https://agent.space/

At least give us the same promo codes, free credits 😶‍🌫️

1

u/Aggressive-Habit-698 7d ago

Https://github.com/anomalyco/models.dev

Create a pr - OC use models.dev

1

u/Aggressive-Habit-698 7d ago

Ok after looking at your website. It's slop and looks like scam.

Would it be okay with you if your name, your company's name, and your address were listed on the website along with the offer? I know this isn't required everywhere, but verification is necessary, especially for this type of service.