Adicione um provider personalizado compatível com OpenAI ao OpenCode.

Updated 2026-07-29

O OpenCode lê providers personalizados direto do opencode.json. Declare um bloco provider com o pacote @ai-sdk/openai-compatible, aponte options.baseURL para https://api.apisrouter.com/v1, e cada modelo que você listar se torna selecionável no seletor /models sob uma chave.

Resposta rápida: um bloco provider no opencode.json.

O OpenCode suporta providers personalizados compatíveis com OpenAI nativamente. Adicione uma entrada de provider no opencode.json com npm definido como "@ai-sdk/openai-compatible", defina options.baseURL como https://api.apisrouter.com/v1, leia a chave de uma variável de ambiente com o template {env:...}, e liste os ids de modelo que você quer em models. Depois defina o campo model do nível superior como "apisrouter/<model-id>" e o OpenCode roteia o loop de agente inteiro pelo gateway. Esse é o caminho de provider personalizado documentado na documentação do OpenCode, não um wrapper ou um fork. O arquivo de configuração vive na raiz do seu projeto (opencode.json) ou globalmente em ~/.config/opencode/opencode.json, e os dois são mesclados, então o bloco provider pode ser declarado uma vez e reutilizado em todo repositório.

{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "apisrouter": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "APIsRouter",
      "options": {
        "baseURL": "https://api.apisrouter.com/v1",
        "apiKey": "{env:APISROUTER_API_KEY}"
      },
      "models": {
        "claude-sonnet-4-6": { "name": "Claude Sonnet 4.6" }
      }
    }
  },
  "model": "apisrouter/claude-sonnet-4-6"
}

Como o OpenCode resolve providers e modelos.

O OpenCode (anomalyco no GitHub, um dos agentes de codificação de terminal com mais estrelas, cerca de 186 mil) constrói sua camada de provider sobre o Vercel AI SDK. O campo npm em um bloco provider nomeia qual pacote do SDK o OpenCode carrega para falar com esse provider: "@ai-sdk/openai-compatible" fala o protocolo padrão /v1/chat/completions, enquanto "@ai-sdk/openai" fala o protocolo /v1/responses da OpenAI. Um gateway multi-fornecedor serve chat completions, então openai-compatible é o pacote certo; escolher "@ai-sdk/openai" contra um endpoint de chat-completions é a forma mais comum dessa configuração quebrar. Modelos são endereçados como pares provider/model. O id do provider é a chave que você escolheu no bloco provider ("apisrouter" acima), e o id do modelo é a chave dentro do mapa models, então o modelo padrão se torna "apisrouter/claude-sonnet-4-6". Tudo que você declarar aparece no seletor /models dentro da TUI, trocável no meio da sessão. Um comportamento que vale a pena internalizar: para providers personalizados, o mapa models é uma allowlist. Providers nativos vêm com um catálogo conhecido, mas o OpenCode não consegue enumerar os modelos de um endpoint personalizado por conta própria, então só os ids que você declara explicitamente ficam endereçáveis. Quando o endpoint atrás de baseURL serve ids Claude, GPT, DeepSeek e Kimi lado a lado, declarar uma entrada por modelo transforma o seletor em um painel de troca entre fornecedores atrás de uma única chave.

Configuração completa: config global, config de projeto, limites por modelo.

O layout limpo é declarar o provider uma vez na configuração global em ~/.config/opencode/opencode.json e manter no opencode.json de cada projeto só as escolhas por repositório (qual modelo, quais agentes). O OpenCode mescla arquivos de configuração em vez de substituí-los, então o arquivo do projeto fica pequeno e o bloco provider nunca é duplicado. O template {env:APISROUTER_API_KEY} resolve no momento do carregamento a partir do ambiente, o que mantém a chave fora de qualquer arquivo que possa ser commitado. Exporte-a do perfil do seu shell para que toda sessão de terminal que lança o OpenCode consiga vê-la. Cada entrada de modelo também aceita um objeto limit com tetos de token de contexto e saída. Declará-los importa mais do que parece: o OpenCode usa o número de contexto para decidir quando uma sessão precisa de sumarização, então um modelo de contexto longo declarado sem limites é tratado de forma mais conservadora do que deveria. Defina limit.context para o que o modelo de fato suporta e sessões longas compactam mais tarde em vez de mais cedo.

{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "apisrouter": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "APIsRouter",
      "options": {
        "baseURL": "https://api.apisrouter.com/v1",
        "apiKey": "{env:APISROUTER_API_KEY}"
      },
      "models": {
        "claude-opus-4-7":   { "name": "Claude Opus 4.7",   "limit": { "context": 200000, "output": 32000 } },
        "claude-sonnet-4-6": { "name": "Claude Sonnet 4.6", "limit": { "context": 200000, "output": 64000 } },
        "gpt-5.5":           { "name": "GPT-5.5" },
        "gpt-5.6-sol": { "name": "GPT-5.6 Sol" },
        "kimi-k2.7-code":    { "name": "Kimi K2.7 Code" }
      }
    }
  },
  "model": "apisrouter/claude-sonnet-4-6",
  "small_model": "apisrouter/kimi-k2.7-code"
}

Escolhendo model e small_model.

O fluxo de trabalho prático é manter o slot principal no modelo em que você confia para edições e rotacionar candidatos em sessões reais em vez de benchmarks: uma tarde de diffs reais contra seu próprio código diz mais que um leaderboard. Rotear por um endpoint torna cada candidato uma mudança de uma linha, e a visão de uso por chave mostra quanto cada experimento realmente custou.

  • model dirige o loop principal do agente: ler arquivos, planejar edições, escrever diffs, rodar ferramentas. Esse slot vê os contextos mais longos e faz a engenharia de verdade, então um modelo de codificação de ponta (claude-sonnet-4-6, claude-opus-4-7, gpt-5.5) pertence aqui.
  • small_model cuida de tarefas leves como geração de título de sessão. Ele dispara com frequência mas nunca carrega o trabalho de codificação, então um id rápido e barato é o formato certo; não há motivo para queimar tokens de ponta em títulos.
  • Ids ajustados para código como gpt-5.6-sol e kimi-k2.7-code valem a pena declarar mesmo se não forem seu padrão: trocar para eles em uma sessão pesada de refatoração é uma seleção no /models, não uma edição de configuração.
  • Como os dois slots aceitam strings provider/model contra o mesmo bloco provider, os slots principal e pequeno podem vir de fornecedores diferentes na mesma sessão, algo que nenhuma chave de fornecedor único permite.

Pague pelo uso · abaixo do preço oficial

Selected models are priced below official list prices. Exact input, output, cache, and per-request prices are shown for each model.

ModeloPreço oficialNosso preço
Claude Sonnet 4.6$3.00 / $15.00 per M$2.40 / $12.00 per M
Claude Opus 4.7$5.00 / $25.00 per M$4.00 / $20.00 per M
GPT-5.5$5.00 / $30.00 per M$4.00 / $24.00 per M
GPT-5.6 Sol$5.00 / $30.00 per M$4.00 / $24.00 per M
Kimi K2.7 Code$0.95 / $4.00 per M$1.00 / $4.00 per M

Os modos de falha específicos dos providers personalizados do OpenCode.

Pacote de SDK errado. "@ai-sdk/openai" faz POST em /v1/responses; um gateway de chat-completions responde essa rota com um erro. Se sua primeira requisição falhar com um erro no formato de protocolo ou rota em vez de um erro de autenticação, verifique se o campo npm diz exatamente "@ai-sdk/openai-compatible". Modelo ausente no seletor. Modelos de provider personalizado só existem se declarados; um erro de digitação em uma chave de models, ou um id que você assumiu mas nunca adicionou, simplesmente não aparece em /models. Ids são strings exatas incluindo sufixos de versão, e a listagem /v1/models do gateway é a fonte de verdade para copiar. {env:...} não resolvido. O template resolve a partir do ambiente do processo que lançou o OpenCode. Uma chave exportada em um terminal não alcança uma instância do OpenCode lançada de outro terminal ou de um lançador de desktop que nunca carregou seu perfil. Coloque o export no perfil do shell, não em uma sessão avulsa. Surpresas de mesclagem de configuração. Como as configurações global e de projeto se mesclam, um opencode.json de projeto que define model para um provider diferente sobrepõe silenciosamente seu padrão global, e um bloco provider deixado para trás em um projeto antigo pode ofuscar expectativas. Quando o roteamento parecer errado, leia os dois arquivos antes de assumir que o gateway se comportou mal. baseURL sem /v1. O SDK anexa caminhos de rota como /chat/completions à base que você fornece, então https://api.apisrouter.com/v1 está correto e o host puro não. Uma falha de conexão ou no formato 404 em uma configuração aparentemente correta quase sempre é isso.

Quem roteia o OpenCode por um gateway.

  • Desenvolvedores que vivem na TUI o dia inteiro e querem Claude, GPT e Kimi em um seletor /models em vez de manter credenciais de provider separadas por fornecedor.
  • Engenheiros comparando modelos de codificação em trabalho real. Cada candidato é uma entrada declarada e uma seleção no seletor; a comparação sessão a sessão não precisa de contas novas.
  • Times padronizando um único segredo. Um único APISROUTER_API_KEY na documentação de onboarding substitui uma checklist de chaves por fornecedor, e o uso por chave mostra quem gasta o quê.
  • Usuários combinando um modelo principal de ponta com um small_model barato de um fornecedor diferente, algo que configurações de fornecedor único não conseguem expressar.
  • Desenvolvedores sem acesso ao faturamento de um determinado fornecedor. O acesso baseado em recarga sem exigência de cartão remove a dependência de cadastro por provedor.

Verifique o endpoint e depure a primeira sessão.

Antes de começar uma sessão, liste o que o gateway serve. Os ids retornados por /v1/models são exatamente as strings que as chaves do seu mapa models precisam corresponder. As falhas da primeira sessão são consistentes. Um 401 significa que APISROUTER_API_KEY não estava visível para o processo do OpenCode; use echo na variável no mesmo terminal de onde você lança. Um erro de modelo não encontrado do gateway significa que a chave declarada não corresponde a um id servido, sufixos de versão incluídos. Se o provider não aparecer de jeito nenhum, valide o JSON, já que uma vírgula sobrando ou uma chave mal posicionada torna o arquivo inteiro ilegível e o OpenCode volta para os padrões. Assim que as requisições fluem, o console da APIsRouter mostra modelo, contagens de token e gasto por requisição. Agentes de codificação são cargas de trabalho de contexto longo e muitos turnos, e ver quais sessões e quais modelos consomem os tokens é como você decide se o slot principal está valendo o preço.

curl -s https://api.apisrouter.com/v1/models \
  -H "Authorization: Bearer $APISROUTER_API_KEY" | head -50

Perguntas frequentes

O OpenCode pode usar modelos Claude, GPT e Kimi por um único provider personalizado?

Sim. Um provider personalizado é só uma baseURL mais uma allowlist de models. Quando o endpoint serve múltiplos fornecedores, declare uma entrada por id e cada modelo declarado aparece no seletor /models sob o mesmo provider e chave, trocável no meio da sessão.

Onde a chave de API vai no opencode.json?

Em options.apiKey usando o template de ambiente, por exemplo "{env:APISROUTER_API_KEY}". O template resolve no momento do carregamento então a chave literal nunca fica no arquivo de configuração. Exporte a variável do perfil do seu shell para que todo terminal que lança o OpenCode a herde.

O bloco provider deve viver na configuração global ou de projeto?

Global, em ~/.config/opencode/opencode.json. O OpenCode mescla arquivos de configuração, então declarar o provider uma vez globalmente e definir só a escolha de modelo por projeto mantém os repositórios livres de encanamento de credenciais e evita blocos duplicados divergindo entre si.

Por que meu modelo não aparece no seletor /models?

Modelos de provider personalizado precisam ser declarados explicitamente; o OpenCode não consegue enumerar um endpoint personalizado. Verifique se o mapa models contém a string de id exata, sufixos de versão incluídos, e copie os ids da resposta /v1/models do gateway em vez de digitá-los de memória.

Qual é a diferença entre @ai-sdk/openai-compatible e @ai-sdk/openai aqui?

@ai-sdk/openai-compatible fala /v1/chat/completions, o protocolo que gateways multi-fornecedor servem. @ai-sdk/openai fala o protocolo /v1/responses da OpenAI. Para a APIsRouter, use @ai-sdk/openai-compatible; o outro pacote vai fazer POST em uma rota que o gateway não serve para esse fim.

Os limites de contexto declarados realmente importam?

Sim. O OpenCode usa limit.context para decidir quando uma sessão precisa de compactação. Deixar limites não declarados em um modelo de contexto longo significa que sessões são sumarizadas mais cedo do que precisariam; defina limit.context e limit.output para o que o modelo genuinamente suporta.