Aggiungi un provider personalizzato compatibile OpenAI a OpenCode.
Updated 2026-07-29
OpenCode legge i provider personalizzati direttamente da opencode.json. Dichiara un blocco provider con il pacchetto @ai-sdk/openai-compatible, punta options.baseURL su https://api.apisrouter.com/v1, e ogni modello che elenchi diventa selezionabile nel selettore /models sotto un'unica chiave.
Risposta rapida: un blocco provider in opencode.json.
OpenCode supporta nativamente i provider personalizzati compatibili OpenAI. Aggiungi una voce provider a opencode.json con npm impostato su "@ai-sdk/openai-compatible", imposta options.baseURL su https://api.apisrouter.com/v1, leggi la chiave da una variabile d'ambiente con il template {env:...}, ed elenca gli id dei modelli che vuoi sotto models. Poi imposta il campo model di primo livello su "apisrouter/<model-id>" e OpenCode instrada l'intero ciclo dell'agente attraverso il gateway. Questo è il percorso documentato per i provider personalizzati nella documentazione di OpenCode, non un wrapper o un fork. Il file di configurazione risiede o nella radice del tuo progetto (opencode.json) o globalmente in ~/.config/opencode/opencode.json, e i due vengono uniti, quindi il blocco provider può essere dichiarato una volta e riutilizzato in ogni repo.
{
"$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"
}Come OpenCode risolve provider e modelli.
OpenCode (anomalyco su GitHub, uno degli agenti di coding da terminale con più stelle, circa 186K) costruisce il suo layer di provider sul Vercel AI SDK. Il campo npm in un blocco provider nomina quale pacchetto SDK OpenCode carica per parlare con quel provider: "@ai-sdk/openai-compatible" parla il protocollo standard /v1/chat/completions, mentre "@ai-sdk/openai" parla il protocollo /v1/responses di OpenAI. Un gateway multi-fornitore serve chat completions, quindi openai-compatible è il pacchetto giusto; scegliere "@ai-sdk/openai" contro un endpoint chat-completions è il modo più comune in cui questa configurazione si rompe. I modelli si indirizzano come coppie provider/model. L'id del provider è qualunque chiave tu abbia scelto nel blocco provider ("apisrouter" sopra), e l'id del modello è la chiave dentro la mappa models, quindi il modello predefinito diventa "apisrouter/claude-sonnet-4-6". Tutto ciò che dichiari compare nel selettore /models dentro la TUI, commutabile a metà sessione. Un comportamento che vale la pena interiorizzare: per i provider personalizzati, la mappa models è una allowlist. I provider integrati vengono distribuiti con un catalogo noto, ma OpenCode non può enumerare da solo i modelli di un endpoint personalizzato, quindi sono indirizzabili solo gli id che dichiari esplicitamente. Quando l'endpoint dietro baseURL serve id Claude, GPT, DeepSeek e Kimi fianco a fianco, dichiarare una voce per modello trasforma il selettore in un centralino cross-fornitore dietro un'unica chiave.
Configurazione completa: config globale, config di progetto, limiti per modello.
L'organizzazione pulita è dichiarare il provider una volta nella config globale in ~/.config/opencode/opencode.json e mantenere solo le scelte per repo (quale modello, quali agenti) nell'opencode.json di ciascun progetto. OpenCode unisce i file di configurazione invece di sostituirli, quindi il file di progetto resta minuscolo e il blocco provider non viene mai duplicato. Il template {env:APISROUTER_API_KEY} si risolve al momento del caricamento dall'ambiente, il che mantiene la chiave fuori da qualsiasi file che potrebbe finire committato. Esportala dal tuo profilo di shell così che ogni sessione di terminale che lancia OpenCode possa vederla. Ogni voce di modello accetta anche un oggetto limit con tetti di token per contesto e output. Dichiararli conta più di quanto sembri: OpenCode usa il valore del contesto per decidere quando una sessione ha bisogno di riassunto, quindi un modello a contesto lungo dichiarato senza limiti viene trattato in modo più conservativo di quanto dovrebbe. Imposta limit.context su ciò che il modello supporta davvero e le sessioni lunghe si comprimono più tardi invece che prima.
{
"$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"
}Scegliere model e small_model.
Il workflow pratico è mantenere lo slot main sul modello di cui ti fidi per le modifiche e far ruotare i candidati attraverso sessioni reali piuttosto che benchmark: un pomeriggio di diff reali sulla tua codebase ti dice più di una classifica. Instradare attraverso un unico endpoint rende ogni candidato una modifica di una riga, e la vista di utilizzo per chiave mostra quanto è costato davvero ogni esperimento.
- model guida il ciclo principale dell'agente: leggere file, pianificare modifiche, scrivere diff, eseguire strumenti. Questo slot vede i contesti più lunghi e fa l'ingegneria vera e propria, quindi qui appartiene un modello di coding di frontiera (claude-sonnet-4-6, claude-opus-4-7, gpt-5.5).
- small_model gestisce task leggeri come la generazione del titolo di sessione. Si attiva spesso ma non porta mai il lavoro di coding, quindi un id veloce ed economico è la forma giusta; non c'è motivo di bruciare token di frontiera sui titoli.
- Gli id ottimizzati per il coding come gpt-5.6-sol e kimi-k2.7-code vale la pena dichiararli anche se non sono il tuo default: passare a essi per una sessione ricca di refactoring è una singola selezione /models, non una modifica di configurazione.
- Poiché entrambi gli slot prendono stringhe provider/model contro lo stesso blocco provider, gli slot main e small possono provenire da fornitori diversi nella stessa sessione, qualcosa che nessuna chiave a fornitore singolo consente.
Pagamento a consumo · sotto i prezzi ufficiali
Selected models are priced below official list prices. Exact input, output, cache, and per-request prices are shown for each model.
| Modello | Prezzo ufficiale | Il nostro prezzo |
|---|---|---|
| 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 |
Le modalità di errore specifiche dei provider personalizzati di OpenCode.
Pacchetto SDK sbagliato. "@ai-sdk/openai" invia a /v1/responses; un gateway chat-completions risponde a quella route con un errore. Se la tua prima richiesta fallisce con un errore a forma di protocollo o route piuttosto che un errore di autenticazione, controlla che il campo npm dica esattamente "@ai-sdk/openai-compatible". Modello assente dal selettore. I modelli dei provider personalizzati esistono solo se dichiarati; un errore di battitura in una chiave models, o un id che hai dato per scontato ma mai aggiunto, semplicemente non compare in /models. Gli id sono stringhe esatte inclusi i suffissi di versione, e l'elenco /v1/models del gateway è la fonte di verità da cui copiare. {env:...} non risolto. Il template si risolve dall'ambiente del processo che ha lanciato OpenCode. Una chiave esportata in un terminale non raggiunge un'istanza di OpenCode lanciata da un altro terminale o da un launcher desktop che non ha mai caricato il tuo profilo. Metti l'export nel profilo di shell, non in una sessione una tantum. Sorprese da unione della config. Poiché le config globale e di progetto si uniscono, un opencode.json di progetto che imposta model su un provider diverso sovrascrive silenziosamente il tuo default globale, e un blocco provider residuo in un vecchio progetto può oscurare le aspettative. Quando l'instradamento sembra sbagliato, leggi entrambi i file prima di dare per scontato che il gateway si sia comportato male. baseURL senza /v1. L'SDK aggiunge percorsi di route come /chat/completions a qualunque base tu gli dia, quindi https://api.apisrouter.com/v1 è corretto e l'host nudo non lo è. Un fallimento di connessione o a forma di 404 su una configurazione altrimenti corretta è quasi sempre questo.
Chi instrada OpenCode tramite un gateway.
- Sviluppatori che vivono nella TUI tutto il giorno e vogliono Claude, GPT e Kimi in un unico selettore /models invece di mantenere credenziali di provider separate per fornitore.
- Ingegneri che confrontano modelli di coding su lavoro reale. Ogni candidato è una voce dichiarata e una selezione nel selettore; il confronto sessione per sessione non richiede nuovi account.
- Team che standardizzano su un solo segreto. Un'unica APISROUTER_API_KEY nella documentazione di onboarding sostituisce una checklist di chiavi per fornitore, e l'utilizzo per chiave mostra chi spende cosa.
- Utenti che abbinano un modello main di frontiera con uno small_model economico di un fornitore diverso, cosa che le configurazioni a fornitore singolo non possono esprimere.
- Sviluppatori senza accesso alla fatturazione di un dato fornitore. L'accesso basato su ricarica senza obbligo di carta rimuove la dipendenza dalla registrazione per provider.
Verifica l'endpoint e fai debug della prima sessione.
Prima di iniziare una sessione, elenca cosa serve il gateway. Gli id restituiti da /v1/models sono esattamente le stringhe che le chiavi della tua mappa models devono corrispondere. I fallimenti della prima sessione sono coerenti. Un 401 significa che APISROUTER_API_KEY non era visibile al processo OpenCode; fai un echo della variabile nello stesso terminale da cui lanci. Un errore modello-non-trovato dal gateway significa che la chiave dichiarata non corrisponde a un id servito, suffissi di versione inclusi. Se il provider non compare affatto, valida il JSON, dato che una virgola in eccesso o una parentesi fuori posto rende illeggibile l'intero file e OpenCode ricade sui default. Una volta che le richieste scorrono, la console di APIsRouter mostra modello per richiesta, conteggi dei token e spesa. Gli agenti di coding sono carichi di lavoro a contesto lungo e molti turni, e vedere quali sessioni e quali modelli consumano i token è come decidi se lo slot main si sta guadagnando il suo prezzo.
curl -s https://api.apisrouter.com/v1/models \
-H "Authorization: Bearer $APISROUTER_API_KEY" | head -50Domande frequenti
OpenCode può usare modelli Claude, GPT e Kimi tramite un unico provider personalizzato?
Sì. Un provider personalizzato è solo un baseURL più una allowlist di modelli. Quando l'endpoint serve più fornitori, dichiara una voce per id e ogni modello dichiarato compare nel selettore /models sotto lo stesso provider e chiave, commutabile a metà sessione.
Dove va la chiave API in opencode.json?
In options.apiKey usando il template d'ambiente, per esempio "{env:APISROUTER_API_KEY}". Il template si risolve al momento del caricamento così che la chiave letterale non risieda mai nel file di configurazione. Esporta la variabile dal tuo profilo di shell così che ogni terminale che lancia OpenCode la erediti.
Il blocco provider dovrebbe risiedere nella config globale o di progetto?
Globale, in ~/.config/opencode/opencode.json. OpenCode unisce i file di configurazione, quindi dichiarare il provider una volta globalmente e impostare solo la scelta del modello per progetto mantiene i repo liberi dall'idraulica delle credenziali ed evita che blocchi duplicati si allontanino tra loro.
Perché il mio modello non compare nel selettore /models?
I modelli dei provider personalizzati devono essere dichiarati esplicitamente; OpenCode non può enumerare un endpoint personalizzato. Controlla che la mappa models contenga la stringa id esatta, suffissi di versione inclusi, e copia gli id dalla risposta /v1/models del gateway invece di digitarli a memoria.
Qual è la differenza tra @ai-sdk/openai-compatible e @ai-sdk/openai qui?
@ai-sdk/openai-compatible parla /v1/chat/completions, il protocollo servito dai gateway multi-fornitore. @ai-sdk/openai parla il protocollo /v1/responses di OpenAI. Per APIsRouter, usa @ai-sdk/openai-compatible; l'altro pacchetto invierà a una route che il gateway non serve per questo scopo.
I limiti di contesto dichiarati contano davvero?
Sì. OpenCode usa limit.context per decidere quando una sessione ha bisogno di compressione. Lasciare i limiti non dichiarati su un modello a contesto lungo significa che le sessioni vengono riassunte prima del necessario, quindi imposta limit.context e limit.output su ciò che il modello supporta davvero.