OmniRoute: una API, muchos modelos y una capa más que sí tengo que entender
Cambiar el modelo de un agente de código debería ser aburrido. Una URL, un nombre de modelo, quizá otra credencial. En la práctica cada cliente interpreta el formato a su manera, cada proveedor agrega sus campos propios, y yo termino editando variables de entorno a una hora en la que ya no debería tomar decisiones técnicas.
Uso OmniRoute porque ataca justo esa molestia. Levanta un gateway local en el puerto 20128, con dashboard incluido, y expone un endpoint compatible con OpenAI en http://localhost:20128/v1. Del otro lado puede hablar con proveedores comerciales o con Ollama corriendo en mi propia máquina. Aclaración de raíz: no lo hice yo y no tengo ninguna relación con el proyecto. Soy el usuario cansado del otro lado.
La idea cabe en una frase: una API, muchos modelos. Lo interesante empieza cuando preguntas qué simplifica de verdad esa capa y qué problemas solamente se mudan de lugar.
Un proxy, pero con criterio
Si nunca usaste uno, piensa en un proxy especializado. Tu agente no llama directo a OpenAI, Anthropic o Google. Llama a OmniRoute, que recibe la solicitud, decide a dónde va, adapta el protocolo si hace falta y devuelve una respuesta normalizada.
Agente de código
↓ compatible con OpenAI
http://localhost:20128/v1
↓ selección y adaptación
OpenAI | Anthropic | Google | Ollama | otrosEso concentra una decisión que antes tenía repartida por todos lados. En vez de soltar claves, URLs y reglas de fallback entre varios clientes, toda esa lógica vive en un proceso local que puedo abrir y leer.
La instalación documentada es corta:
npm install -g omniroute
omnirouteEl dashboard queda en http://localhost:20128. La versión que corría ese día, 3.8.48. Y un detalle que preferí encontrar en la documentación y no en un error a las once de la noche: el paquete exige Node >=22.22.2 <23 || >=24 <27. Node 23 queda fuera del rango, a propósito. Si tu entorno vive en la versión que no entra, revisa eso antes de instalar.
El proyecto es MIT, autoalojable, de diegosouzapw/OmniRoute, y también se publica como el paquete npm omniroute. Hay instalación con Docker y desde el código fuente. Para probarlo, npm reduce pasos. Para operarlo con más disciplina, un contenedor le pone un límite más claro al proceso, a su configuración y a sus secretos.
Lo que pasa en el medio
La palabra proxy se queda corta. Antes de tocar al proveedor hay capas de tolerancia a fallos: circuit breakers que sacan de circulación la ruta enferma y un cooldown por clave que respeta el Retry-After cuando el upstream contesta un 429. Con agentes importa: disparan muchas solicitudes, y un proxy común te devuelve el error y buena suerte. Esto espera lo que pide el proveedor y prueba otra ruta. No es magia. Es reintentar con criterio. Aunque es una pieza más que operar: si el gateway cae, todo pierde acceso aunque los proveedores estén sanos.
Del lado del cliente, solo hace falta una base URL y una clave local:
export OPENAI_BASE_URL=http://localhost:20128/v1
export OPENAI_API_KEY=omniroute-local-keyDespués pides un modelo explícito o una ruta automática. Las rutas auto expresan intención: auto/coding, auto/cheap, auto/offline. Lo bueno del alias es que mi configuración deja de nombrar proveedores: le pido auto/offline y el trabajo se queda en mi máquina si puede. Si mañana cambio de proveedor, lo cambio una vez en el alias y no en siete configuraciones.
La condición: dos ejecuciones con auto/coding pueden terminar en modelos distintos. Para completar trabajo está bien. Para reproducir una evaluación, no. Cuando comparo resultados o investigo una regresión, fijo proveedor y modelo a mano. El fallback merece la misma desconfianza: cambiar de modelo a mitad de un flujo puede alterar el tool calling o el costo. El circuito evita quedarte golpeando una puerta cerrada; no puede decidir si la de al lado sirve para lo mismo.
Una interfaz estable sobre protocolos que no lo son
Este es el beneficio que más valoro: los clientes hablan uno o dos dialectos, y una interfaz OpenAI-compatible reduce el acoplamiento y conecta herramientas que nunca fueron diseñadas para cada upstream. Del otro lado habla OpenAI Chat Completions, Responses, Anthropic Messages y Gemini. Suena a mucho, y en buena parte es verdad. Aun así no leería “compatible” como “idéntico”: una respuesta normalizada conserva solo lo que el modelo común puede representar, y esos formatos difieren en streaming, herramientas o razonamiento visible.
Por eso pruebo la ruta completa, no un curl que devuelve texto: streaming sin eventos truncados y argumentos de herramientas válidos. “El chat respondió” es una verificación demasiado pobre para algo que va a editar archivos o ejecutar comandos.
Hacia los proveedores soporta API key, OAuth 2.0 con PKCE y servicios sin clave. Ollama aparece como ciudadano de primera, y LM Studio y vLLM también están en la documentación. El caso que más uso es el local: misma base URL, ciertas tareas se van a Ollama, y eso vuelve viable una política auto/offline de verdad. La documentación lista como clientes Claude Code, Codex CLI, Cursor, OpenCode, Cline, Continue y Aider, que resulta ser casi exactamente mi menú diario.
Ojo: nada de esto convierte todo en privado por defecto. La privacidad depende de la ruta que elija la política y de cómo estén configurados los logs y las credenciales; autoalojar el router no encierra nada por sí solo. Y ojo con la plata: OmniRoute en sí es $0, pero los costos, los límites y los términos pertenecen a cada upstream. Si una ruta automática pasa de un proveedor sin clave a uno facturado, quiero enterarme antes y no al revisar el estado de cuenta.
Los números del catálogo no cuadran, y a esta altura me da risa
Tres superficies oficiales, el mismo día, tres inventarios distintos. El sitio dice 339 proveedores, 56 free-forever, 95 integraciones MCP y 25 mil tests. El README dice 351 proveedores, 56 free-forever, 110 integraciones MCP, 35 agentes CLI y 39 mil tests. El paquete en npm dice 352.
Ya ni intento conciliarlas. El catálogo se mueve rápido y algunas cifras parecen texto promocional actualizado en momentos distintos. Pero es un dato sobre el proyecto: si no logra ponerse de acuerdo consigo mismo sobre cuántos proveedores tiene, yo no voy a citar ese número para nada.
Para decidir me quedo con tres preguntas más modestas. ¿Está el proveedor que necesito? ¿Funciona la capacidad que usa mi agente? ¿Puedo operar esta versión sin exponer secretos? Una prueba contra mi ruta real vale más que discutir si el inventario correcto es 339, 351 o 352. Los números grandes envejecen mal.
Mi veredicto por ahora: sigo usándolo porque vuelve aburrida una parte del trabajo que debería serlo. No es una abstracción transparente: es infraestructura con acceso a mis secretos, así que fijé la versión y probé los tool calls que uso de verdad antes de confiarle algo sensible. “Una API, muchos modelos” es una buena interfaz mental, con tal de recordar lo que esconde: contratos distintos, cuotas ajenas y comportamientos que el gateway ordena pero no hace equivalentes. Por ahora me sirve. Si el ecosistema se asienta quizá deje de hacer falta, y si sigue fragmentándose se vuelve más necesario. No me apuraría a declarar ninguna de las dos.