Añade un proveedor personalizado compatible con OpenAI a OpenCode.
Updated 2026-07-29
OpenCode lee proveedores personalizados directamente desde opencode.json. Declara un bloque provider con el paquete @ai-sdk/openai-compatible, apunta options.baseURL a https://api.apisrouter.com/v1, y cada modelo que listes se vuelve seleccionable en el selector /models bajo una sola clave.
Respuesta rápida: un bloque provider en opencode.json.
OpenCode admite proveedores personalizados compatibles con OpenAI de forma nativa. Añade una entrada provider a opencode.json con npm configurado en "@ai-sdk/openai-compatible", configura options.baseURL en https://api.apisrouter.com/v1, lee la clave desde una variable de entorno con la plantilla {env:...}, y lista los ids de modelo que quieras bajo models. Luego configura el campo model de nivel superior en "apisrouter/<model-id>" y OpenCode enruta todo el bucle del agente a través del gateway. Esta es la ruta de proveedor personalizado documentada en los docs de OpenCode, no un wrapper ni un fork. El archivo de configuración vive en la raíz de tu proyecto (opencode.json) o globalmente en ~/.config/opencode/opencode.json, y ambos se combinan, así que el bloque provider puede declararse una vez y reutilizarse en todos los repositorios.
{
"$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"
}Cómo resuelve OpenCode proveedores y modelos.
OpenCode (anomalyco en GitHub, uno de los agentes de codificación de terminal con más estrellas, unas 186K) construye su capa de proveedores sobre el Vercel AI SDK. El campo npm en un bloque provider nombra qué paquete del SDK carga OpenCode para hablar con ese proveedor: "@ai-sdk/openai-compatible" habla el protocolo estándar /v1/chat/completions, mientras que "@ai-sdk/openai" habla el protocolo /v1/responses de OpenAI. Un gateway multiproveedor sirve chat completions, así que openai-compatible es el paquete correcto; elegir "@ai-sdk/openai" contra un endpoint de chat-completions es la forma más común en que esta configuración se rompe. Los modelos se direccionan como pares provider/model. El id de proveedor es la clave que hayas elegido en el bloque provider ("apisrouter" arriba), y el id de modelo es la clave dentro del mapa models, así que el modelo por defecto se convierte en "apisrouter/claude-sonnet-4-6". Todo lo que declares aparece en el selector /models dentro de la TUI, intercambiable a mitad de sesión. Un comportamiento que vale la pena interiorizar: para proveedores personalizados, el mapa models es una lista blanca. Los proveedores integrados vienen con un catálogo conocido, pero OpenCode no puede enumerar por sí solo los modelos de un endpoint personalizado, así que solo los ids que declares explícitamente son direccionables. Cuando el endpoint detrás de baseURL sirve ids de Claude, GPT, DeepSeek y Kimi lado a lado, declarar una entrada por modelo convierte el selector en una centralita cruzada de proveedores tras una sola clave.
Configuración completa: config global, config de proyecto, límites por modelo.
La disposición más limpia es declarar el proveedor una sola vez en la configuración global en ~/.config/opencode/opencode.json y mantener en el opencode.json de cada proyecto solo las decisiones por repositorio (qué modelo, qué agentes). OpenCode combina los archivos de configuración en lugar de reemplazarlos, así que el archivo del proyecto se mantiene diminuto y el bloque provider nunca se duplica. La plantilla {env:APISROUTER_API_KEY} se resuelve al momento de carga desde el entorno, lo que mantiene la clave fuera de cualquier archivo que pudiera terminar en un commit. Expórtala desde el perfil de tu shell para que cada sesión de terminal que lance OpenCode pueda verla. Cada entrada de modelo también acepta un objeto limit con techos de tokens de contexto y de salida. Declararlos importa más de lo que parece: OpenCode usa la cifra de contexto para decidir cuándo una sesión necesita resumirse, así que un modelo de contexto largo declarado sin límites se trata de forma más conservadora de lo que debería. Configura limit.context según lo que el modelo realmente soporta y las sesiones largas se compactan más tarde en lugar de antes.
{
"$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"
}Elegir modelos para model y small_model.
El flujo de trabajo práctico es mantener el slot principal en el modelo en el que confías para las ediciones y rotar candidatos en sesiones reales en lugar de benchmarks: una tarde de diffs reales contra tu propia base de código te dice más que una tabla de clasificación. Enrutar por un solo endpoint convierte cada candidato en un cambio de una línea, y la vista de uso por clave muestra cuánto costó realmente cada experimento.
- model impulsa el bucle principal del agente: leer archivos, planificar ediciones, escribir diffs, ejecutar herramientas. Este slot ve los contextos más largos y hace la ingeniería real, así que un modelo de codificación de vanguardia (claude-sonnet-4-6, claude-opus-4-7, gpt-5.5) pertenece aquí.
- small_model maneja tareas ligeras como la generación de títulos de sesión. Se dispara a menudo pero nunca carga con el trabajo de codificación, así que un id rápido y económico es la forma correcta; no hay razón para quemar tokens de vanguardia en títulos.
- Los ids afinados para código como gpt-5.6-sol y kimi-k2.7-code merecen declararse aunque no sean tu opción por defecto: cambiar a ellos para una sesión intensiva en refactorización es una sola selección en /models, no una edición de configuración.
- Como ambos slots aceptan cadenas provider/model contra el mismo bloque provider, los slots main y small pueden venir de proveedores distintos en la misma sesión, algo que ninguna clave de un solo proveedor permite.
Pago por uso · por debajo del precio oficial
Selected models are priced below official list prices. Exact input, output, cache, and per-request prices are shown for each model.
| Modelo | Precio oficial | Nuestro precio |
|---|---|---|
| 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 |
Modos de fallo específicos de los proveedores personalizados de OpenCode.
Paquete de SDK equivocado. "@ai-sdk/openai" hace POST a /v1/responses; un gateway de chat-completions responde a esa ruta con un error. Si tu primera petición falla con un error de forma de protocolo o de ruta en lugar de un error de autenticación, comprueba que el campo npm diga exactamente "@ai-sdk/openai-compatible". Modelo ausente del selector. Los modelos de proveedores personalizados solo existen si se declaran; un error tipográfico en una clave de models, o un id que asumiste pero nunca añadiste, simplemente no aparece en /models. Los ids son cadenas exactas, incluidos sufijos de versión, y el listado /v1/models del gateway es la fuente de verdad de la que copiar. {env:...} sin resolver. La plantilla se resuelve desde el entorno del proceso que lanzó OpenCode. Una clave exportada en una terminal no llega a una instancia de OpenCode lanzada desde otra terminal o desde un lanzador de escritorio que nunca cargó tu perfil. Pon el export en el perfil de la shell, no en una sesión puntual. Sorpresas al combinar configuraciones. Como las configuraciones global y de proyecto se combinan, un opencode.json de proyecto que configura model a un proveedor distinto sobrescribe silenciosamente tu valor global por defecto, y un bloque provider olvidado en un proyecto antiguo puede eclipsar lo que esperas. Cuando el enrutamiento se vea raro, lee ambos archivos antes de asumir que el gateway se comportó mal. baseURL sin /v1. El SDK añade rutas como /chat/completions a lo que le des como base, así que https://api.apisrouter.com/v1 es correcto y el host pelado no lo es. Un fallo de conexión o con forma de 404 sobre una configuración por lo demás correcta casi siempre es esto.
Quién enruta OpenCode a través de un gateway.
- Desarrolladores que viven todo el día en la TUI y quieren Claude, GPT y Kimi en un solo selector /models en lugar de mantener credenciales de proveedor separadas por vendor.
- Ingenieros que comparan modelos de codificación en trabajo real. Cada candidato es una entrada declarada y una selección en el picker; la comparación sesión a sesión no necesita cuentas nuevas.
- Equipos que estandarizan un solo secreto. Una única APISROUTER_API_KEY en la documentación de onboarding sustituye una lista de claves por proveedor, y el uso por clave muestra quién gasta qué.
- Usuarios que combinan un modelo main de vanguardia con un small_model económico de un proveedor distinto, algo que las configuraciones de un solo proveedor no pueden ofrecer.
- Desarrolladores sin acceso a la facturación de un proveedor concreto. El acceso mediante recarga sin necesidad de tarjeta elimina la dependencia de registrarse en cada proveedor.
Verifica el endpoint y depura la primera sesión.
Antes de empezar una sesión, lista lo que sirve el gateway. Los ids devueltos por /v1/models son exactamente las cadenas que deben coincidir con las claves de tu mapa models. Los fallos de primera sesión son consistentes. Un 401 significa que APISROUTER_API_KEY no era visible para el proceso de OpenCode; haz echo de la variable en la misma terminal desde la que lanzas. Un error de modelo no encontrado desde el gateway significa que la clave declarada no coincide con un id servido, sufijos de versión incluidos. Si el proveedor no aparece en absoluto, valida el JSON, ya que una coma sobrante o una llave mal colocada hace que todo el archivo sea ilegible y OpenCode recae en los valores por defecto. Una vez que las peticiones fluyen, la consola de APIsRouter muestra el modelo por petición, el recuento de tokens y el gasto. Los agentes de codificación son cargas de trabajo de contexto largo y muchos turnos, y ver qué sesiones y qué modelos consumen los tokens es cómo decides si el slot principal está justificando su precio.
curl -s https://api.apisrouter.com/v1/models \
-H "Authorization: Bearer $APISROUTER_API_KEY" | head -50Preguntas frecuentes
¿Puede OpenCode usar modelos de Claude, GPT y Kimi a través de un solo proveedor personalizado?
Sí. Un proveedor personalizado es solo un baseURL más una lista blanca de modelos. Cuando el endpoint sirve varios proveedores, declara una entrada por id y cada modelo declarado aparece en el selector /models bajo el mismo proveedor y clave, intercambiable a mitad de sesión.
¿Dónde va la clave de API en opencode.json?
En options.apiKey usando la plantilla de entorno, por ejemplo "{env:APISROUTER_API_KEY}". La plantilla se resuelve al momento de carga, así que la clave literal nunca queda en el archivo de configuración. Exporta la variable desde el perfil de tu shell para que cada terminal que lance OpenCode la herede.
¿El bloque provider debe vivir en la configuración global o en la del proyecto?
Global, en ~/.config/opencode/opencode.json. OpenCode combina los archivos de configuración, así que declarar el proveedor una vez a nivel global y configurar solo la elección de modelo por proyecto mantiene los repositorios libres de fontanería de credenciales y evita que bloques duplicados se desincronicen.
¿Por qué mi modelo no aparece en el selector /models?
Los modelos de proveedores personalizados deben declararse explícitamente; OpenCode no puede enumerar un endpoint personalizado. Comprueba que el mapa models contiene la cadena exacta del id, incluidos sufijos de versión, y copia los ids de la respuesta /v1/models del gateway en lugar de escribirlos de memoria.
¿Cuál es la diferencia entre @ai-sdk/openai-compatible y @ai-sdk/openai aquí?
@ai-sdk/openai-compatible habla /v1/chat/completions, el protocolo que sirven los gateways multiproveedor. @ai-sdk/openai habla el protocolo /v1/responses de OpenAI. Para APIsRouter, usa @ai-sdk/openai-compatible; el otro paquete hará POST a una ruta que el gateway no sirve para este propósito.
¿Realmente importan los límites de contexto declarados?
Sí. OpenCode usa limit.context para decidir cuándo una sesión necesita compactarse. Dejar los límites sin declarar en un modelo de contexto largo hace que las sesiones se resuman antes de lo necesario, así que configura limit.context y limit.output según lo que el modelo realmente soporta.