Capítulo IA de la guía Neblla — neblla.ai.prompt(), presets, rutas de pago y entrega diferida. El contrato base está en core.txt; el criterio de cuándo usar Neblla, en empezar.txt.

IA integrada

Llamadas a la IA desde la app sin montar servidor propio, sin gestionar claves en backend, sin rate limiting manual. El proveedor lo eliges tú: Claude (por defecto), OpenAI o DeepSeek; neblla.ai.prompt() funciona igual con los tres.


const res = await neblla.ai.prompt('Estoy en una sala oscura con una puerta cerrada. ¿Qué hago?', {
  preset: 'pista'
});
console.log(res.text);

Firma: neblla.ai.prompt(text, { preset?, model?, provider?, userToken? }) (CLIENT) — devuelve Promise<{ text, usage, quota }>.

Proveedores y modelos

ai.provider elige el proveedor de la app: 'claude' (por defecto), 'openai' o 'deepseek', en Config > IA o con neblla_update_app({ ai: { provider, model, ... } }) (el objeto ai se reemplaza entero). Cada uno con sus modelos:

Cuando pagas tú, Neblla usa tu clave de ese proveedor: la de Claude se guarda en tu cuenta (Cuenta > Claude), las de OpenAI y DeepSeek en su tarjeta de Config > IA; todas cifradas. Sin clave guardada, la llamada responde no_developer_key. Los errores del proveedor llegan como claude_error:<tipo>, openai_error:<tipo> o deepseek_error:<tipo>.

El provider de la llamada solo vale cuando paga el usuario (con su propia clave de ese proveedor); con tu clave, otro proveedor que el de la app se rechaza con provider_not_allowed.

Presets

Los preset son prompts que el desarrollador configura en el dashboard (p. ej. el preset pista lleva el prefijo "Eres el narrador de una aventura. Da una pista sutil sin desvelar la solución..."). Editables en el dashboard sin redeploy.


// ❌ Mal — el prompt completo en cliente:
neblla.ai.prompt('Eres el narrador de una aventura. Da una pista... ' + userQuestion);

// ✅ Bien — preset en el dashboard, solo la pregunta del usuario:
neblla.ai.prompt(userQuestion, { preset: 'pista' });

El preset prefix se aplica server-side (en rutas con clave del dev) y queda privado.

Las tres rutas

Neblla elige la ruta según un solo ajuste de la app, ai.userTokenMode, no por cómo se llame a neblla.ai.prompt(). Vía MCP es neblla_update_app con ai: { userTokenMode: 'off' | 'browser' | 'server' }. Lee bien los valores — 'off' es el que paga el dev:

1. Browser-directo (userTokenMode: 'browser') — el usuario aporta su propia clave; la llamada sale del navegador al proveedor (Anthropic u OpenAI) directamente, sin pasar por Neblla. DeepSeek no se llama desde el navegador: con DeepSeek, las claves de los usuarios van por el modo server (pedir browser con DeepSeek responde invalid_ai_browser_provider). El dev no paga tokens, no consume cuota de Neblla, no requiere login. El preset prefix queda visible en el bundle del cliente. 2. Servidor con clave del dev (userTokenMode: 'off' — el valor por defecto; "off" significa sin token DEL USUARIO, o sea que se usa la clave del dev) — la llamada va por el servidor de Neblla con la clave de API del dev. Cada usuario tiene una cuota diaria de tokens, encendida por defecto (limitsEnabled, 10.000 tokens al día con tokensPerDay; pasarse responde quota_exceeded): así un usuario no te vacía la clave. Se apaga con limitsEnabled: false. Requiere login. El modelo del panel (ai.model) es el tope: el model de la llamada puede ser ese o uno más barato del mismo proveedor (Haiku < Sonnet < Opus; nano < mini < gpt-5; deepseek-chat < deepseek-reasoner); uno más caro se rechaza con model_not_allowed, sin llamar al proveedor. 3. Servidor con clave del usuario (userTokenMode: 'server') — el usuario aporta su clave (se pasa en el userToken del call), pero la llamada va por el servidor de Neblla para que el preset prefix quede privado. El dev no paga tokens. Requiere login.

En browser y server paga el usuario: una llamada sin userToken se rechaza con missing_user_token y nunca cae en la clave del dev. En esos modos el usuario elige el proveedor y el modelo, porque lo paga él.

Coste en cuota

Cada llamada por servidor consume 500 unidades de la cuota diaria de la app (los tokens del proveedor se facturan aparte, contra la clave del dev o del usuario). El modo browser no consume cuota. Tabla completa de cuotas en publicar.txt.

El consumo, a la vista

El panel (Funciones › IA y Dinero › Plan y uso) y neblla_get_app (en aiUsage) enseñan lo que lleva gastado la IA de la app: hoy, este mes (UTC) y los últimos 30 días, y día a día en el panel. Para cada periodo: calls (llamadas que respondió el proveedor), tokensIn y tokensOut, refused (rechazadas antes de llegar al proveedor, sin coste: refusedBy dice por qué, p. ej. quota_exceeded, no_developer_key, model_not_allowed, login_required), failed (el proveedor respondió un error; ya pagó su coste fijo: failedBy) y credits (lo que costó en la cuota de la app). Separa lo que va con tu clave (dev), con la clave de cada usuario a través de Neblla (user) y la revisión con IA de la comunidad (prescreen, también con tu clave). lifetime da los tokens y llamadas de siempre que contó la cuota, y creditsPerCall lo que cuesta una llamada. ai dice el proveedor (provider, providerName) y si tienes guardada tu propia clave para él (ownKey, nunca la clave): con ella el panel pone «Tu IA · OpenAI» (o el proveedor que sea); sin ella, «Falta tu clave de OpenAI» (no hay una clave de Neblla para la IA de una app: las llamadas responden no_developer_key); y si paga la clave de cada usuario (userTokenMode server o browser), «Clave de cada usuario · OpenAI». Lo que cobra Neblla es solo eso: los créditos de la cuota de la app, y euroPerCredit / eurosPerCall su precio en euros al precio del paquete de cuota (14.000 créditos por 10 €). A eso súmale lo que te cobre tu proveedor de IA por los tokens, en la clave que pagó: la tuya o la de cada usuario (ai.userTokenMode). Neblla no lleva una tabla de precios de los proveedores: mira la suya. El asistente de crear una app y «+ Añadir funciones» enseñan la misma cuenta en la tarjeta de la IA (POST /api/backend/ai-price, sin app: { creditsPerCall, euroPerCredit, eurosPerCall, eurosPer1000Calls, currency, pack }). El modo browser no pasa por Neblla y no se cuenta. Los días se guardan 90 días; un borrador (pre) cuenta para su app. Por HTTP, con la sesión del panel: POST /api/backend/apps/<appId>/ai-usage con { days? } (1–90, 30 por defecto).

Entrega diferida

Si la conexión se cae mientras la IA piensa, la respuesta se entrega cuando el usuario reconecta (dentro de 24h). El resultado llega por neblla.ai.on('reply', cb) (CLIENT), sin código especial.

Una consecuencia que conviene conocer: un await neblla.ai.prompt(...) que tarde más de 120 segundos ya ha rechazado con ai_timeout cuando llega la respuesta tardía, y esa respuesta se entrega solo por neblla.ai.on('reply'). Si tu app puede quedarse esperando dos minutos, escucha el evento además de hacer await.