Saltar al contenido principal

0011 — Modelo por nodo IA, con claves de plataforma

Fecha: 2026-09-23 · Estado: aceptada

Contexto​

Todos los nodos IA de un flujo usaban el modelo del bot. Un flujo típico tiene pasos baratos (clasificar una intención, sacar una cédula) y uno caro (la conversación): con un solo modelo se paga el caro en todos, o se usa el barato también donde hace falta calidad.

El runtime solo ejecutaba OpenAI (SUPPORTED_PROVIDERS en supabase-bots.repository.ts).

Decisión​

  • Los nodos llm y extract_data pueden fijar su propio modelo (llm_provider, llm_model, llm_temperature). Vacío = el del bot.
  • Proveedores por nodo: OpenAI, Anthropic y Google.
  • Las claves de Anthropic y Google son de la plataforma (ANTHROPIC_API_KEY, GOOGLE_API_KEY), no de cada tenant. Xenpia paga y cobra por model_pricing, como ya hace con OpenAI.
  • Qué modelo se puede usar lo decide el catálogo ai_models (activos): lo que no esté ahí cae al modelo del bot. El flujo se guarda desde el frontend sin pasar por el backend, así que el control está al compilar el grafo, no al guardar.
  • El modelo del bot sigue siendo solo OpenAI, y los bots simples (base-agent.graph.ts) no cambian. Visión, transcripción, embeddings y especialistas siguen con la clave de OpenAI.
  • El asistente de flujos no elige modelos: deja el campo vacío.

Alternativas descartadas​

  • Claves por tenant, cifradas. Más superficie de seguridad (tabla de secretos, RLS, UI) sin necesidad actual. Se puede añadir después sin cambiar el formato del nodo.
  • Guardar ai_models.id en el nodo. Los uuid cambian entre DEV y PROD y romperían las plantillas; el model_code viaja igual en todos los entornos.
  • Abrir también el modelo del bot a otros proveedores. Cambiaría el comportamiento de bots en producción que hoy tienen un Claude elegido pero corren con GPT.

Consecuencias​

  • Un nodo nunca rompe por su modelo: proveedor desconocido, clave ausente o modelo retirado significan "usa el del bot" y un aviso en el log (y en el panel del editor).
  • Cada proveedor tiene sus diferencias de API (forzar herramienta, temperatura, salida estructurada, razonamiento). Están resueltas en chat-model-factory.ts; un modelo nuevo de Claude se trata como "reciente" por defecto, que es lo seguro.
  • Detalle técnico en Bots y LangGraph → Modelo por nodo.