Modo servidor
ai serve expone el enrutador como una API compatible con OpenAI. Usa los mismos inicios de sesión, claves, cuentas, cooldowns y fallbacks que el CLI.
ai serve # http://127.0.0.1:8080/v1
ai serve --host 0.0.0.0 --port 9000 --max-concurrent 4 --timeout 600
ai serve keys [list | add NAME | remove NAME]
API de administración
Desactivada por defecto. Configura un servidor en ejecución sin acceso al shell.
ai serve admin-keys add ops # clave propia, mostrada una sola vez
ai serve --enable-admin
curl -H "Authorization: Bearer omni-admin-..." http://127.0.0.1:8080/admin/health
| Ruta | Función |
|---|---|
GET/PUT /admin/config |
Modelos, orden de fallback (fallback_order) y routing |
GET/POST /admin/keys, DELETE /admin/keys/{id} |
Claves de proveedores. El id es openrouter u openrouter.work |
GET /admin/accounts |
Cuentas, inicio de sesión y cooldown |
GET/POST /admin/api-keys, DELETE /admin/api-keys/{nombre} |
Claves de los clientes de /v1 |
GET /admin/health |
Estado del servidor |
POST /admin/accounts/{cuenta}/login |
Inicia el inicio de sesión por suscripción: devuelve el enlace y el id del intento |
POST /admin/accounts/{cuenta}/login/complete |
Termina el inicio de sesión |
DELETE /admin/accounts/{cuenta}/login |
Cancela, con el id en X-Omni-Login-Attempt |
- Claves separadas: una clave de
/v1nunca abre/admin, ni al revés. Sin clave de administración,--enable-adminno arranca. - Red: desde fuera de esta máquina, exige HTTPS con proxy inverso, que debe definir
X-Forwarded-Proto.--admin-allow-httpdesactiva esta comprobación. Solo evita la exposición por error: quien llegue directo al puerto puede falsificar la cabecera, así que deja el puerto abierto solo para el proxy. En Docker, el puerto publicado cuenta como acceso externo. - Secretos: las respuestas muestran solo el final de las claves de proveedores. La excepción es la clave de cliente recién creada, mostrada una sola vez.
- Campos protegidos: el modo de permisos, las rutas de binarios y
config_dirdevuelven 403. - Cuidado: esta clave puede activar modelos de pago (
openrouter_paid) y cambiar claves de proveedores. En Docker, usaSMART_AI_ADMIN=1.
Inicio de sesión por la API. {cuenta} es primary y las otras cuentas Claude, codex, cursor, grok, o codex.NOMBRE para una cuenta extra. Un intento dura 10 minutos y cada cuenta acepta uno a la vez (409).
| Herramienta | Cómo terminar |
|---|---|
| Claude Code | Abre el enlace y envía {"attempt_id": "...", "code": "..."} con el código obtenido |
| Codex, Grok | Abre el enlace, escribe el user_code y envía {"attempt_id": "..."}. La respuesta es 202 hasta terminar |
| Cursor | Abre el enlace y envía {"attempt_id": "..."}. La respuesta es 202 hasta terminar |
Antigravity y las herramientas solo con clave devuelven 400. Los códigos y tokens no aparecen en respuestas ni en logs. La excepción es user_code, que hay que escribir en el navegador.
Escritura en paralelo
En los modos de escritura, los pedidos se ejecutan en paralelo, hasta --max-concurrent, sin tocar la carpeta original.
| Carpeta con git | Carpeta sin git | |
|---|---|---|
| Dónde trabaja | Worktree en una rama omni/<id>, desde el último commit |
Copia de la carpeta, hasta 1 GB |
| Resultado | Commit en la rama, indicada en X-Omni-Branch. El merge es tuyo |
Copia en ~/.local/share/smart-ai/runs/, indicada en X-Omni-Copy |
| Continuar | Envía X-Omni-Branch en el siguiente pedido |
Envía X-Omni-Copy en el siguiente pedido |
| Limpieza | El worktree se va al final. La rama queda hasta que la borres | La copia queda hasta que la borres |
- Sin cambios: la rama o copia nueva se descarta y el header no viene. En streaming, el header sale al inicio y puede apuntar a algo descartado.
- Fallo o timeout: lo hecho se conserva y el header viene en la respuesta de error. Tras una caída del servidor, los cambios se guardan en el siguiente inicio.
- Concurrencia: dos pedidos en la misma rama o copia reciben 409. Solo se pueden continuar ramas
omni/. - Cola: por encima del límite, el pedido espera hasta
--queue-waitsegundos (60), con hasta--queue-sizeen la cola (16). Solo entonces recibe 429. - Limitaciones: los cambios sin commit y los archivos ignorados por git, como
node_modules, no entran en el worktree. El aislamiento cubre archivos: puertos, bases de datos y otros servicios usados por los comandos aún pueden chocar, y un comando puede escribir fuera de la carpeta. La memoria también cuenta: cada pedido es un proceso de CLI. Los comandos git del propio servidor no ejecutan hooks nicore.fsmonitordel repositorio. Los filtros de git, como los de Git LFS, siguen ejecutándose: sirve solo repositorios en los que confías.
ai serve work --workdir CARPETA # lista
ai serve work remove ID --workdir CARPETA # muestra; con --yes, borra
ai serve work prune --older-than 30 --workdir CARPETA # también --merged; con --yes, borra
Sin --yes, no se borra nada. El comando solo alcanza ramas omni/ y copias de Omni. Un elemento en uso, o una copia cambiada hace menos de 15 minutos, se conserva.
Como servicio
ai serve --install-service [--host H] [--port P] [--mode M] [--workdir CARPETA]
ai serve --service-status
ai serve --uninstall-service
Arranca solo y se reinicia si falla, con launchd en macOS y systemd de usuario en Linux. En Windows, en contenedores y en WSL sin systemd, el comando avisa y no instala nada; ejecuta ai serve manualmente.
- Secretos: el archivo del servicio no guarda claves. Sin clave guardada, la instalación crea una y la muestra una sola vez. Fuera de
127.0.0.1, exige una clave guardada antes. - Entorno: solo
PATHy las carpetas de Omni llegan al servicio. Las claves que existen solo en tu shell no llegan: guárdalas conai --key. La instalación las lista, junto con los CLI que no encontró. - Carpeta y modo: el valor por defecto es
plan, en~/.local/share/smart-ai/serve.--mode yoloy sobrescribir un archivo que Omni no generó requieren--yes. - Logs:
~/.cache/smart-ai/serve.log, con rotación, yserve.out.log, que se vacía en cada instalación. - Linux: para arrancar con el sistema sin sesión abierta, ejecuta
loginctl enable-linger $USER. La instalación avisa, pero no lo hace por ti. - Actualización:
ai --updatereinicia el servicio. En instalaciones sin git, reinstala el servicio después.
Uso de la API
from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:8080/v1", api_key="omni-...")
client.chat.completions.create(model="omni-auto", messages=[{"role": "user", "content": "Olá"}])
En el primer inicio, el servidor crea una clave y la muestra una sola vez. Solo se guarda su hash. En un contenedor, también se puede definir SMART_AI_SERVER_KEY. No existe un modo sin autenticación.
| Ruta | Función |
|---|---|
POST /v1/chat/completions |
Respuesta completa o streaming (SSE) |
GET /v1/models |
omni-auto, que usa el enrutador, y omni/<herramienta> para cada herramienta configurada |
| Header de la respuesta | Significado |
|---|---|
X-Omni-Provider |
Herramienta que respondió |
X-Omni-Usage |
reported (informado por el proveedor) o estimated (estimado). No aparece en streaming |
X-Omni-Ignored-Params |
Parámetros recibidos e ignorados |
Seguridad:
- Por defecto, las herramientas se ejecutan en modo
plan, en una carpeta temporal, sea cual sea elSMART_AI_MODE. - Para crear, editar y ejecutar comandos:
ai serve --mode edits|auto|yolo --workdir CARPETA. La carpeta es obligatoria y nada pide aprobación. Cada pedido trabaja aislado. Quien tiene la clave puede cambiar la carpeta y, con comandos, alcanzar los inicios de sesión de las cuentas. - Solo lectura no impide leer archivos. Quien tiene la clave puede pedirle a una herramienta que lea archivos de esta máquina. Los MCP configurados también pueden estar disponibles. Trata la clave como acceso a tu cuenta.
- El valor predeterminado es
127.0.0.1. Para exponerlo en red, usa--hosty HTTPS con un proxy inverso. - Por encima del límite de conexiones (128 o más, según el sistema), la respuesta es 503. El inicio de cada pedido debe llegar en 30 segundos como máximo. En exposición pública, usa también los límites por origen del proxy.
- Compartir una instancia significa compartir las mismas cuentas y suscripciones. Revisa los términos de cada proveedor.
Limitaciones:
- Cuando el modo del servidor niega una acción y la herramienta termina con error, como hace Grok, la respuesta es
403 action_not_allowed. temperaturesolo se aplica en OpenRouter, DeepSeek y Grok por API. Los CLI la ignoran, y aparece enX-Omni-Ignored-Params.max_tokenses aproximado en los CLI (unos 4 caracteres por token).usagees estimado cuando el proveedor no informa el consumo.- Cada pedido puede consumir bastante cuota, porque los CLI de agente cargan su propio contexto. En Codex, un simple "OK" usó unos 19 mil tokens de entrada.
- En los CLI, el streaming entrega la respuesta de una vez, al final. Solo OpenRouter envía partes durante la generación, salvo cuando hay datos personales enmascarados.
- El fallback es transparente hasta la primera parte de la respuesta. Si el proveedor falla después, el cliente recibe un error.
tools/function calling solo en los proveedores de API (OpenRouter, DeepSeek y Grok con clave). El servidor nunca ejecuta las herramientas: la llamada vuelve a tu código. Otros modelos devuelven 400, porque los CLI de agente no pueden devolver la llamada, salvo con--tool-emulation. Conomni-auto, el orden es OpenRouter, DeepSeek y Grok. En OpenRouter, sinopenrouter_paid, solo modelos gratuitos. En streaming, la llamada llega de una vez, al final. Los argumentos fuera del schema hacen que el servidor pruebe el siguiente proveedor; solo se comprueba el núcleo de JSON Schema (type,required,enum,properties,items,additionalProperties).functions(formato antiguo) devuelve 400.- Experimental:
ai serve --tool-emulation(SMART_AI_TOOL_EMULATION=1en Docker) emulatoolsen Claude Code y Grok CLI, con sus herramientas propias desactivadas. El modelo escribe la llamada en JSON, y el servidor la valida y reintenta una vez, lo que gasta más cuota. Solo se aplica cuando no hay proveedor de API. Codex y Cursor quedan fuera, porque sus herramientas no se pueden desactivar. El modelo puede fallar más que en el modo nativo, los datos personales no se enmascaran, y el contenido del cliente puede imitar el formato. - Las imágenes devuelven error 400.
- El prompt llega a las herramientas como argumento de línea de comandos y queda visible en la lista de procesos de la máquina. El límite es de 100 KB por pedido.
- Los perfiles Claude heredados, que cambian el archivo de credenciales, limitan el servidor a un pedido a la vez.
Este texto viene del README del proyecto. Ver el original en GitHub