Los ids de modelo no pertenecen a TypeScript

· 6 min de lectura

Un id de modelo es el dato que más rápido cambia en todo este sistema. Los proveedores los renombran, los retiran, publican una variante con fecha, cambian discretamente a qué apunta el alias sin fecha y condicionan la mitad de ellos a qué cuenta pregunta. Compila eso dentro de un paquete y habrás garantizado que el paquete esté mal en cuestión de semanas; no roto de forma evidente, lo que al menos daría un informe de error, sino mal de esa manera concreta en la que un selector ofrece a alguien un modelo que su clave no puede llamar.

Por eso el catálogo es un archivo JSON, y lo interesante no es que sea JSON. Es lo que la separación en capas que hay debajo admite sobre la certeza.

Cinco capas: las posteriores ganan a las anteriores

0. pi-ai's built-in models      whatever it knows about the catalogued vendors
1. the bundled catalog.json     27 providers, 6 verified models
2. ~/.oharness/catalog.json     your edits, and what discovery found
3. a catalog path in config
4. providers / models in config
5. /models refresh              asks the vendor directly

Lee esa columna de números como una clasificación de confianza, no como un orden de carga. La capa 0 es la instantánea del mundo de otra persona. La capa 1 es lo que estábamos dispuestos a afirmar sin rodeos. La capa 5 es el proveedor respondiendo sobre tu cuenta, ahora mismo, y gana, porque nada de lo que publicamos hace tres meses sabe más sobre tus derechos de acceso que el endpoint al que estás a punto de llamar.

La capa incluida trae veintisiete proveedores y seis modelos verificados, y esa proporción es todo el diseño. Los datos del proveedor —el endpoint, la variable de entorno, el protocolo de transmisión— son lo bastante estables para publicarlos. Los ids de modelo no lo son, así que los únicos que se afirman sin rodeos son los que realmente pudieron verificarse, y todo lo demás llega mediante el descubrimiento, que consulta el propio /models de cada proveedor.

Seis es un número incómodo de publicar. También es el honesto.

Las sobrescrituras son a nivel de campo

La razón por la que esto importa en el día a día es más pequeña y más aburrida: apuntar Kimi a su endpoint de China continental no debería obligar a repetir todo lo demás sobre Kimi.

{ "providers": { "moonshot": { "baseUrl": "https://api.moonshot.cn/v1" } } }

Esa es toda la edición. Las sobrescrituras de entradas completas son la forma en que se pudren los formatos de configuración: alguien copia el bloque publicado para cambiar una URL y, dos versiones después, su copia es lo único que se interpone entre esa persona y una corrección que todos los demás ya recibieron.

Dónde se detiene la semilla

La capa 0 merece una nota, porque es la que sorprende a la gente: un proveedor que nunca has conectado ya tiene modelos que mostrar. Vienen de pi-ai, la capa de transmisión, que incluye un catálogo generado con lo que conoce. Traen ventanas de contexto, precios y niveles de razonamiento, y no saben absolutamente nada de lo que tu cuenta puede llamar; por eso tanto una entrada declarada como cualquier cosa que devuelva el descubrimiento les ganan, y OHARNESS_NO_BUILTIN_MODELS=1 desactiva la semilla por completo.

Dos límites impiden que esa semilla cause daños.

Un modelo solo se siembra en una entrada cuyo protocolo coincida con la API contra la que pi-ai lo cataloga. Los modelos de Mistral figuran contra la API de conversaciones propia de pi-ai, así que se dejan al descubrimiento en lugar de enviarse a un endpoint compatible con OpenAI en una forma que no habla. Enviar la forma equivocada es un 400 que te toca depurar, no una respuesta degradada con la que puedas vivir.

Y cuando los dos catálogos no coinciden en el id de un proveedor, se concilian nombrando el otro, no adivinando:

{ "providers": { "moonshot": { "piProvider": "moonshotai" } } }

Un proveedor sin semilla y aún sin descubrimiento —un servidor local, una pasarela para la que nadie incluye nombres— sigue apareciendo en el selector como una única fila que abre el panel donde lo conectas. Un estado vacío que se explica solo es mejor que un proveedor que simplemente no está hasta que se cumple alguna condición invisible.

El protocolo es lo único que merece nombrarse

El protocol de una entrada del catálogo indica el formato que habla su endpoint:

anthropic-messages   openai-chat      openai-responses
gemini               bedrock          vertex
openai-codex

openai-codex es el que justifica mantener esta lista explícita en lugar de deducirla del nombre del proveedor. Es el backend con el que habla Codex CLI, y es un formato de transmisión realmente distinto de openai-responses, no el mismo en otro host: store se rechaza, max_output_tokens no se envía y el id de cuenta viaja en su propia cabecera. Un sistema que adivinara «es OpenAI, usa la forma de OpenAI» se equivocaría en tres aspectos distintos.

Los SDK que hay detrás se importan de forma diferida, así que una sesión que solo habla con Anthropic nunca carga los clientes de AWS ni de Google.

Lo que no se movió

La autenticación. Las credenciales las resuelve en cada solicitud el propio AuthManager del harness, porque un token de suscripción que era válido al arrancar no lo es una hora después. Por eso las implementaciones de API de pi-ai se llaman directamente y reciben una clave y unas cabeceras ya resueltas, en lugar de pasar por su autenticación de proveedores y su almacén de credenciales.

Por eso algunas entradas no se publican en absoluto. Bedrock y Vertex funcionan como protocolos, pero solo con credenciales que ya estén en el entorno: la firma SigV4 completa y gcloud ADC viven justo en la capa de proveedores que este harness evita usar para la autenticación. Azure OpenAI no tiene una URL base fija que catalogar, porque el endpoint depende de cada despliegue. Cualquiera cuyo entorno ya esté preparado puede declarar ambos; ninguno se va a publicar como un valor predeterminado que funciona y que, en silencio, no funciona.

El patrón que hay debajo de todo: afirma los datos que se mantienen quietos, pregunta por los que no, y deja la diferencia visible en el archivo en lugar de enterrarla en unas notas de la versión.


OHarness es un harness de agentes de código abierto con licencia MIT. La referencia de proveedores documenta cada capa, sobrescritura y protocolo anteriores, y el centro de proveedores enumera lo que incluye hoy el catálogo integrado.