Rylvo

Crea, ejecuta y gestiona agentes de IA en tu espacio de trabajo de Rylvo: bots, prompts, salvaguardas, bases de conocimiento, canales, pruebas y flujos.

Servidor MCP alojado

npx add-mcp 'https://rylvo.com/mcp'

Se instala en Claude Code, Codex, Cursor y más

Documentación

Referencia de la API de Rylvo

Un solo endpoint. Control agéntico completo. Ejecuta un turno de bot (prompts, guardarraíles, herramientas y recuperación de base de conocimiento) con tu propia clave de LLM, en minutos.

Inicio rápido

Haz tu primera llamada a la API en menos de un minuto. Necesitas un botId y una clave de API del panel de control. Las claves de API están incluidas desde el plan Lite; los espacios de trabajo Free y Starter no tienen ninguna, y en su lugar puedes poner un bot en un sitio web con el widget o compartirlo con un enlace de Beam.

curl -X POST https://rylvo.com/api/v1/bot-run \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "botId": "your_bot_id",
    "sessionId": "session_001",
    "message": "I can't access my account."
  }'

Modelo de acceso

Rylvo expone tres superficies. Saber cuál usar para qué evita confusiones al integrar un backend, conectar un editor de IA u operar la plataforma en el día a día.

Convención de rutas: las rutas de documentos de Firestore en esta referencia escriben {envRoot} como abreviatura de la raíz de espacio de trabajo-entorno — el subárbol environments/{environment} bajo organizations/{orgId} — donde {environment} es production o test. Las colecciones propiedad del entorno existen de forma independiente por entorno — el mismo ID lógico en Test y Production se refiere a dos documentos diferentes. Los datos de todo el espacio de trabajo (miembros, facturación, registro de auditoría) permanecen directamente bajo organizations/{orgId}.

REST públicoRuntime de backend

Llama desde tu backend con la clave de API de tu organización (Authorization: Bearer rylv_…). Esta es la superficie de runtime que despliegas en producción.

  • POST /api/v1/bot-run (alcance: respond)
  • POST /api/v1/kb/query (alcance: kb:read)
  • POST /api/v1/kb/documents (alcance: kb:write)
  • POST /api/v1/tests/gate (alcance: tests:read)
  • /health, /ready, /live, /flags (sin autenticación)

MCP / Editor de IAHerramientas de IA externas

Conecta Claude Code, Cursor, Windsurf, Zed o Codex directamente a Rylvo. OAuth 2.1 + PKCE, tokens con alcance de organización.

  • POST /mcp (HTTP Streamable)
  • Registro /oauth/* + intercambio de tokens
  • 167 herramientas para bots, prompts, KB, skills, conectores
  • Especificación OpenAPI 3.1 de los 3 endpoints REST públicos en /openapi.json

Panel de controlConfiguración y operaciones

Gestiona desde rylvo.com/dashboard. Muchas funciones también son accesibles a través de la superficie MCP / Editor de IA.

  • Bots, Prompts, Guardarraíles, Base de Conocimiento
  • Arquitecto de Espacio de Trabajo, Chat de Bot, Pruebas de Bot
  • Casos Extremos, Red Team, Automatización, Informes
  • Control de Misión, Evolución de Agentes, Skills, MCP Hub
  • Facturación, Equipo, Claves de API, Inteligencia de Compilación

Las secciones siguientes marcadas como Solo panel de control aún no tienen un endpoint REST público dedicado. Siguen siendo totalmente funcionales dentro del panel de control, a través de la superficie MCP / Editor de IA, y su comportamiento afecta al runtime /api/v1/bot-run.

Entornos y versiones

Cada espacio de trabajo tiene dos entornos: Test y Production. Construyes y experimentas en Test, luego promueves una versión congelada y versionada a Production. La configuración, los datos, la analítica, los traces y las claves de API están aislados por entorno — el mismo ID lógico en Test y Production se refiere a dos documentos diferentes (consulta Modelo de acceso para la convención de rutas {envRoot}). Hay una visión general dedicada de Entornos y versiones si quieres el recorrido por el producto.

Testeditable

Una copia totalmente editable de tu espacio de trabajo. Itera sobre bots, prompts, guardarraíles, flujos, skills, conocimiento y conectores contra modelos reales. El tráfico de Test nunca toca la configuración o los datos de Production.

Productionde solo lectura

Lo que alcanzan tus clientes. La configuración promovible es de solo lectura — solo cambia cuando activas una versión o reviertes una. Una organización que nunca ha promovido sigue sirviendo su configuración heredada hasta que se activa la primera versión.

El ciclo de vida de las versiones

  1. Congela un candidato — captura la configuración actual de Test en un candidato de versión inmutable (un manifiesto versionado de artefactos). Test sigue siendo editable.
  2. Revisa el diff y los requisitos — mira qué cambió frente a Production en vivo (añadido / cambiado / eliminado / sin cambios, agrupado por familia de artefactos). Requisitos opcionales: aprobación de dos personas (el creador no puede aprobar su propio manifiesto) y una ejecución de pruebas en verde.
  3. Activa Production — el puntero activo cambia atómicamente, pero solo después de que cada artefacto del manifiesto esté verificado. La generación del entorno se incrementa en uno.
  4. Revierte si es necesario — cada versión activada es inmutable y se conserva. Apunta Production de nuevo a cualquier versión anterior y el tráfico de runtime cambia inmediatamente.

También puedes actualizar Test desde la versión activa de Production (el modo seguro preserva las ediciones divergentes de Test) o restablecer Test por completo. Cada operación destructiva se guarda en un checkpoint primero. Gestionar versiones (congelar, activar, revertir) requiere un rol de administrador o propietario.

Seleccionar un entorno a través de la API

Envía el encabezado X-Rylvo-Environment para elegir el entorno de una solicitud. Su valor es production o test. Las claves de API también están limitadas a un entorno, por lo que una clave de Test nunca puede autenticarse contra datos de Production. El mismo bot responde desde la configuración correcta y escribe en el almacén de datos correcto para el entorno seleccionado.

curl -X POST https://rylvo.com/api/v1/bot-run \
  -H "Authorization: Bearer rylv_…" \
  -H "X-Rylvo-Environment: test" \
  -H "Content-Type: application/json" \
  -d '{"botId": "…", "message": "hello"}'

Omitir el encabezado usa Production por defecto. Consulta Autenticación y Claves de API para saber cómo se limitan las claves.

Marca de agua de datos de Test

Los datos exportados desde Test llevan una marca de agua para que un conjunto de datos de Test nunca se confunda con registros reales de clientes downstream. Las exportaciones de Production no llevan marca de agua; las de Test siempre la llevan, y la procedencia del entorno viaja con los datos después de que salen de Rylvo.

Autenticación

Todas las solicitudes a la API requieren una clave de API enviada en el encabezado X-API-Key. Crea claves desde tu panel de control.

X-API-Key: rylv_abc123...

Seguridad: nunca expongas claves de API en código del lado del cliente. Siempre llama a la API desde tu backend.

BotsSolo panel de control

Cada agente en tu espacio de trabajo se construye, configura y despliega desde Panel de control → Bots. La barra lateral lista primero los grupos de agentes y después los bots independientes, mostrando cada uno el modelo en el que se ejecuta y si está activo.

Nuevo bot — desde cero

  • Nombre, avatar generado y una descripción de para qué sirve el agente
  • Modelo, elegido una vez de cada proveedor del que tengas una clave (consulta BYOK abajo)
  • Alternancias de entrada de imagen y audio
  • Cuántos mensajes recientes relee el bot en cada turno
  • Opcionalmente, coloca el nuevo agente directamente en un grupo

Desde una plantilla

  • Catálogo de planos validados, buscables y filtrables por categoría
  • Primero bots de agente único, después pipelines multiagente
  • Elegir uno abre un paso de personalización — no se crea nada hasta que lo terminas
  • Lo que obtienes es un bot totalmente editable, no un ajuste preestablecido bloqueado

Un bot solo es accesible a través de la API una vez que está activo y tienes una clave de proveedor para su modelo. Agrupa varios bots para que puedan pasarse trabajo entre sí — consulta Grupos de agentes.

Claves de proveedor (BYOK)Solo panel de control

Cada chat de bot en Rylvo se ejecuta con tu propia clave de proveedor de LLM. Rylvo enruta la llamada en el servidor y registra un trace completo para la observabilidad, pero añade cero margen en los costes de tokens — pagas a tu proveedor de LLM directamente. Gestiona las claves en Configuración → Claves de proveedor de LLM.

Chat de bot, chat de grupo, pruebas de bot

Enruta a la clave de proveedor del cliente. Requiere la clave directa del proveedor correspondiente (p. ej. Anthropic para modelos anthropic/*) o una clave universal de OpenRouter. Sin una clave, la interfaz bloquea el chat y muestra una llamada a la acción. Los espacios de trabajo nuevos comienzan con una clave de prueba de 14 días con $2 de uso de IA, para que puedan chatear antes de añadir una.

Arquitecto de espacio de trabajo

Se ejecuta con tu propia clave de proveedor como todo lo demás. Durante la prueba Pro de 14 días se ejecuta con los $2 de uso de IA que Rylvo incluye, para que puedas construir antes de añadir una clave. Los bots que crea también necesitan una clave una vez que termina la prueba.

Orden de resolución de claves

  1. Auto (predeterminado) — la clave nativa del proveedor del modelo cuando se añade (directa a p. ej. api.anthropic.com), si no, tu clave de OpenRouter.
  2. Siempre OpenRouter — cada chat se ejecuta con tu clave de OpenRouter, incluso cuando existe una clave directa.
  3. Solo claves nativas — OpenRouter nunca se usa; los modelos sin clave directa están bloqueados.
  4. Anulación por bot disponible en el Hub de Bots. Cuando ninguna clave puede servir un modelo, el chat de la interfaz nombra exactamente qué clave(s) lo desbloquearían.

Proveedores compatibles

  • OpenRouter — universal, cubre todos los modelos excepto los de Groq y GLM 4.7 FlashX
  • OpenAI — openai/*
  • Anthropic — anthropic/* (adaptador nativo de Messages API)
  • Google Gemini — google/* (adaptador nativo generateContent)
  • DeepSeek — deepseek/*
  • xAI (Grok) — x-ai/*
  • Kimi / Qwen / GLM — moonshotai/*, qwen/*, z-ai/* (bots antiguos: kimi/*, zhipu/*); las claves de cualquiera de las dos regiones funcionan
  • Mistral — mistralai/*
  • Groq — groq/* (necesita su propia clave; no está en OpenRouter)
  • MiniMax, Meta, Cohere, NVIDIA, Xiaomi, ByteDance, Tencent, StepFun, Inception, Upstage, IBM — solo clave de OpenRouter
  • La lista completa de modelos, con precios y la clave en la que se ejecuta cada uno, está en el selector de modelos del panel de control (Bots → Editar → Modelo).

Acceso y seguridad

  • Escritura/eliminación restringida a administradores de la organización.
  • Lectura permitida para todos los miembros de la organización para que los operadores puedan chatear con los bots.
  • Las claves nunca salen de Firestore + el manejador de rutas — nunca se exponen al HTML de la página.
  • La rotación de claves restablece automáticamente el estado de verificación.

Verificada al guardar

Cada clave se comprueba con su proveedor antes de almacenarse — un ping de 16 tokens (< $0.001). Una clave que el proveedor rechaza nunca se guarda, y la página muestra exactamente lo que respondió el proveedor. Usa Test para volver a comprobar una clave guardada en cualquier momento y Test all para reverificar todas las claves a la vez.

Etiquetado de bots (obligatorio)

Requerido: cada solicitud de runtime debe incluir un botId (o un groupId para un grupo de agentes). Las solicitudes sin ninguno de los dos se rechazan con un error 400.

Los bots son la unidad organizativa principal para tu uso de la API. Cada bot representa un agente o caso de uso distinto (p. ej. "Bot de triaje de soporte", "Bot de calificación de ventas"). Crea bots desde tu panel de control y luego usa el ID del bot para etiquetar cada llamada a la API.

Cómo funciona

1

Crea un bot

Ve a Panel de control → Bots → Nuevo bot. Dale un nombre y una descripción.

2

Copia el ID del bot

Cada bot obtiene un ID único. Cópialo de la tarjeta del bot.

3

Etiqueta cada solicitud a la API

Incluye "botId": "tu_id_de_bot" en el cuerpo de la solicitud.

4

Consulta la analítica por bot

Filtra traces, analítica y facturación por bot.

Solicitud de ejemplo con botId

{
  "botId": "bot_abc123def456",
  "sessionId": "sess_001",
  "message": "I can't access my account."
}

Beneficios del etiquetado de bots

Analítica por bot

Consulta métricas, latencia y tasas de error por bot

Agrupación de traces

Filtra y busca traces por nombre de bot

Asociación de claves

Vincula claves de API a bots específicos

Control de acceso

Gestiona permisos por bot

Playground de chat de botSolo panel de control

Prueba el comportamiento de un bot de extremo a extremo antes de apuntar tráfico de producción hacia él. El playground en /dashboard/bots/[botId]/chat ensambla el runtime completo exactamente como lo hace /api/v1/bot-run: prompts de sistema, placeholders, guardarraíles, conectores, conexiones de KB y reglas de evolución.

Cada turno captura

  • IDs de prompt activos + placeholders resueltos
  • Guardarraíles evaluados (y cuáles se activaron)
  • Conectores invocados + cuerpos de solicitud/respuesta
  • Reglas de evolución inyectadas en el prompt de sistema
  • Paso de flujo activo + transiciones evaluadas (si hay un flujo adjunto)
  • Uso de tokens + coste (se ejecuta con tu propia clave BYOK)

Bueno para

  • Reproducir un fallo desde una reproducción de trace
  • Iterar sobre un prompt antes de promoverlo a activo
  • Verificar que un nuevo guardarraíl realmente se activa
  • Comparar dos bots lado a lado (/dashboard/bots/[botId]/compare)

Cada turno del playground muestra la pila de prompts, las decisiones de guardarraíles, las llamadas a conectores, las reglas de evolución aplicadas, el paso de flujo activo (si hay un flujo adjunto), los susurros del operador, el uso de tokens y el coste — todo junto al mensaje en sí.

Pruebas de botSolo panel de control

Define casos de prueba reutilizables por bot y ejecútalos bajo demanda o mediante un horario de Automatización. Gestiona en /dashboard/bots/[botId]/tests.

Un caso de prueba especifica

  • Mensaje de entrada (de un solo turno) o una conversación multi-turno con guion
  • Texto de salida esperado / comportamiento esperado
  • Salvaguardas que deberían o no deben activarse
  • Comprobaciones de las respuestas: palabras que deben o no deben usar, un patrón, JSON con una forma determinada, un número dentro de un margen, redacción cercana a una respuesta de referencia
  • Comprobaciones de lo que hizo el bot: las herramientas que llamó (o que nunca debe llamar, o en qué orden), si usó la base de conocimiento, la rapidez de cada respuesta, el costo de la conversación
  • structured_state opcional pre-rellenado

Una ejecución de prueba produce

  • Aprobado/reprobado por caso con diferencias frente a las expectativas
  • Uso de tokens y costo de toda la ejecución
  • Enlaces de seguimiento completos para cada caso (para depuración)
  • Un resumen que puedes adjuntar a un informe o canal de alertas

La forma de calificar una prueba es tuya. Pruebas → Calificación establece la nota de aprobación (70 a menos que la cambies), barreras más estrictas para una prioridad o tipo de prueba, qué puntúa el juez de IA y cuánto cuenta cada parte — para cada bot, o para uno solo. La prueba recalifica la última ejecución del bot antes de que guardes, y cada ejecución registra la calificación bajo la que se juzgó, de modo que las ejecuciones calificadas de forma distinta nunca se comparan como si nada hubiera cambiado. Cada plan puede verlo; cambiarlo es Pro, para administradores y propietarios.

Las comprobaciones son reglas estrictas. Cada una reprueba la prueba por sí sola, sin importar lo que puntúe el juez de IA, y una comprobación sin nada que leer — un tiempo de respuesta no registrado, un bot sin base de conocimiento — reprueba y lo dice en lugar de aprobar en silencio. La similitud compara redacción, no significado: úsala cuando exigir una frase exacta sea incorrecto, pero la respuesta debería leerse de forma muy parecida.

Un fallo se convierte en prueba. En un caso límite, o en cualquier respuesta en Trazas, "Añadir como prueba" abre el editor de pruebas ya rellenado: los mensajes del cliente hasta donde salió mal, lo que debería haber ocurrido, y una comprobación que evita que vuelva a aprobar. Guárdala y el mismo error no puede publicarse dos veces — el caso límite lista las pruebas creadas a partir de él y las ejecuta.

Los conjuntos de pruebas mantienen fija una suite. Guarda las pruebas que importan — por ejemplo, las que deben aprobar antes de un lanzamiento — como un conjunto con nombre. Cada versión congela una copia de cada prueba incluida, de modo que "la suite de lanzamiento, versión 3" ejecuta las mismas conversaciones contra las mismas expectativas en marzo y en diciembre, sin importar cómo se hayan editado las pruebas desde entonces. Cada versión marca cuáles de sus pruebas han cambiado o se han eliminado desde entonces, y cada ejecución indica qué versión ejecutó.

Las pruebas viajan como archivos. Descarga las pruebas de un bot, o una versión de un conjunto, como CSV (una prueba por fila, para una hoja de cálculo), JSON Lines o JSON — e importa cualquiera de ellas de vuelta. Una importación se comprueba antes de añadir nada, y un archivo que no puede leerse indica qué fila y por qué.

Hasta qué punto confiar en el juez (Enterprise). Los revisores dan su propio veredicto sobre los resultados juzgados — aprobado, parcial o reprobado, y una puntuación para cualquier parte si lo desean. Pruebas → Calificación muestra entonces con qué frecuencia el juez de IA coincide con ellos (con la kappa de Cohen, de modo que la coincidencia por azar no cuenta), si es más a menudo demasiado generoso o demasiado estricto, y qué parte puntúa más lejos de tus revisores. Probar un cambio de calificación indica si el juez coincidiría más con ellos, y un juez de referencia fijado marca cualquier ejecución juzgada de forma diferente — sus puntuaciones no se comparan con la tendencia.

Un lanzamiento espera hasta que las pruebas aprueben. Activado en Pruebas → Puerta de lanzamiento, un lanzamiento a Producción espera hasta que cada bot incluido supere la puerta en una ejecución contra ese lanzamiento exacto, y Revisar y lanzar nombra las pruebas que no aprobaron, cada una con un enlace a su resultado. A menos que lo cambies, una ejecución supera la puerta cuando ninguna de sus pruebas reprueba y al menos una aprueba. En Enterprise decides qué significa aprobar — una tasa de aprobación, cada prueba crítica, una ejecución de un conjunto de pruebas con nombre, el acuerdo del juez con tus revisores — y tu propio pipeline de CI pregunta a la misma puerta con POST /api/v1/tests/gate y una clave API con el alcance tests:read, fallando el despliegue a menos que diga aprobado.

Los casos de prueba fallidos pueden convertirse en Casos límite para que el motor los rastree a través del bucle detectar → clasificar → corregir → verificar.

Grupos de agentes (equipos multi-bot)Solo panel

Compón varios bots en un equipo donde un bot enruta, delega y fusiona resultados de especialistas. Útil para flujos de trabajo que abarcan dominios (p. ej., facturación + soporte técnico) o requieren borradores en paralelo.

Modos de grupo

  • Enrutador — un bot elige al mejor especialista por turno
  • Secuencial — los bots se ejecutan en un pipeline fijo
  • Paralelo — los bots se ejecutan simultáneamente, un fusionador resume
  • Round-robin — alterna bots entre turnos

Cada miembro contribuye

  • Sus propios prompts, salvaguardas, conectores, alcance de KB
  • Un rol/persona adjunto (p. ej., billing_specialist)
  • Su propio seguimiento — el seguimiento del grupo los enlaza a todos

Los chats de grupo registran qué bots miembros contribuyeron a cada turno y cómo se tomaron las decisiones de enrutamiento, para que puedas depurar quién dijo qué y por qué.

Decisiones tipadas en grupos: un enrutador cuyas reglas leen solo la intención (sin otros hechos, sin pass_fields) es despachado por TypeSafe Jev; otros enrutadores mantienen el clasificador LLM. Un fan-out con la fusión vote hace que Jev elija la mejor rama, y la respuesta de esa rama se devuelve exactamente como se escribió — anteriormente un LLM la re-tipaba. Ambos recurren a la ruta LLM si Jev no puede responder.

Endpoints

MétodoRutaDescripción
POST/api/v1/bot-runEjecuta un turno de un bot o grupo de agentes (alcance: respond)
POST/api/v1/kb/queryConsulta una conexión de base de conocimiento (alcance: kb:read)
POST/api/v1/kb/documentsSube documentos a una fuente de KB (alcance: kb:write)
POST/api/v1/tests/gate¿La ejecución de pruebas de un bot supera la puerta de lanzamiento? Para CI (alcance: tests:read)
GET/healthVitalidad (proceso activo)
GET/readyDisponibilidad (puede manejar solicitudes)
GET/liveSonda de tiempo activo
GET/flagsBanderas de despliegue

El catálogo de modelos, trazas, análisis y CRUD de conectores se gestionan desde el panel y la superficie MCP / Editor de IA — no se exponen como endpoints REST públicos hoy.

Runtime (Turno de bot)

POST /api/v1/bot-run es el núcleo de Rylvo. Envía un mensaje (más sesión e historial opcionales) y el motor ejecuta un turno agéntico completo, devolviendo la respuesta del asistente con telemetría completa. Se ejecuta con tu propia clave BYOK.

Ensamblaje de prompts

Prompts del bot + habilidades

Salvaguardas

Bloquear / reescribir / escalar

Herramientas y conectores

Llamadas a herramientas en vivo

Recuperación de KB

Respuestas fundamentadas

Formato de solicitud

{
  "botId": "bot_abc123def456",
  "sessionId": "sess_001",
  "message": "The display shows error E42.",
  "conversationHistory": [
    { "role": "user", "content": "Hi, my device won't start." },
    { "role": "assistant", "content": "I can help. What does the screen show?" }
  ],
  "endUserExternalId": "user_8842",
  "endUserDisplayName": "Jordan Lee",
  "channel": "api"
}

Campos obligatorios

CampoTipoDescripción
botIdstringIdentificador del bot (desde Panel → Bots). Se requiere botId o groupId.
messagestringEl mensaje actual del usuario final

Campos opcionales

CampoTipoDescripción
groupIdstringIdentificador del grupo de agentes (ejecuta un equipo multi-bot en lugar de un solo bot)
conversationHistoryobject[]Turnos anteriores: { role: 'user' | 'assistant', content }
sessionIdstringIdentificador de conversación/sesión; se devuelve como conversationId
endUserExternalIdstringIdentificador estable del usuario final en tu espacio de nombres (≤256). Requerido para nombre mostrado / correo.
endUserDisplayNamestringNombre legible por humanos mostrado en Trazas (≤200)
endUserEmailstringCorreo del usuario final para transferencia de soporte (validado)
known_factsobject[]Lo que ya sabes sobre la persona: [{ key, value }], como máximo 20. key es una clave de campo de Recopilación de datos del bot (minúsculas, ≤64, enviada una vez); value es texto ≤1000. Se usa solo para que el bot no vuelva a preguntar; nunca se guarda; debe ser una respuesta válida para ese campo. Una lista malformada es un 400.
channelstringapi (predeterminado) | widget | whatsapp | slack | unknown
modelstringModelo de anulación (p. ej., openai/gpt-4.1-mini, anthropic/claude-sonnet-4.6)
maxTokensnumberMáximo de tokens de salida para este turno
temperaturenumberTemperatura de muestreo para este turno
disableToolsbooleanDesactiva las llamadas a herramientas/conectores para este turno
maxToolIterationsnumberLimita las iteraciones del bucle de llamadas a herramientas
responseFormatobjectSalida estructurada: {type:"json_object"} o {type:"json_schema", json_schema:{...}} — restringe la respuesta final (solo modelos compatibles con OpenAI)
streambooleanTransmisión de tokens mediante Server-Sent Events: eventos de token mientras se genera la respuesta, luego un evento de resultado final con el cuerpo JSON estándar (solo bot único)

Cabecera opcional Idempotency-Key: <uuid> — reenviar la misma clave para la misma clave API reproduce la respuesta almacenada (sin doble facturación / sin re-ejecutar herramientas).

Formato de respuesta

{
  "response": "I've logged error E42. Let me pull up the matching fix steps.",
  "conversationId": "sess_001",
  "runId": "run_8f3a21c9",
  "model": "openai/gpt-4.1-mini",
  "latencyMs": 1840,
  "tokens": { "prompt": 1203, "completion": 88, "total": 1291 },
  "guardrails": {
    "inputBlocked": false,
    "outputBlocked": false,
    "outputRewritten": false,
    "blockedBy": null,
    "escalated": false,
    "escalatedBy": null
  },
  "toolCalls": [],
  "augmentation": { "rulesApplied": 0, "skillsMatched": 1, "episodicRecallCount": 0, "userModelApplied": false },
  "sessionEnd": null,
  "kb": null,
  "pendingApproval": null
}

Campos clave de respuesta

CampoDescripción
responseEl texto de respuesta del asistente para mostrar al usuario
runIdIdentificador único de este turno — encuéntralo en Panel → Trazas
conversationIdDevuelve el sessionId de la solicitud
modelEl modelo que realmente sirvió el turno
latencyMsLatencia del turno en el servidor (ms)
tokensConteos de tokens { prompt, completion, total }
guardrails{ inputBlocked, outputBlocked, outputRewritten, blockedBy, escalated, escalatedBy } — inputBlocked = el mensaje fue rechazado antes de que el modelo se ejecutara; outputBlocked = la respuesta fue bloqueada después de generarse
toolCallsHerramientas invocadas en este turno (nombre, disposición, latencia, costo)
sessionEndSe establece cuando el bot terminó la sesión ({ reason, summary? })
kbTelemetría de fundamentación de KB incl. citas (cuando se ejecutó la recuperación)
pendingApprovalPresente cuando una llamada a herramienta espera aprobación del operador

Flujos

Los flujos son un grafo de conversación guiado/estricto opcional adjunto a un bot (bot.flowId) o a un grupo de agentes (gestionado por panel/MCP) que da forma a su comportamiento en runtime — no forman parte de la solicitud o respuesta /api/v1/bot-run. Un flujo es un conjunto de pasos: el motor mantiene un puntero por sesión al paso actual, inyecta el objetivo de ese paso en el prompt del sistema, limita sus herramientas y avanza cuando se dispara una transición.

Un paso lleva

goal Inyectado en el prompt del sistema como instrucción de este paso

collect Información que pedir antes de continuar — el flujo conserva lo que el bot no puede guardar

allowed_tools Estricto: las únicas herramientas ofrecidas. Guiado: nombradas al bot como orientación

transitions Bordes al siguiente paso, evaluados cada turno

Tipos de transición

always Se dispara incondicionalmente

data_complete Todos los campos de recopilación del paso están reunidos

intent La intención clasificada coincide

condition Una expresión sobre los campos (null hasta que se proporciona), detalles rastreados como estado.<key>, y turn_count / step_turns es verdadero

tool_result Una herramienta nombrada se ejecutó con éxito este turno

Cómo se clasifica la intención: cuando un paso tiene transiciones intent, TypeSafe Jev elige una de las intenciones de ese paso. Una transición se toma solo cuando Jev está al menos 50% seguro; de lo contrario, el flujo permanece en su paso. Si Jev no puede responder, el clasificador LLM anterior en el modelo del bot decide.

Etapas del flujo de trabajo del bot (bot.workflowId, separadas de los flujos): cuando el flujo de trabajo define dos o más etapas, el motor elige la etapa actual cada turno a partir de los identificadores de etapa propios de ese flujo de trabajo y puntúa el sentimiento del usuario de -1 (furioso) a 1 (encantado) en la misma solicitud de Jev. Las condiciones sentiment < … en las reglas de escalado del flujo de trabajo ahora se comparan contra esa puntuación; antes, el motor usaba una constante 0.

Manejo de errores

400

Solicitud no válida

JSON malformado, mensaje faltante, botId/groupId faltante o forma de campo incorrecta.

401

Error de autenticación

Clave API faltante o no válida.

403

Prohibido

La clave carece del alcance, está vinculada a un bot diferente, o la organización está suspendida.

404

No encontrado

Bot, grupo o recurso no encontrado.

429

Límite de velocidad

Límite de velocidad por clave excedido — consulta la cabecera Retry-After.

502 / 503

Motor no disponible

El motor de runtime es inalcanzable, no está configurado o está temporalmente deshabilitado. Engine-side failures (e.g. a missing BYOK provider key) pass through the engine's status code with its own code / error.

// Error response format
{
  "error": "One of \`botId\` or \`groupId\` is required.",
  "code": "invalid_request"
}

Ejemplo de múltiples turnos

Mantén un sessionId estable y pasa la transcripción en curso en conversationHistory para que el bot tenga contexto.

Turno 1 - El usuario reporta un problema

curl -X POST https://rylvo.com/api/v1/bot-run \
  -H "Authorization: Bearer YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"botId":"bot_abc123","sessionId":"conv_001","message":"My subscription renewal failed."}'

Turno 2 - El usuario proporciona el número de pedido (incluye turnos anteriores)

curl -X POST https://rylvo.com/api/v1/bot-run \
  -H "Authorization: Bearer YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"botId":"bot_abc123","sessionId":"conv_001","message":"My order is ORD-98765-XYZ","conversationHistory":[{"role":"user","content":"My subscription renewal failed."},{"role":"assistant","content":"I can help — what is your order number?"}]}'

Turno 3 - El usuario quiere escalar

curl -X POST https://rylvo.com/api/v1/bot-run \
  -H "Authorization: Bearer YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"botId":"bot_abc123","sessionId":"conv_001","message":"I want to talk to a real person."}'

Webhooks

/api/v1/bot-run es síncrono: el resultado del turno se devuelve en la respuesta. Para notificaciones asíncronas (escalaciones, cambios de etapa, fallos de verificación, resultados de herramientas), registra un Event Connector (Dashboard → Connectors, o a través de la superficie MCP). Rylvo hace POST de cada evento suscrito a tu endpoint con el método de autenticación y el secreto de firma HMAC que configures en el conector. Los tipos de eventos suscribibles se enumeran en Connectors.

Límites de tasa

POST /api/v1/bot-run tiene límite de tasa por clave de API: 60 solicitudes/minuto por defecto, modificable por clave (Dashboard → API Keys). El chat de bot iniciado desde el dashboard usa tu propia clave BYOK y NO tiene límite de tasa por Rylvo; las funciones de IA de la plataforma (Agent Evolution, Self-Improving Prompts, Red Team) también se ejecutan con tu propia clave de LLM y son gratuitas; consulta pricing.

PlanMensualRespuestas del bot
Free$0Uso justo
Lite$40Uso justo
Pro$100Uso justo · guía ≈ 100K/mes
EnterprisePersonalizadoEstablecido en tu contrato

Las respuestas del bot son de uso justo: nada las mide ni las cobra por plan, y las cifras anteriores son guías, no límites.

Encabezados de límite de tasa en cada respuesta: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset y Retry-After en 429.

Facturación y uso

El modelo de facturación de Rylvo es simple: un plan de suscripción mensual cubre la capacidad de la plataforma (bots, prompts, guardrails, fuentes de KB, conectores, observabilidad), y cada función de IA se ejecuta con tu propia clave de LLM (BYOK) de forma gratuita.

Tu clave de LLM (BYOK)

Cada función de IA — gratuita

Chat de bot, Workspace Architect, Agent Evolution, Self-Improving Prompts, Edge Case Engine, Red Team, broadcasts: todo se ejecuta con tu propia clave de proveedor sin margen. Sin créditos de IA, sin margen. La indexación de la base de conocimiento está incluida hasta el límite de tu plan. Durante la prueba Pro de 14 días, se incluyen hasta $2 de uso de IA; después de eso, todo es tu clave.

Monedero prepago (opcional)

Exceso de almacenamiento de conversaciones

Un monedero prepago en USD cubre solo el exceso de almacenamiento de conversaciones más allá del grupo incluido en tu plan y los complementos de retención financiados por el monedero. Dodo cobra las suscripciones del plan por separado. Recarga desde $5 en Dashboard → Billing. Las funciones de IA nunca se descuentan de él.

Planes de suscripción

PlanPrecioLímites principalesNotas
Free$01 bot · retención de trazas de 7 díasTu propia clave de IA, sin margen; las respuestas del bot son de uso justo
Lite$403 bots · retención de trazas de 14 díasKit para constructores individuales; sin suite avanzada de IA ni broadcasts
Pro$10025 bots · retención de trazas de 90 díasSuite avanzada de IA + broadcasts
EnterprisePersonalizadoNegociadoDPA personalizado, revisión de seguridad, contacto designado (siguiente día hábil, no es un SLA)

Suite avanzada de IA (Pro+): Agent Evolution, Self-Improving Prompts, Edge Case Engine, Red Team, Mission Control, Exportación de registro de auditoría, Bloques de políticas personalizados. Broadcasts (Pro+): campañas salientes multicanal. Lite conserva Advanced Analytics, BYODB, Test Suites, MCP Hub, Webhooks y Build Intelligence. Asientos (Pro+): Pro incluye tu asiento; cada compañero adicional cuesta $40/asiento/mes ($32 en facturación anual), hasta 100 asientos en total.

Prueba, reembolsos e impuestos

  • Prueba. Cada nuevo espacio de trabajo comienza en Pro durante 14 días con hasta $2 de uso de IA (otorgado una vez que tu correo esté verificado), sin tarjeta. Cuando termina, el espacio de trabajo pasa a Free (1 agente) a menos que actualices, y el uso de IA de la prueba termina con él, así que añade tu propia clave de proveedor para que tus agentes sigan respondiendo. Con más de un agente, tienes 7 días para elegir cuál conservar (o actualizar); después, los extras se pausan, nunca se eliminan, y cuando actualices se reactivan si todos caben en el límite de agentes de tu nuevo plan (de lo contrario, eliges cuáles se ejecutan). Los agentes demo que no hayas hecho tuyos se eliminan al final de la prueba; uno que hayas cambiado, implementado o usado con personas reales es tuyo para conservar.
  • Reembolsos. Envía un correo a contact@rylvo.com dentro de los 14 días posteriores a tu primer pago en un plan de pago (mensual o anual) y te reembolsamos el importe completo a través de Dodo Payments, una vez por cliente, a menos que la cuenta haya sido suspendida por violar los Términos. Las renovaciones, asientos, otros complementos y recargas de monedero comprados después no son reembolsables, excepto cuando la ley lo exija o según los términos del comprador de Dodo Payments. Terms: Billing & Payment.
  • Moneda e impuestos. Los precios están en USD. Dodo Payments es el comerciante de registro y el GST de India se añade al finalizar la compra.
  • Intervalo de facturación. Mensual o anual en Lite y Pro (anual es aproximadamente un 20% más bajo). Starter es solo mensual.

Costo de tokens (BYOK — informativo)

Los turnos del bot se ejecutan con tu propia clave de proveedor, por lo que Rylvo no factura por token: pagas a tu proveedor de LLM directamente. Cada turno aún registra su costo de tokens en la traza para observabilidad y seguimiento del presupuesto por bot:

trace.cost_usd = (input_tokens  × model.price_per_input_token)
               + (output_tokens × model.price_per_output_token)

Encabezados de respuesta en /api/v1/bot-run

EncabezadoSignificado
X-RateLimit-LimitCapacidad de solicitudes por minuto de la clave
X-RateLimit-RemainingSolicitudes restantes en la ventana de límite de tasa actual
X-RateLimit-ResetSegundos Unix cuando se restablece la ventana
Retry-AfterSegundos a esperar antes de reintentar (en 429)
Idempotent-Replaytrue cuando se reproduce una respuesta idempotente almacenada

Estado de suscripción solo en Dashboard

La suscripción de facturación es un documento único en Firestore. Las transiciones de estado están impulsadas por webhooks del proveedor más un cron de ciclo de vida por hora. Solo el estado downgraded desactiva las funciones de pago. Los IDs de planes heredados (starter es un alias antiguo de Pro, además de growth y scale) se migran en tiempo de lectura; el plan Starter actual tiene el ID solo.

Puertas de plan

  • requireFeature — función bloqueada o degradada
  • requireQuota — uso ≥ límite del plan
  • requireProviderKey — la función de IA necesita tu propia clave de LLM (BYOK, gratuita)
  • requireStorageEventsBudget — grupo de almacenamiento agotado
  • Devuelve PlanAccessError con upgradeTarget

Arquitectura de outbox duradera

  • Las rutas de API publican en un billingOutbox duradero antes de Pub/Sub
  • La Cloud Function billingOutboxWorker es el único escritor de cuentas
  • Transacciones atómicas con idempotencia + límite negativo
  • El billingReconciliation diario ejecuta comprobaciones de integridad del libro mayor
  • Diseño basado en puertos: todo el código de facturación depende de interfaces abstractas

Límite de presupuesto por bot

Cada bot puede tener un límite de gasto mensual. La puerta suma el costo observado (BYOK) del bot desde el almacén de observabilidad canónico a través de sum_cost_by_bot y pausa el bot cuando se supera el límite. Establece límites en la configuración del bot.

Recarga y libro mayor solo en Dashboard

El monedero prepago (exceso de almacenamiento de conversaciones + complementos de retención) se recarga en cualquier cantidad desde $5 hasta $10,000 en Dashboard → Billing. Cada débito y crédito se registra en un libro mayor de transacciones inmutable que puedes revisar y exportar desde la página de Billing (desglose por bot, desglose por modelo, rango de fechas, CSV).

Los turnos del bot son BYOK: /api/v1/bot-run no se descuenta del monedero prepago ni devuelve 402 por saldo. El monedero solo cubre el exceso de almacenamiento de conversaciones y los complementos de retención financiados por el monedero; Dodo cobra el plan por separado.

Trazas y analíticas

Cada decisión se traza a un único almacén canónico: Postgres rylvo-obs (observability_traces → observations → scores). La doble escritura heredada de Firestore chatTraces se retiró. Puedes reproducir cualquier turno pasado, listar cada ejecución en una sesión y obtener analíticas resumidas por empresa desde el dashboard. Los endpoints del motor a continuación respaldan esas vistas: son internos (dashboard / MCP), no forman parte de la superficie REST pública.

Endpoints internos (alimentan el dashboard)

MétodoRutaDescripción
GET/v1/traces/{trace_id}/replayCarga completa de reproducción para una traza (pila de prompts, guardrails, llamadas a herramientas, tiempos por etapa)
GET/v1/sessions/{session_id}/traces?limit=50Lista cada ejecución en una sesión, más reciente primero
GET/v1/analytics/companies/{company_id}/overview?limit=500&top_n=10Tasa de escalación, latencia promedio y resúmenes de tokens/costos en la ventana
GET/v1/analytics/companies/{company_id}/runs?limit=100Ejecuciones individuales recientes para una empresa

Rutas de escritura

  • Motor: make_observability_ingest_hook (canales en vivo)
  • Playground / Architect: adaptadores → POST /v1/observability/ingest
  • Contexto operador enriquecido en metadata.turn_context
  • Observaciones jerárquicas: spans, generaciones, herramientas, guardrails, recuperador, agente

Rutas de lectura

  • Trazas del dashboard: proyectores respaldados por canónico
  • Analíticas: analytics-rows agregados de Postgres
  • Facturación: sum_cost_by_bot (límite por bot)
  • Audiencia / GDPR: filas de clientes canónicas

Decisiones tipadas (TypeSafe Jev)

Algunas decisiones dentro de un turno solo eligen una etiqueta, por lo que el motor las plantea como preguntas tipadas a TypeSafe Jev ("System One" de TypeSafe AI), un modelo solo de decisiones que elige una de N opciones, responde sí/no o coloca texto en una escala ordenada, con una probabilidad calibrada, y nunca escribe texto. Cada sitio conserva su implementación anterior como respaldo automático cuando Jev no puede responder, y un interruptor de circuito hace que ese respaldo sea inmediato durante una interrupción. Jev se ejecuta con la propia clave TypeSafe de Rylvo, no con tu clave de proveedor BYOK; el respaldo usa tu clave como antes.

  • Guardrails: reglas de evaluación personalizadas sobre el mismo texto, en una solicitud
  • Flows: transiciones de intención; etapa del flujo de trabajo del bot + sentimiento
  • Agent Groups: enrutamiento de despacho solo por intención; fan-out vote
  • Knowledge Base: calificación de relevancia Self-RAG
  • Mission Control: la señal de riesgo de la conversación

Cada solicitud de Jev es una observación generation en la traza, nombrada como jev-guardrail-check, jev-workflow-stage, jev-kb-relevance o jev-flow-intent, con el modelo typesafe/jev-latest, tokens, costo, latencia y cada pregunta con su respuesta y probabilidad. Se cobra como cualquier otra generación y cuenta para el total de la traza. El texto de la pregunta puede citar a tu cliente, por lo que solo se almacena cuando el bot captura entradas. Cuando Jev no respondió, el paso registra el error y que la implementación anterior decidió. La señal de riesgo no es un paso de traza; aparece con las señales de riesgo de la conversación en Mission Control. Las organizaciones pueden optar por no usar Jev en Settings, y cada decisión usa entonces su implementación anterior.

Trampa de fechas: las columnas de observabilidad started_at son TIMESTAMP WITHOUT TIME ZONE. Usa siempre UTC naive en el límite del repositorio; las fechas con zona horaria son rechazadas por asyncpg.

Ejemplo de reproducción

curl https://rylvo.com/api/v1/traces/tr_def456/replay \
  -H "X-API-Key: YOUR_API_KEY"

Analytics solo en Dashboard

Gráficos en cada respuesta que envían tus bots, leídos del almacén de observabilidad canónico (Postgres): las mismas respuestas que lista la página de Traces. Cada parte tiene su propia página en Dashboard → Analytics: salas (cada sala, su configuración y cada widget), la biblioteca de widgets, plantillas, alertas y enlaces compartidos.

Salas

Una cuadrícula nombrada de widgets con su propio rango y bot.

  • Última hora, 24 horas, 7, 30 o 90 días, todo el tiempo, o días personalizados en la zona horaria del espacio de trabajo
  • El rango y el bot viven en la URL, por lo que un enlace abre la misma vista
  • Haz clic en un punto, barra o porción para abrir esas respuestas en Traces
  • Test y Production tienen cada uno sus propias salas; los lanzamientos no las transfieren

Widgets

Qué contar, la medida, cómo dividirlo y el gráfico.

  • Contar respuestas, llamadas a herramientas o respuestas pagadas
  • Respuestas, personas alcanzadas, conversaciones, costo, tokens, tiempo de respuesta, tasa de éxito / fallo / advertencia / bloqueo / error
  • A lo largo del tiempo, o por bot, modelo, canal, resultado o usuario final — como número, línea, columnas, barras, dona, distribución o tabla
  • Un widget puede reducir el rango de la sala o el bot, nunca ampliarlo; los mosaicos de números se comparan con el período anterior

Biblioteca y plantillas

  • Una biblioteca de widgets para Pruebas y Producción
  • Agregar un widget de la biblioteca a una sala coloca una copia — cambiar la biblioteca no cambia las salas
  • 10 plantillas — Resumen, Ahora mismo, Calidad, Velocidad, Costo, Canales, Clientes, Bots comparados, Herramientas, Modelos — vistas previas con tus números en vivo
  • Un espacio de trabajo vacío comienza con una sala de Resumen de los últimos 7 días

Alertas

  • Tasa de error, tasa de advertencia, tiempo de respuesta (p95), costo por respuesta o gasto diario en o por encima de un umbral
  • Un bot o todos los bots; Producción, Pruebas o ambos
  • Se revisan aproximadamente cada 5 minutos; cuando se activa una, cada miembro recibe una notificación en la aplicación, luego espera su período de enfriamiento
  • El formulario muestra cuál es el número en este momento

Compartir, eventos y exportación

  • Un enlace para compartir es una instantánea — números tal como estaban, nunca texto de respuestas; los usuarios finales aparecen como “Cliente 1, 2…”
  • Los enlaces expiran (el valor predeterminado del espacio de trabajo, hasta su máximo) y se pueden desactivar
  • Los eventos marcan un lanzamiento o un incidente en los gráficos de tiempo de una sala
  • Exporta los números de widgets de una sala, o las respuestas detrás de ellos, como CSV o JSON

Cuánto se lee

  • Hasta 20,000 de las respuestas más recientes en el rango, 2,000 por página
  • Cuando un rango contiene más, la sala indica qué días cubren sus números
  • Las respuestas aún en ejecución y los turnos de Workspace Architect se omiten

Roles y plan

Advanced Analytics está disponible desde el plan Lite en adelante; los espacios de trabajo gratuitos ven un aviso de actualización. Los espectadores ven todas las salas y pueden exportar; los operadores crean salas, editan widgets, guardan en la biblioteca y agregan eventos; los administradores eliminan salas, gestionan alertas, crean enlaces para compartir y eliminan widgets de la biblioteca.

Referencia de AnalyticsSolo panel

Las formas y los endpoints internos detrás de Analytics. Las salas se leen desde Firestore en tiempo real y se escriben solo a través del motor, que verifica la organización, el plan y el rol, y escribe una entrada de auditoría. Ninguno de estos endpoints es REST público.

Endpoints internos (motor)

  • GET /v1/analytics-rooms/{company_id} — listar salas
  • GET /v1/analytics-rooms/{company_id}/{room_id} — una sala (404 si falta)
  • POST /v1/analytics-rooms/{company_id} — crear (operadores+; 201, { room_id, ok })
  • PUT /v1/analytics-rooms/{company_id}/{room_id} — cambiar nombre, filtros o gráficos (operadores+)
  • DELETE /v1/analytics-rooms/{company_id}/{room_id} — eliminar (administradores; idempotente)
  • GET /v1/observability/orgs/{org_id}/analytics-rows — respuestas para gráficos, más recientes primero, ≤ 2,000 por llamada
  • POST /v1/observability/orgs/{org_id}/alerts — crear, o actualizar cuando se envía un id (administradores)
  • POST /v1/observability/orgs/{org_id}/alerts/check — el número de una alerta en este momento (cualquier miembro)

Los cambios en las salas se auditan (analytics_room_created / updated / deleted), y también los enlaces para compartir (analytics.share_created / analytics.share_revoked).

Alertas

  • metric: error_rate, warning_rate, p95_latency_ms, avg_cost_usd, daily_spend
  • environment: production, test, o null para ambos; botId null = todos los bots
  • Las tasas se almacenan como fracciones (0.05 = 5%); el formulario trabaja en porcentaje
  • Se activa en o por encima del umbral con al menos minTraces respuestas, luego espera cooldownMinutes

Roles

  • analytics.view — espectador
  • analytics.edit, analytics.annotate — operador
  • analytics.manage, analytics.share — administrador
  • Widgets de biblioteca: los operadores escriben, los administradores eliminan; los eventos y enlaces para compartir son solo de servidor

Forma de Firestore

{envRoot}/analyticsRooms/{roomId}          (Test and Production each have their own)
  |- name (1-200), createdBy, createdAt, updatedAt
  |- filters: { botId, env, dateRange }     (the room's own range and bot)
  +- charts: [{ id, type, position, title?, width?, height?, color?,
                customWidget?: WidgetConfig }]

WidgetConfig:
  view: traces (replies) | tool_calls | cost (paid replies)
  metric: count | total_cost | p95_latency | error_rate | ... (20)
  breakdown: none | time | bot | model | status | user | channel | ...
  chartType: big_number | line | bar_v | bar_h | pie | histogram | pivot
  filters: [{ id, column, op, value }], dateRange (narrows only), topN? (10)

{orgRoot}/analyticsWidgets/{widgetId}  library (Test + Production)
{orgRoot}/analyticsAnnotations/{id}    events (server-written)
analyticsShares/{token}                share links + snapshot (server-only)

SDKs y Bibliotecas

Python

import requests

resp = requests.post(
    "https://rylvo.com/api/v1/bot-run",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={
        "botId": "bot_abc123def456",
        "sessionId": "sess_001",
        "message": "I can't access my account.",
    },
)

data = resp.json()
print(data["response"])
print(f"run {data['runId']} · {data['tokens']['total']} tokens")

JavaScript / Node.js

const res = await fetch("https://rylvo.com/api/v1/bot-run", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer YOUR_API_KEY",
  },
  body: JSON.stringify({
    botId: "bot_abc123def456",
    sessionId: "sess_001",
    message: "I can't access my account.",
  }),
});

const data = await res.json();
console.log(data.response);
console.log(data.runId, data.tokens.total, "tokens");

PromptsSolo panel

Los prompts son las instrucciones que tus agentes siguen en tiempo de ejecución. Créalos desde el panel de Prompts, asígnalos a bots y opcionalmente habilita la optimización auto-mejorable.

Conceptos clave

Categorías de agentes

9 categorías: Sistema, Compositor de respuestas, Clasificador de etapas, Selector de acciones, Clasificador de escalamiento, Resumidor de sesiones, Verificador, Recuperación, Personalizado

Marcadores de posición

Usa la sintaxis {{key}} para valores dinámicos resueltos en tiempo de ejecución (nombre de empresa, tono, idioma, etc.)

Auto-mejora

Activa prompts auto-mejorables para permitir que el sistema genere, evalúe y promueva mejores variantes de prompts

Asignación de bots

Asigna prompts a bots específicos, o déjalos compartidos entre todos los bots

Crear un prompt

1

Elige una categoría de agente

Selecciona qué tipo de agente controla este prompt (por ejemplo, Compositor de respuestas, Verificador).

2

Escribe el contenido de tu prompt

Usa la sintaxis {{placeholder_key}} para valores dinámicos. Se proporcionan plantillas para cada categoría.

3

Agrega marcadores de posición

Define claves, etiquetas, valores predeterminados y si son obligatorios. Usa la biblioteca de plantillas para los comunes.

4

Asigna a un bot (opcional)

Vincula el prompt a un bot específico, o déjalo compartido. Etiqueta las solicitudes con prompt_id en la API.

5

Habilita la auto-mejora (opcional)

Activa la auto-optimización en el panel de detalles del prompt. Elige una estrategia, métrica y frecuencia.

Sintaxis de marcadores de posición

Los marcadores de posición usan sintaxis de doble llave: {{key}}. En tiempo de ejecución, se resuelven con valores de la solicitud de API o valores predeterminados.

You are a support agent for {{company_name}}.

Greet the user as {{user_name}} in a {{tone}} tone.
Respond in {{language}}. Keep replies under {{max_length}} tokens.

{{context}}

Plantillas de marcadores de posición integradas

ClavePredeterminadoDescripción
{{company_name}}Acme CorpEl nombre de la empresa del cliente
{{user_name}}JohnEl nombre para mostrar del usuario final
{{product_name}}Widget ProEl producto en discusión
{{industry}}TechnologyEl sector vertical de la industria del cliente
{{tone}}professionalTono de respuesta (formal, casual, empático)
{{language}}EnglishIdioma de respuesta
{{max_length}}256Longitud máxima de respuesta en tokens
{{context}}-Contexto adicional para el prompt

Historial de versiones

Cada edición de un prompt crea una nueva versión. Las versiones se rastrean como manual o auto_optimized. Puedes ver, comparar y promover cualquier versión a activa desde el panel de detalles del prompt.

Herencia de prompts

Crea una bifurcación de un prompt estableciendo un parentPromptId. El hijo hereda la plantilla base y puede agregar sus propias anulaciones mientras mantiene el linaje rastreado en el historial de versiones. Esto es útil para variaciones por bot o por grupo de un prompt compartido.

Grafo de dependencias

El panel de Prompts tiene un grafo SVG interactivo que muestra cómo se relacionan los prompts, los bots y los grupos de agentes entre sí.

Diseño del grafo

  • Bots a la izquierda → Prompts en el centro → Grupos de agentes a la derecha
  • Las aristas muestran las asignaciones de prompts de bots mediante prompt.botId
  • Los prompts a nivel de organización (botId = null) se conectan a un nodo virtual de la organización
  • La herencia padre → hijo se dibuja dentro de la columna de prompts
  • Los prompts compartidos por grupo se conectan a su grupo de agentes

Interacciones

  • Haz clic en un prompt → abre el detalle del prompt
  • Haz clic en un bot → abre la página del bot
  • Pasa el cursor sobre cualquier nodo → información sobre herramientas con nombre completo y metadatos
  • Desplázate o haz pinza para hacer zoom, arrastra para desplazarte
  • Botones de zoom/ajuste para navegación rápida

Analíticas de uso de prompts

El panel de detalles del prompt muestra métricas de uso en tiempo real desde el almacén de trazas canónico: volumen de trazas, costo, latencia e historial de ejecuciones A/B. Úsalo para decidir qué versión tiene mejor rendimiento antes de promoverla.

Versionado de recursosSolo panel

Cada recurso que afecta el tiempo de ejecución está versionado, no solo los prompts. Los prompts, las salvaguardas, los conectores, las reglas de evolución y los planos de KB rastrean un historial de versiones inmutable más la fuente de cada edición. Puedes comparar, previsualizar, promover y revertir desde el panel.

Reglas y puntuación también. Las reglas de detección de casos límite (con los criterios de revisión de IA), la puntuación de pruebas y la puerta de lanzamiento mantienen una versión por guardado — quién la guardó, cuándo, la nota, cuántas cosas cambiaron — listadas bajo Historial en su página, en todos los planes. En Enterprise, Restaurar devuelve una versión anterior: se guarda como una nueva versión (el historial conserva ambas), se verifica como cualquier guardado — un límite de plan o una regla que ya no existe lo detiene y explica por qué — y se escribe en el registro de auditoría.

Como código. Cada uno de los tres es un documento JSON: el campo detection, scoring o criteria de su GET, que su PUT recupera con base_version (uno obsoleto se rechaza) y un change_note opcional — para que una canalización pueda mantenerlos en git. En Enterprise, Exportar descarga la versión guardada como ese JSON, e Importar coloca un archivo — una exportación, o una respuesta de API guardada — en la página como cambios sin guardar para verificar y guardar. Los ajustes que la página no tiene se omiten y se nombran. A través de MCP (Build Intelligence), los mismos tres son edge_cases.get/set_detection_rules, tests.get/set_scoring y tests.get/set_release_gate, con workspace.restore_config_version para devolver uno — guardar es para administradores y propietarios, y el historial nombra a la persona (“Alex a través de MCP”).

Fuentes de edición

human

Edición manual por un compañero desde el panel

architect

Aplicado a través de Workspace Architect (modo de configuración / edición conversacional)

auto_generated

Producido por el optimizador Auto-Mejorable o el generador de reglas de Evolución de Agentes

fix_proposal

Aceptado de una propuesta de corrección del Motor de Casos Límite

system

Migración interna o semilla predeterminada

red_team

Creado en respuesta a un hallazgo de equipo rojo

Qué está versionado

Bots

Prompts

Salvaguardas

Conectores

Reglas de Evolución

Planos de KB

Qué puedes hacer desde el panel

  • Ver el historial completo de ediciones de cualquier recurso (quién, qué, cuándo, por qué)
  • Comparar dos versiones lado a lado
  • Previsualizar una versión antes de promoverla a activa
  • Promover cualquier versión anterior de nuevo a activa con un clic (reversión)
  • Filtrar el historial por fuente — manual, arquitecto, generado automáticamente, etc.

Cada decisión en tiempo de ejecución registra qué versión estaba activa cuando se ejecutó, para que puedas correlacionar cambios de rendimiento con ediciones específicas — no solo qué recurso se usó, sino qué versión de él.

Prompts Auto-MejorablesSolo panel

Rylvo implementa optimización automática de prompts respaldada por investigación. Cuando está habilitada, el sistema genera, evalúa y selecciona continuamente mejores variantes de prompts usando datos de rendimiento reales.

Cómo funciona

1. Recopilar

El sistema reúne métricas de rendimiento de solicitudes de API reales que usan este prompt — tasa de éxito, tasa de aprobación de verificación, señales de satisfacción del usuario y latencia.

2. Generar

Un LLM optimizador analiza el historial de prompts puntuados y propone N variantes mejoradas. Cada variante conserva todos los marcadores de posición y la intención central, pero prueba una estrategia de mejora diferente.

3. Evaluar

Cada variante se puntúa según tu métrica elegida. La puntuación usa análisis estructural, calidad de restricciones y patrones de rendimiento históricos.

4. Seleccionar

Se identifica la variante con mejor rendimiento. Debe superar al prompt actual por al menos el umbral de mejora (predeterminado 2%) para calificar.

5. Promover o sugerir

Si la auto-promoción está activada, el ganador se convierte automáticamente en el prompt activo. De lo contrario, aparece en el historial de versiones para revisión manual.

Estrategias de optimización

Hay cuatro estrategias respaldadas por investigación disponibles. Cada una usa un enfoque diferente para la mejora de prompts.

OPRO

Yang et al., 2023 - Google DeepMind

Optimización mediante PROmpting. Alimenta historial puntuado (prompt, rendimiento) a un LLM que propone variantes mejoradas. Idea central: los LLM pueden actuar como optimizadores cuando se les dan ejemplos con puntuaciones.

Mejor cuando tienes historial de versiones con puntuaciones diversas.

APE

Zhou et al., 2023 - Universidad de Toronto

Ingeniero Automático de Prompts. Genera candidatos diversos usando múltiples estrategias de mejora (instrucciones explícitas, ejemplos, reestructuración, salvaguardas, simplificación), evalúa cada uno, selecciona el mejor.

Mejor para prompts nuevos con poco historial.

DSPy Bootstrap

Khattab et al., 2023 - Stanford Compila los patrones de mejor rendimiento de la historia en demostraciones few-shot optimizadas. Extrae lo que funciona y lo incorpora directamente al prompt como ejemplos.

Mejor cuando existen versiones de alta puntuación de las que aprender.

PromptBreeder

Fernando et al., 2023 - Google DeepMind

Evolución autorreferencial. Aplica prompts de mutación (hazlo conciso, añade restricciones, reestructura, añade razonamiento, añade role-playing) para evolucionar el prompt de la tarea. Las mutaciones en sí mismas pueden evolucionar.

Mejor para la exploración creativa del espacio de prompts.

Opciones de configuración

OpciónPredeterminadoDescripción
EstrategiaOPROQué algoritmo de optimización usar
Métrica de evaluaciónTasa de éxitosuccess_rate | verification_pass | user_satisfaction | latency
Frecuencia de ejecuciónDiariahourly | daily | weekly | manual
Auto-promociónDesactivadaPromover automáticamente variantes ganadoras a activas
Umbral de mejora2%Mejora mínima requerida para calificar como ganadora
Máx. variantes por ejecución5Número de variantes candidatas generadas por ejecución de optimización
Tamaño mínimo de muestra50Solicitudes API mínimas antes de la primera ejecución de optimización

Habilitar la auto-mejora

1

Abre el panel de detalles del prompt

Haz clic en cualquier prompt de la página Prompts para ver sus detalles.

2

Expande 'Prompts auto-mejorables'

Haz clic en el encabezado del panel para expandir la configuración de optimización.

3

Activa 'Habilitar auto-mejora'

Esto activa el bucle de optimización para este prompt.

4

Elige tu estrategia

Selecciona OPRO, APE, DSPy Bootstrap o PromptBreeder según tus necesidades.

5

Configura tu métrica y frecuencia

Elige qué optimizar y con qué frecuencia ejecutarlo.

6

Decide sobre la auto-promoción

Actívala para implementar automáticamente variantes ganadoras, o déjala desactivada para revisión manual.

Uso de la API de Prompts

Los prompts se asignan a un bot en el panel (o mediante la superficie MCP), se versionan y se resuelven automáticamente cuando el bot se ejecuta. /api/v1/bot-run no acepta un prompt_id ni un prompt_overrides — para cambiar qué prompt usa un bot, actualiza su asignación de prompt.

Cómo se resuelven los prompts en tiempo de ejecución

1

Resolver

Los prompts asignados al bot cargan sus versiones activas.

2

Sustituir

Todos los valores {{placeholder}} se completan desde los valores predeterminados del bot/org.

3

Inyectar

El texto resuelto se convierte en parte del prompt del sistema para el turno.

4

Rastrear

El trace registra qué versiones de prompt estaban activas (impulsa análisis + Prompts auto-mejorables).

Cambiar o hacer A/B de un prompt

  • Actualiza la asignación de prompt de un bot en Panel → Bots (o en la página Prompts).
  • Usa Prompts auto-mejorables para hacer A/B de variantes y auto-promover ganadoras.
  • El trace de cada turno registra la versión de prompt resuelta para análisis y optimización.

Motor de Casos Límite Solo panel

Detecta, clasifica y corrige automáticamente los modos de fallo del bot

El Motor de Casos Límite escanea los traces de tu bot y archiva lo que realmente registraron en 15 categorías, con los traces como evidencia. Funciona en cuatro etapas: Observar → Detectar → Clasificar → Triaje, y un caso resuelto se reabre solo si el problema vuelve a aparecer. Gestiona desde Panel → Casos Límite. Función del plan Pro+.

3 mecanismos de detección

  1. Escaneo de traces — POST /v1/edge-cases/{org}/scan archiva lo que registró cada trace (veredictos de fallo y brechas de conocimiento), un caso por señal por bot, con los traces como evidencia. 10 escaneos/min por org
  2. Revisión por IA — opcional: un modelo que elijas lee las conversaciones reales y solo puede informar defectos visibles en la respuesta, citando el trace. Se ejecuta gratis con tu propia clave LLM (BYOK)
  3. Pruebas adversariales Red Team — 13 estrategias integradas con entradas estáticas y generadas por LLM, se ejecutan sincrónicamente en Cloud Run con checkpointing por resultado

12 categorías de casos límite

  • Alucinación — respuesta no fundamentada en evidencia de KB
  • Violación de política — incumplió la política de la empresa/flujo de trabajo
  • Escalamiento omitido — debería haber escalado pero no lo hizo
  • Herramienta incorrecta — seleccionó la herramienta equivocada
  • Llamada a herramienta faltante — debería haber llamado a la herramienta pero la omitió
  • Etapa incorrecta — identificó mal la etapa del flujo de trabajo
  • Memoria obsoleta — usó hechos de sesión desactualizados
  • Intención desconocida — intención no cubierta por el flujo de trabajo
  • Violación de tono — no coincide con las pautas de marca
  • Fuga de PII — expuso información personal sensible
  • Bucle detectado — bot atascado en un patrón repetitivo
  • Personalizado — categoría definida por el usuario

Ciclo de vida de estado y severidad

5 niveles de severidad (crítico=5, alto=4, medio=3, bajo=2, informativo=1) ordenados por peso.

Flujo de estado:

open → acknowledged → fix_proposed → fix_applied → resolved

Alternativa: descartado (falso positivo) o eliminado (remoción permanente).

Correcciones

Sugerir correcciones en un caso límite (o en Correcciones) da las correcciones de Rylvo para ese tipo de problema, más hasta tres que la IA escribe para la conversación exacta con tu clave de modelo. Cada una es de uno de cuatro tipos:

  • Guardarraíl — añadido en Pruebas con un clic (o editado primero); una versión lo pone en producción
  • Prompt — texto para añadir al prompt del bot: cópialo, añádelo, márcalo como hecho
  • Conocimiento — una respuesta para añadir a una base de conocimiento, luego márcala como hecha
  • Configuración — pasos a verificar, con un enlace al lugar

Rylvo nunca edita un prompt ni una base de conocimiento por ti. Las correcciones también se pueden publicar mediante la API (POST /v1/red-team/{org}/fix-proposals).

Ciclo de vida: por hacer → hecho / descartado

13 estrategias de Red Team

  • policy_probe, hallucination_bait, tool_confusion, escalation_boundary
  • injection_attempt, context_overflow, mcp_abuse, pii_extraction
  • multi_turn_coercion, jailbreak_dan, function_leak, billing_bypass, kb_poisoning

Ajuste: presupuesto de ejecución de 240s, tiempo de espera de 45s por turno, 6 concurrentes, máx. 25 pruebas/estrategia. Los guardarraíles se activan como en producción; facturación/gobernanza omitidas (ejecuciones sintéticas gratuitas).

Deduplicación y RBAC

ID determinista de SHA256(botId::categoría::título). Los escaneos duplicados incrementan occurrenceCount.

  • edgeCases.view — viewer+
  • edgeCases.manage — admin+
  • guardrails.view — viewer+
  • guardrails.manage — admin+
  • redTeam.view — viewer+
  • redTeam.run — admin+

4 pestañas del panel

Casos Límite

Filtrar por estado/categoría/severidad/bot, buscar, crear/editar/resolver/descartar/eliminar, asignar

Red Team

Crear ejecuciones, seleccionar estrategias, configurar, ejecutar sincrónicamente, ver resultados, crear casos límite a partir de fallos

Guardarraíles

Ver/crear/editar/activar/desactivar/eliminar, condiciones, acciones, prioridades, estadísticas de activación, historial de versiones

Propuestas de corrección

Ver/crear/aplicar/rechazar/revertir con vinculación de pruebas de regresión

Estructura de Firestore

{envRoot}/edgeCases/{edgeCaseId}
  |- title, description, category, severity, status
  |- source: trace_mining / red_team / manual / guardrail_trigger
  |- botId, botName, traceIds[], occurrenceCount
  |- sampleInput, sampleOutput, expectedBehavior
  |- fixProposalId, guardrailId, tags, assignedTo
  +- firstSeenAt, lastSeenAt, resolvedBy, resolvedAt

{envRoot}/fixProposals/{proposalId}
  |- edgeCaseId, fixType, title, description
  |- impact, confidence, status
  |- details: { guardrailConfig?, promptChanges?, thresholdChanges?, customSteps? }
  |- regressionTestIds[]
  +- appliedBy, appliedAt, createdBy, createdAt

{envRoot}/redTeamRuns/{runId}
  |- name, botId, strategies[], status
  |- config: { testsPerStrategy, maxConcurrent, timeoutMs, ... }
  |- results: { totalTests, passedTests, failedTests, edgeCasesFound }
  +- edgeCaseIds[], startedAt, completedAt

{envRoot}/redTeamRuns/{runId}/results/{resultId}
  |- strategy, testInput, botResponse, passed
  |- failureCategory, failureReason, severity, edgeCaseId
  |- guardrailResults[], toolCalls[], traceId, latencyMs
  +- model, tokens, createdAt

Guardarraíles Solo panel

Reglas de seguridad programables que se ejecutan en cada respuesta del bot

Los guardarraíles son reglas en tiempo de ejecución que verifican entradas/salidas del bot y toman acción cuando se cumplen condiciones. Se pueden crear manualmente o sugerirse automáticamente mediante el Motor de Casos Límite cuando detecta patrones de fallo.

Tipos de guardarraíles

  • Filtro de entrada - Valida la entrada del usuario antes del procesamiento
  • Filtro de salida - Valida la respuesta del bot antes de la entrega
  • Verificación de hechos - Verifica afirmaciones contra la base de conocimiento
  • Verificación de política - Asegura el cumplimiento de políticas de la empresa
  • Detección de PII - Detecta y redacta datos sensibles
  • Verificación de tono - Valida que el tono coincida con la marca
  • Rompe bucles - Rompe patrones de conversación repetitivos
  • Anulación de escalamiento - Fuerza el escalamiento bajo condiciones
  • Puerta de herramientas - Controla el acceso a herramientas en contextos específicos

Acciones

  • Bloquear - Evitar la respuesta, devolver mensaje de respaldo
  • Advertir - Marcar para revisión pero permitir que la respuesta pase
  • Reescribir - Modificar automáticamente la respuesta para cumplir
  • Escalar - Activar transferencia humana inmediatamente
  • Registrar - Registrar para monitoreo, sin tomar acción

Cada guardarraíl tiene condiciones (campo + operador + valor) y un mensaje de respaldo que se muestra cuando se activa.

Condiciones y evaluación

Una condición de guardarraíl se construye a partir de un campo de trace/tiempo de ejecución, un operador y un valor. Ejemplos:verification.status == fail,output.pii_detected == true, o loop.count > 3. Los guardarraíles se evalúan en orden de prioridad; las acciones de bloqueo y escalamiento cortocircuitan el resto.

Evaluación personalizada (custom_eval) las condiciones toman una regla en lenguaje natural. Cada regla personalizada que verifica el mismo texto se juzga en una sola solicitud TypeSafe Jev en lugar de una llamada LLM por regla, y el motivo lleva la probabilidad, p. ej. Violates "Never promise a refund" (p=0.94). Si Jev no puede responder, el juez LLM se ejecuta con tu clave; la política de cierre por fallo no cambia — si ningún juez puede responder, la regla cuenta como violada.

Ciclo de vida y auditoría

Versionado

Cada edición es una nueva versión etiquetada manual, fix_proposal, red_team, system o auto_generated

Controlado por experimento

Los cambios riesgosos se pueden implementar detrás de un flag antes de la promoción completa

Auditoría de traces

Cada decisión de guardarraíl se registra en las observaciones del trace

Auditoría de guardarraíles

Tarea de automatización programada revisa la efectividad y sugiere ajustes

Pruebas de Red Team Solo panel

Descubre proactivamente vulnerabilidades con pruebas adversariales

Las ejecuciones de Red Team generan entradas adversariales contra tu bot para encontrar fallos antes que los usuarios. Selecciona un bot, elige estrategias de ataque, y el motor genera casos de prueba automáticamente. Los resultados se convierten en casos límite con niveles de severidad.

13 estrategias de ataque integradas

  • Sonda de política - Prueba condiciones límite de política con entradas de casos límite
  • Cebo de alucinación - Preguntas sin respuesta en KB para probar la fundamentación
  • Confusión de herramientas / Abuso de MCP - Entradas que activan selección incorrecta o insegura de herramientas
  • Límite de escalamiento - Prueba el borde de los umbrales de escalamiento
  • Intento de inyección / Jailbreak (DAN) - Inyección de prompts e intentos de jailbreak
  • Desbordamiento de contexto - Conversaciones largas que estresan los límites de memoria
  • Extracción de PII / Fuga de funciones - Intentos de exponer datos privados o internos del sistema
  • Coerción multi-turno, Bypass de facturación, Envenenamiento de KB

Automatización e Informes Solo panel

Programa escaneos, conecta canales y genera informes automatizados

La página de Automatización en /dashboard/automation te permite configurar trabajos recurrentes, canales de notificación e informes analíticos automatizados. Todo se ejecuta según el horario que elijas — sin intervención manual después de la configuración. Cada parte tiene su propia página: Resumen, Tareas (cada una con sus ejecuciones y configuraciones), Informes (cada uno con su historial y configuraciones), Informes generados y Canales. Editas las automatizaciones en Pruebas; la copia publicada se ejecuta y envía en Producción, mientras que las ejecuciones de Pruebas se guardan en cada página de tarea y nunca se envían.

10 plantillas de tareas programadas

Trabajos cron que se ejecutan automáticamente mediante Cloud Function (cada 5 min):

  • trace_scan — escaneo automático de traces para casos límite
  • red_team_run — pruebas adversariales periódicas
  • guardrail_audit — revisión de efectividad de guardarraíles
  • complaint_watch — monitoreo de conversaciones con riesgo de quejas
  • dev_review — revisión de ejecuciones fallidas y patrones
  • conversation_quality — muestreo de conversaciones para revisión de calidad
  • cost_usage_watch — revisión de gasto y costo de tokens registrados
  • kb_gap_analysis — búsqueda de brechas de conocimiento en resultados de traces
  • connector_health — auditoría de salud de conectores/MCP
  • test_suite_run — ejecutar una suite de pruebas cuando la integración del motor está configurada

9 cadencias: hourly → monthly. Configuración de horario rica (intervalo/semanal/mensual con zona horaria IANA). Máx. 25 tareas/invocación, 3 concurrentes/org, tiempo de espera de 90s. Los trabajadores seleccionados pueden añadir análisis BYOK opcional; los informes se configuran por separado.

5 canales de notificación

Dónde se envían alertas e informes. Entrega mediante outbox duradero con reintento de backoff exponencial:

  • Slack — integración de webhook
  • Email — directo a bandejas de entrada del equipo
  • Discord — integración de webhook
  • Microsoft Teams — integración de webhook
  • Webhook personalizado — cualquier endpoint HTTPS

Eventos: edge_case.created, red_team.completed, report.generated, etc. Alcance: global o vinculado a bots específicos.

13 secciones de informes

  • executive_summary, edge_cases_overview, edge_cases_by_category/severity
  • guardrail_performance, red_team_results, fix_proposals_summary
  • improvements_timeline, bot_comparison, complaints_and_escalations
  • developer_followups, automation_coverage, recommendations (AI)

13 fuentes de datos, 5 formatos de salida funcionales (html_email, slack_blocks, teams_card, discord_embed, markdown). 5 filtros de destinatarios (all_members, admins_only, owners_only, operators_only, custom). Formateo LLM opcional con modelo personalizado, prompt del sistema, temperatura, tokens máximos. La opción reservada de PDF actualmente no genera un archivo PDF.

RBAC y límites del plan

  • automation.view — viewer+
  • automation.generate_report — operator+
  • automation.manage_tasks — admin+
  • automation.manage_channels — admin+
  • automation.manage_reports — admin+

Gratis: 0ch, 0tasks, 0configs, 0reports/mo / Starter: 2ch, 0tasks, 0configs, 0reports/mo / Lite: 10ch, 10tasks, 2configs, 25reports/mo / Pro: 25ch, 25tasks, 5configs, 100reports/mo / Enterprise: ilimitado.

Estructura de Firestore

{envRoot}/scheduledTasks/{taskId}
  |- name, type, cadence, enabled, botId
  |- config: { traceLimit?, redTeamStrategies?, aiConfig?, scheduleConfig? }
  |- notificationChannelIds[], lastRunAt, lastRunStatus, nextRunAt
  +- runCount, failCount

{envRoot}/notificationChannels/{channelId}
  |- name, type, enabled, config, events[], botIds[], scope
  +- lastUsedAt, lastStatus

{envRoot}/reportConfigs/{configId}
  |- name, cadence, sections[], dataSources[], filters
  |- recipientFilter, customRecipientEmails[], notificationChannelIds[]
  |- aiConfig?, outputFormats[], scheduleConfig?
  +- lastGeneratedAt, nextGenerateAt

{envRoot}/reports/{reportId}
  |- configId, status, sections[], data, distributedTo[]
  |- llmFormattedContent?, pdfUrl?, tokenUsage?
  +- periodStart, periodEnd, generationDurationMs

{envRoot}/scheduledTaskRuns/{runId}
  |- taskId, taskType, status, summary, details
  +- startedAt, completedAt

Panel de Agent Evolution (solo dashboard)

Sistema de bucle cerrado que aprende del tráfico real y reescribe el agente de forma segura

Mientras que el Motor de Casos Extremos detecta fallos individuales, Agent Evolution analiza patrones entre ejecuciones y actualiza el propio agente. Ejecuta un bucle de seis fases: observar, detectar, inferir, generar, inyectar, verificar—y escribe nuevas reglas, variantes de prompt o ajustes de guardarraíl en recursos versionados. Cada cambio es reversible.

Fases

  1. Observar — muestrear trazas recientes del bot
  2. Detectar — agrupar fallos y cuasi-errores
  3. Inferir — el LLM revisor nombra el patrón y la causa raíz
  4. Generar — redactar una regla, edición de prompt o guardarraíl
  5. Inyectar — adjuntar al bot detrás de una bandera de experimento
  6. Verificar — medir el efecto; promover automáticamente, mantener o revertir

Qué se escribe

  • Reglas de evolución (inyectadas condicionalmente en el prompt del sistema)
  • Actualizaciones de versión de prompt (marcadas como auto_generated)
  • Ajustes de guardarraíl (umbral, condición, texto de respaldo)
  • Perspectivas del revisor (explicaciones narrativas para el equipo)
  • Puntuaciones de efectividad por regla (controlan la promoción automática)

Pestañas del panel

Resumen

Puntuación de salud del bot, mejoras recientes, experimentos activos y resumen de ejecución

Fallos

Trazas fallidas agrupadas por causa raíz; promover a Casos Extremos

Libro de reglas

Reglas de evolución activas y pendientes con banderas de experimento y reversión

Mejorar

Ejecutar un ciclo de mejora manual en trazas o prompts seleccionados

Modelo dialéctico

Configuración del modelo revisor para crítica y refinamiento

Configuración

Habilitar/deshabilitar módulos, filtros de trazas, cadencia, notificaciones y qué busca cada revisor

Registros de ejecución

Historial de cada ejecución de evolución con estado, costo y artefactos

Qué busca cada revisor

Cuatro revisores de IA leen las últimas respuestas de un bot—los revisores de patrón, velocidad, calidad de respuesta y entrada—y cada uno trabaja a partir de un brief. En Agent Evolution → Configuración → Revisiones puedes cambiar el brief de un revisor para el bot: las cosas que busca, una por línea, y para dos de ellos un número—cuántas respuestas necesita un patrón antes de ser reportado (2 para empezar), y cuánto tiempo puede tomar un paso antes de que cuente como lento (2,000 ms para empezar). Cómo un revisor reporta lo que encuentra permanece fijo: tu brief se le entrega junto a las respuestas, nunca como sus instrucciones. Un patrón que cita menos respuestas de las que pide su brief se deja de lado, y el revisor de velocidad ve el tiempo de cada paso. Solo lo que cambias se guarda, así que Usar el brief incluido restaura el propio de Rylvo. Cada revisión—iniciada desde el panel, después de una ejecución de fallos, o después de un chat en la página del bot—se ejecuta en los servidores de Rylvo, con tu propia clave LLM.

Prompts de auto-mejora

Un flujo de trabajo enfocado de Agent Evolution para prompts. Analiza el rendimiento de versiones de prompt a partir de trazas en vivo, genera revisiones propuestas con explicaciones, las evalúa contra trazas reservadas y publica versiones ganadoras como nuevas versiones de prompt (no en vivo hasta que las promuevas). Se ejecuta con tu propia clave LLM (BYOK) y es gratuito.

Cada cambio propuesto está detrás de una bandera de experimento con criterios de éxito medibles. Cualquier cosa que no mueva la aguja se revierte automáticamente; cualquier cosa que sí lo haga se convierte en un cambio versionado permanente que puedes inspeccionar, bifurcar o revertir.

Habilidades de agente (solo dashboard)

Paquetes de capacidades reutilizables que extienden tus bots

Las habilidades son instrucciones reutilizables y versionadas que un bot sigue solo cuando el mensaje de un cliente lo requiere. Una habilidad se activa cuando el mensaje contiene una de sus palabras o una de sus frases tal como están escritas (o en cada respuesta, cuando no tiene ninguna), y sus instrucciones se añaden al prompt del sistema del bot para esa respuesta. Las habilidades son parte de Pro y superiores, y se ejecutan para un bot una vez que su interruptor de Habilidades está activado. Escribe las tuyas propias, añade una de la biblioteca, impórtalas o revisa las sugeridas a partir de lo que Agent Evolution aprendió. Gestiona desde Panel → Habilidades de agente.

Habilidades en producción

  • Instrucciones reutilizables — guían al agente cuando una habilidad se activa
  • Palabras y frases — deciden a qué mensajes se aplican
  • Alcance de bot u organización — controlan dónde se aplica una habilidad
  • Versiones y telemetría — revisan cambios y uso en vivo

Coincidencia de disparadores (determinista, sin LLM)

  • Una palabra coincide en cualquier parte del mensaje, incluso dentro de una palabra más larga
  • Una frase coincide tal como está escrita—su parte entre comillas, o cada parte entre comas (5+ caracteres)
  • Una palabra o una frase supera el mínimo predeterminado (0.25); como máximo 8 habilidades por respuesta
  • Palabras comunes (“puedo”, “sobre”, “ellos”…) nunca son disparadores—se descartan e ignoran
  • Coincidencia opcional por significado: similitud de incrustación con peso 0.3
  • Sin palabras y sin frases: se añade a cada respuesta, primero

6 fuentes de habilidades

  • manual — el operador crea a través del panel
  • generated_from_rules — promovido automáticamente desde clústeres de reglas (opt-in)
  • imported — importado desde otro bot/organización
  • architect — creado por Workspace Architect
  • reviewer_suggested — sugerido por el motor revisor
  • prebuilt — instalado desde el catálogo de la Biblioteca de Habilidades

Inyección en tiempo de ejecución y seguridad

  • Las habilidades coincidentes se añaden a BotPromptInputs.skill_instructions
  • Se fusionan en el prompt del sistema bajo "## HABILIDADES ACTIVADAS"
  • El texto que intenta anular las instrucciones del bot se rechaza al guardar
  • Solo se envían las instrucciones (y sugerencias de herramientas)—nunca el nombre o la descripción
  • Uso registrado después del turno a través de SkillUsageEventDoc
  • Confianza: puntuación × 0.9 (éxito) o × 0.2 (fallo) menos penalización de guardarraíl

Alcance y ciclo de vida

  • Alcance de bot — botId = bot específico, solo ese bot lo carga
  • Cada bot — botId = null, cada bot lo carga
  • El tiempo de ejecución carga primero las de alcance de bot (prioridad), luego las de nivel de organización
  • Estado: borrador → activo → deshabilitado → archivado
  • Solo se usa una habilidad que está activada; Producción usa las copias publicadas

Versionado, reversión y promoción automática

  • Cada cambio crea un SkillVersionDoc (7 tipos de cambio)
  • Restaurar una versión recupera su texto y disparadores; el estado activado/desactivado permanece como está; los contadores se reinician
  • La reversión automática desactiva una habilidad fallida y la mantiene en Prueba y Producción hasta que un administrador la libera
  • Sugerencias de reglas aprendidas: opt-in por bot, después de cada revisión completada (clúster ≥ 3, configurable 2–10), siempre como borradores
  • Efectividad: usageCount, successCount, avgConfidence, lastUsedAt

RBAC y límites del plan

  • evolution.edit_config — admin+ (gestionar habilidades)
  • Los viewers pueden ver pero no crear/editar/eliminar/cambiar estado/revertir

Pro y Enterprise: habilidades ilimitadas · Gratis, Starter y Lite: no incluidas (las habilidades existentes se conservan)

Páginas del panel

  • Todas las habilidades — quién usa cada una, qué la activa, cómo le va
  • Cada habilidad — descripción general, instrucciones, disparadores, versiones, configuración
  • Probar un mensaje — qué habilidades activa un mensaje y qué recibe el modelo
  • Biblioteca — 50 habilidades listas en 15 categorías
  • Configuración — el interruptor de Habilidades de cada bot, coincidencia, sugerencias, reversión automática

Activa las habilidades para un bot en Habilidades → Configuración.

Biblioteca de Habilidades (Catálogo preconstruido)

Un catálogo curado de 50 habilidades listas en 15 categorías que cubren plantillas de bots tanto de agente único como multiagente (Soporte al cliente, Ventas, Cumplimiento, Recopilación de datos, Diseño de conversación, Conocimiento y escalamiento, Comercio electrónico, Salud, RR. HH. e interno, Finanzas y seguros, TI y técnico, Multiagente, Contenido y marketing, Bienes raíces y educación, Utilidades). Explora en Habilidades → Biblioteca y añade una copia a un bot o a cada bot.

Modelo de bifurcación

  • Instalar crea una copia que posees (source: "prebuilt")
  • Sin actualizaciones automáticas—edita libremente después de instalar
  • Como draft o activado—tú eliges
  • Para un bot o para cada bot—tú eliges
  • Se activa con las frases del catálogo (las cortas como “vip” también se convierten en palabras)

Guardarraíles

  • Cada habilidad de la biblioteca se puede añadir una vez por bot y una vez para cada bot
  • Añade varias a la vez—a un bot o a cada bot, omitiendo las que ya están
  • Las habilidades instaladas son habilidades normales—editar, clonar, eliminar, revertir

Estructura de Firestore

{envRoot}/agentSkills/{skillId}
  |- skillId, orgId, botId (null = org-level), botName
  |- name, slug, description, skillType, source, status
  |- systemInstructions (max 8000), triggerConditions[], triggerKeywords[]
  |- requiredTools[], toolChain[], generatedFromRuleIds[]
  |- version, previousVersionId
  |- usageCount, successCount, failureCount, avgConfidence, lastUsedAt
  +- tags, metadata, createdBy, createdAt, updatedAt

{envRoot}/agentSkills/{skillId}/versions/{versionId}
  |- version, changeType, previousInstructions, newInstructions
  |- previousStatus, newStatus, changeReason
  |- previous/newTriggerConditions, previous/newTriggerKeywords
  +- usageCountAtChange, changedBy, createdAt

organizations/{org}/skillSafetyHolds/{skillId}
  +- active, reason, failureRate, usageCount, createdAt, releasedAt?

{envRoot}/agentSkills/{skillId}/usageEvents/{eventId}
  |- eventId (turnId:skillId), turnId, outcome, confidence, score
  +- createdAt, aggregated

Mission Control (solo dashboard)

Supervisión humana en vivo para cada conversación de producción

Mission Control es la superficie de operaciones en vivo en /dashboard/mission-control. Los operadores ven cada conversación activa en tiempo real, pueden intervenir en cualquier nivel, y el sistema mantiene un registro de auditoría inmutable que cumple con los requisitos del Artículo 14 de la Ley de IA de la UE (supervisión humana). Tiempo real a través de listeners de Firestore onSnapshot (sin WebSocket/SSE).

6 tipos de intervención

  • Susurro — inyectar instrucción del sistema (el cliente no la ve), inyectada en el prompt a través de fetch_active_whispers
  • Toma de control — el operador se convierte en el respondedor, el bot se pausa
  • Pausa — congelar el bot, el cliente ve un mensaje de espera
  • Terminar — finalizar la sesión inmediatamente, enviar respaldo (irreversible)
  • Reanudar — reanudar una conversación pausada o tomada
  • Marcar — marcar para revisión sin interrumpir

Las intervenciones bloqueantes (pausa/toma de control/terminar) activan el pre-gate del motor Python (evaluate_mission_control_gate) que bloquea la respuesta del bot. Se requiere justificación para pausa/toma de control/terminar.

Aprobaciones y SLA

3 niveles de urgencia con tiempos de espera:

  • inmediato — tiempo de espera de 15s (informativo de bajo riesgo)
  • estándar — 120s (acceso a datos, relacionado con PII)
  • extendido — 900s (financiero, legal, cumplimiento)

Ciclo de vida: pendiente → aprobado / denegado / expirado / auto_denegado. ExpiresAt se calcula en el servidor. Las decisiones se adjuntan a la traza.

11 disparadores de alerta

Por conversación (en línea después de cada turno del bot):

  • risk_score_above, guardrail_blocked, guardrail_triggered_n_times
  • conversation_duration_above, no_operator_monitoring, approval_queue_size_above
  • pattern_detected (regex), budget_threshold_crossed

Tick del servidor (tarea programada cada minuto):

  • bot_turn_failed_n_in_window, byok_key_unhealthy, wallet_balance_below

Severidad: crítico/alto/medio/bajo. Enfriamiento (predeterminado 300s). Supresión: posponer + horas de silencio (zona horaria IANA). Las instancias de alerta son idempotentes a través de groupKey (ruleId:conversationId).

Presencia del operador

  • 4 estados: en línea / ausente / ocupado / fuera de línea
  • Latido de 30s, obsoleto después de 3 min → fuera de línea automático
  • Seguimiento de turnos: shiftStart / shiftEnd
  • Capacidad: maxConcurrentMonitors (predeterminado 5)
  • Estadísticas: totalInterventions, totalApprovals, avgResponseTimeMs
  • Elección de líder entre pestañas con localStorage para el barrido

Puntuación de riesgo y cumplimiento

  • Puntuación de riesgo 0–100, 5 niveles: crítico / alto / medio / bajo / mínimo
  • Pesos fijos: guardarraíl 30, patrón 25, sentimiento 20 (listas de palabras clave en inglés), tema 15, duración 10
  • Además, en turnos de canal en vivo, una señal custom (peso 10) de TypeSafe Jev: probabilidades de frustración, urgencia y amenaza de cancelación en los últimos 5 turnos del usuario, no limitadas al inglés. Puede aumentar el riesgo, nunca reducirlo
  • Señales de riesgo: fuente, nombre, puntuación, detalles, marca de tiempo
  • Modos de cumplimiento: estándar / eu_ai_act / soc2 / hipaa / personalizado
  • Registro de auditoría de solo anexión (cada acción del operador)
  • Exportación de cumplimiento (CSV/JSON) con URL firmadas
  • Retención: basada en el plan (7d/30d/90d/ilimitado), anulable

RBAC

  • missionControl.view — visor+
  • missionControl.intervene — operador+
  • missionControl.resolve_approval — operador+
  • missionControl.ack_alert — operador+
  • missionControl.manage_rules — administrador+
  • missionControl.edit_settings — administrador+
  • missionControl.delete_conversation — administrador+

7 pestañas del panel

Fuente en vivo

Lista de conversaciones en tiempo real (máx. 100), panel de detalles con transcripción + intervenciones + señales de riesgo, acciones rápidas, asignar operador

Alertas

Activas (confirmación masiva, posponer, resolver), pospuestas, historial, CRUD de reglas con chips de evidencia

Canales

Salud de conectividad por canal, tasas de error, cola de reintentos

Analítica

KPIs, gráficos por tipo/gravedad/estado, clasificación de operadores (7d/30d/90d)

Registro de auditoría

Registro de eventos de solo anexión, filtros, exportación de cumplimiento (CSV/JSON)

Operadores

Plantilla del equipo con estado, rol, indicador de turno, estadísticas

Configuración

Habilitar/deshabilitar, urgencia de aprobación, monitoreo automático, modo de cumplimiento, retención, mensajes

Puntos finales de API

  • POST /api/mission-control/intervene — crear intervención (operador+)
  • POST /api/mission-control/revert — revertir intervención (operador+)
  • POST /api/mission-control/alert-rules — crear/actualizar regla de alerta (administrador+)
  • POST /api/mission-control/dispatch — enviar mensaje de operador al canal (operador+)
  • POST /api/mission-control/delete-conversation — eliminación dura + cascada (administrador+)

Forma de Firestore

{envRoot}/liveConversations/{conversationId}
  |- botId, conversationId, status, riskScore, riskLevel
  |- riskSignals[], messageCount, durationMs, lastMessagePreview
  |- guardrailTriggeredCount, assignedOperatorId, monitoringOperatorIds[]
  |- channel, isProduction, tags, flaggedReason
  +- startedAt, lastMessageAt, endedAt

{envRoot}/operators/{uid}
  |- status: online/away/busy/offline, maxConcurrentMonitors
  |- totalInterventions, totalApprovals, avgResponseTimeMs
  +- shiftStart, shiftEnd, lastActiveAt

{envRoot}/interventions/{interventionId}
  |- type, operatorId, rationale, payload, outcome
  |- riskScoreAtTime, messageCountAtTime, idempotencyKey
  +- createdAt, resolvedAt

{envRoot}/approvalRequests/{requestId}
  |- actionType, urgency, timeoutSeconds, status
  |- riskScoreAtTime, riskSignals[], conversationContext
  +- requestedAt, expiresAt, resolvedBy, resolvedAt

{envRoot}/alertRules/{ruleId}
  |- trigger, severity, config, botId, notificationChannelIds[]
  |- cooldownSeconds, snoozedUntil, quietHours
  +- lastTriggeredAt, triggerCount

{envRoot}/alertInstances/{alertId}
  |- ruleId, status, groupKey, fireCount, evidence[]
  +- firstFiredAt, lastFiredAt, acknowledgedAt, resolvedAt

{envRoot}/oversightAudit/{entryId}
  |- eventType, operatorId, conversationId, botId
  +- details, riskScoreAtTime, timestamp

{envRoot}/missionControl/config
  |- enabled, defaultApprovalUrgency, autoMonitorHighRisk
  |- complianceMode, auditRetentionDays, maxOperatorsPerConversation
  +- pauseMessage, takeoverMessage

Flujos

Grafos de conversación guiados/estrictos que dirigen un bot a través de una secuencia de pasos — cada paso lleva un objetivo (inyectado en el prompt del sistema), datos a recopilar, un alcance de herramientas permitidas y transiciones que el motor avanza a medida que la conversación progresa. Los flujos están limitados a la organización, se adjuntan a un bot mediante bot.flowId o a un grupo de agentes mediante group.flowId, se evalúan por turno por el motor y no forman parte de la solicitud o respuesta de /api/v1/bot-run. En cada plan — Gratis incluye 1 flujo, Lite 10, Pro y superiores ilimitados.

Documento de flujo (FlowDoc)

  • name, description
  • mode: guiado | estricto
  • start_step_id: paso de entrada (debe estar definido)
  • steps: FlowStep[]
  • enabled: booleano

Estructura de paso (FlowStep)

  • id (único), name
  • goal: inyectado en el prompt del sistema para este paso
  • collect: información a solicitar antes de avanzar — el flujo conserva lo que la recopilación de datos del bot no puede guardar
  • allowed_tools: string[] | "all" | "none" — aplicado en modo estricto, orientación en modo guiado
  • allowed_agent_id: sub-agente para este paso (grupos)
  • terminal: finaliza el flujo

Transición

  • to: id del paso objetivo
  • kind: siempre | datos_completos | intención | condición | resultado_herramienta
  • intent (tipo=intención), expr (tipo=condición)
  • tool (tipo=resultado_herramienta): se activa cuando se ejecutó correctamente este turno

Estado de ejecución (FlowState)

  • flow_id, current_step_id
  • visited: ids de pasos vistos en esta sesión
  • done: el flujo alcanzó un paso terminal
  • data: respuestas que el flujo conservó (enmascaradas en las respuestas)
  • turns, step_turns: turnos en el flujo / en este paso
  • Un FlowState por sesión, avanzado cada turno; eliminado después de 90 días de inactividad

Validación del grafo

  • Al menos un paso; ids de pasos únicos
  • start_step_id debe ser un paso definido
  • Cada objetivo de transición debe existir
  • intención / condición / resultado_herramienta llevan su campo
  • Todos los pasos alcanzables desde el inicio (BFS)

Adjuntar a bot y grupo

  • Bot: bots/{botId}.flowId
  • Grupo: agentGroups/{groupId}.flowId
  • Adjuntar mediante /attach para que el campo no se elimine por la ruta de escritura del modelo
  • El motor lee flowId del documento sin procesar por turno

Ejecución en tiempo de ejecución (por turno)

  • 1. Leer flowId y cargar el flujo (flow_loader.load_flow)
  • 2. Resolver el FlowState de la sesión (iniciar en el primer turno)
  • 3. Inyectar el objetivo del paso y lo que aún necesita; el modo estricto limita allowed_tools
  • 4. Guardar cada respuesta — en el perfil, o conservada por el flujo cuando el bot no puede guardarla
  • 5. advance() evalúa las transiciones y avanza al siguiente paso
  • 6. Un paso terminal marca el flujo como completado

Versionado

  • Cada actualización crea una instantánea de la revisión anterior
  • GET .../versions lista las revisiones anteriores
  • Restaurar = cargar una revisión en el editor y Guardar
  • Mejor esfuerzo — una falla de instantánea nunca bloquea el guardado

Límites del plan

  • Cada plan tiene flujos — solo los nuevos están limitados (max_flows)
  • Gratis: 1 flujo · Starter: 3 · Lite: 10
  • Pro / Enterprise: ilimitados
  • Editar un flujo existente nunca se bloquea

RBAC

  • Lectura: cualquier miembro de la organización
  • Crear / Actualizar / Eliminar / Adjuntar: requiere la función de flujos
  • Todos los puntos finales ejecutan authorize_org (membresía de la organización)
  • Escrito solo mediante engineFetch — nunca Firestore directamente

Puntos finales de API (Python FastAPI, internos)

  • POST /v1/flows/{company_id} — crear flujo (valida el grafo)
  • GET /v1/flows/{company_id} — listar ({ flows, total })
  • GET /v1/flows/{company_id}/{flow_id} — obtener uno
  • PUT /v1/flows/{company_id}/{flow_id} — actualizar (instantánea de la revisión anterior)
  • GET /v1/flows/{company_id}/{flow_id}/versions — listar revisiones
  • DELETE /v1/flows/{company_id}/{flow_id} — eliminar
  • POST /v1/flows/{company_id}/{flow_id}/attach — vincular a bot o grupo
  • POST /v1/flows/{company_id}/detach — desvincular de bot o grupo

Todos los puntos finales requieren authorize_org(request, company_id). Las mutaciones requieren un administrador o propietario; las creaciones cuentan contra max_flows. Internos (gestionados por el panel), no REST público.

Forma de Firestore

{envRoot}/flows/{flowId}
  |- name, description
  |- mode: guided | strict
  |- start_step_id: string
  |- steps: [{ id, name, goal, collect[],
  |            allowed_tools, allowed_agent_id?,
  |            transitions: [{ to, kind, intent?, expr?, tool? }],
  |            terminal }]
  +- enabled: bool

{envRoot}/bots/{botId}
  +- flowId: string | null

{envRoot}/agentGroups/{groupId}
  +- flowId: string | null

Detalles rastreados (estado)

Detalles tipados que un bot recuerda y mantiene actualizados mientras habla — configúralos en Bots → tu bot → Memoria. Cada detalle se recuerda para esta conversación, esta persona (en todas sus conversaciones) o todos (un valor compartido). El bot los ve en su prompt y los cambia con su herramienta update_state; los prompts usan {{state.key}}; tus sistemas los leen y cambian con la API a continuación. Cada cambio es una revisión que puedes restaurar. El esquema se edita en Prueba y se publica en Producción como el resto del bot; los valores son datos de ejecución en cada entorno.

Tipos y comportamiento de actualización

  • texto, número, booleano, fecha (ISO 8601), opción, lista (de texto, números u objetos), objeto
  • replace, keep_first — cualquier tipo
  • increment, max, min — números (máx/mín también fechas)
  • append, append_unique — listas
  • merge — objetos (RFC 7396: un null elimina una clave)
  • Reglas opcionales: rango numérico, longitud y patrón de texto, tamaño de lista, JSON Schema (Borrador 2020-12) para objetos

API

Usa una clave de API con el alcance state:read o state:write. La organización y el entorno de la clave se aplican; una clave restringida a un bot solo alcanza ese bot. El sujeto es un id de conversación (session), tu id de usuario final (person) o shared (bot).

GET/api/v1/state/{botId}/configLos detalles rastreados del bot
GET/api/v1/state/{botId}/records?scope=&limit=Registros cambiados recientemente
GET/api/v1/state/{botId}/records/{scope}/{subjectId}Valores de un registro
PATCH/api/v1/state/{botId}/records/{scope}/{subjectId}Cambiar valores (atómico; todo o nada)
GET/api/v1/state/{botId}/records/{scope}/{subjectId}/revisionsHistorial, más reciente primero
POST/api/v1/state/{botId}/records/{scope}/{subjectId}/restoreRestaurar una revisión (como una nueva)
DELETE/api/v1/state/{botId}/records/{scope}/{subjectId}Eliminar un registro y su historial
PUT/api/v1/state/{botId}/configReemplazar el esquema (claves de Prueba)
curl -X PATCH https://rylvo.com/api/v1/state/bot_123/records/person/user_42 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-shipped-9921" \
  -d '{
    "ops": [
      { "field": "plan", "op": "replace", "value": "pro" },
      { "field": "orders", "op": "update", "value": 1 },
      { "field": "coupon", "op": "clear" }
    ],
    "expectedRevision": 7
  }'

update aplica el comportamiento de actualización del detalle, replace establece el valor exacto, clear lo elimina. values es una abreviatura para un update por clave. expectedRevision hace que la escritura falle con 409 (y la revisión actual) si algo cambió desde que lo leíste; un valor rechazado es un 422 con una razón por campo. Las respuestas ejecutadas por el bot incluyen el state y stateEvents del turno cuando la clave tiene un alcance de estado.

Conversaciones: reglas y transferencia

Iniciar una nueva conversación cuando…

  • Una regla observa un detalle de conversación o persona: se convierte en un valor, cambia, se establece o se borra
  • Se activa una vez, en el cambio — no mientras el valor permanece igual
  • Cambiado por el bot: la conversación termina después de su respuesta (se le informa al bot, para que concluya)
  • Cambiado por tus sistemas o un compañero: la conversación abierta de la persona termina; la respuesta indica cuántas (sessionsEnded)
  • El siguiente mensaje de la persona inicia una nueva conversación; los rastros muestran la regla

Transferir a la siguiente conversación

  • Los detalles de conversación comienzan vacíos en cada nueva conversación
  • Marca uno para transferir y la siguiente conversación comienza con su último valor (p. ej., el pedido que se está manejando)
  • Copiado una vez, antes de la primera respuesta, como su propia revisión — nunca sobre un valor ya presente
  • Los detalles de persona siempre se mantienen entre conversaciones

Memoria más allá de los últimos mensajes

En Bots → tu bot → Sesiones, la ventana de memoria establece cuántos mensajes recientes lleva una respuesta. Un presupuesto de tokens también los mantiene dentro de esa cantidad de tokens, más recientes primero, para que unos pocos mensajes largos no desplacen al resto. Resumir mensajes más antiguos pliega los mensajes que salen de la ventana en un resumen continuo que el bot ve en cada turno — actualizado después de las respuestas, cada pocos mensajes, en el modelo propio del bot. Los rastros muestran cuándo una respuesta usó el resumen o el presupuesto dejó mensajes fuera.

Varios mensajes a la vez (doble mensaje de texto)

En Bots → tu bot → Sesiones, elige qué sucede cuando alguien envía otro mensaje mientras el bot aún está respondiendo:

  • Responder en orden (predeterminado) — una respuesta a la vez; el siguiente mensaje se responde después de la respuesta anterior, teniéndolo en cuenta
  • Esperar y responder juntos — espera un momento (1–15 s) después del último mensaje y responde mensajes rápidos en una sola respuesta; fotos y notas de voz nunca se combinan (en la API y Beam, los mensajes se responden en orden)
  • Responder solo el primero — los mensajes enviados durante la respuesta reciben un aviso breve en los canales; la API responde 409 conversation_busy con Retry-After
  • Responder cada uno de inmediato — sin coordinación; las respuestas pueden superponerse

La coordinación es por usuario final y conversación, en cada servidor. Nunca pierde un mensaje: un mensaje de canal que ha esperado 45 segundos se responde de todos modos, y una llamada de API espera hasta 25 segundos antes de conversation_busy. Las llamadas sin endUserExternalId no se coordinan.

Contexto de ejecución

Envía hechos que tu aplicación conoce con un mensaje — el plan de la persona, la página en la que está — como context en la ejecución del bot (un objeto JSON, hasta 16 KB). El bot lo ve solo para ese mensaje, los prompts usan {{context.plan}} o {{context.account.tier}}, y no se almacena nada — los rastros conservan solo los nombres de las claves. Establece un JSON Schema en Memoria → Contexto de ejecución y una solicitud que no coincida recibe un 422 con las razones en details.problems, antes de que el bot se ejecute. El contexto enviado desde el widget se ignora.

curl -X POST https://rylvo.com/api/v1/bot-run \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "botId": "bot_123",
    "endUserExternalId": "user_42",
    "message": "Can I add a seat?",
    "context": { "plan": "pro", "seats": 4, "page": "/billing" }
  }'

Memoria a largo plazo

Los detalles rastreados son campos que tú defines. La memoria a largo plazo es todo lo demás que vale la pena saber la próxima vez (las preferencias de una persona, su situación, lo que sucedió), guardado como frases cortas que el bot lee cuando son relevantes. Actívala en la pestaña Memoria del bot (Prueba y luego publica).

  • Acerca de cada persona: se conserva en todas sus conversaciones con el bot (requiere endUserExternalId). Compartida: es verdadera para todos, como un cuaderno de equipo; los nuevos recuerdos compartidos que el bot guarda pueden esperar la revisión de un compañero.
  • Cómo se crean: el bot las guarda y corrige mientras conversa (sus herramientas remember y forget), y cuando termina una conversación, una IA la lee y guarda lo que vale la pena recordar, siguiendo tus instrucciones. Tu aplicación y tus compañeros también pueden añadirlas.
  • Cómo se usan: en cada mensaje, al bot se le muestran los recuerdos más cercanos en significado (los fijados primero), hasta el número que elijas; puede buscar el resto.
  • Mantenimiento: un recuerdo nuevo que dice lo que ya dice uno existente lo actualiza en lugar de duplicarlo; los recuerdos de una persona pueden olvidarse tras días sin uso; borrar a una persona elimina los suyos en todas partes.
GET/api/v1/memory/{botId}/memories?scope=person&subjectId=…Los recuerdos de una persona (o scope=shared)
POST/api/v1/memory/{botId}/memoriesRecordar algo
PATCH/api/v1/memory/{botId}/memories/{memoryId}Corregir, fijar, etiquetar o aprobar
DELETE/api/v1/memory/{botId}/memories/{memoryId}Eliminar uno
POST/api/v1/memory/{botId}/searchBuscar por significado
DELETE/api/v1/memory/{botId}/people/{subjectId}Olvidar todo sobre una persona
# Tell the bot something about a customer, from your backend
curl -X POST https://rylvo.com/api/v1/memory/bot_123/memories \
  -H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"scope": "person", "subjectId": "user_42", "text": "Upgraded to the Pro plan on 3 Oct 2026.", "kind": "event"}'

# What does the bot remember about their billing?
curl -X POST https://rylvo.com/api/v1/memory/bot_123/search \
  -H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"query": "billing and plan", "subjectId": "user_42"}'

Usa una clave con memory:read o memory:write. Con memory:read, las respuestas ejecutadas por el bot también incluyen memory: los recuerdos que se le mostraron al bot y lo que cambió. Un espacio completo responde 409; cuando la memoria a largo plazo está desactivada, las escrituras responden 422.

Código personalizado

Ejecuta tu propio código en cinco puntos de cada conversación, desde la pestaña Código del bot (Prueba y luego publica): en tu servidor — Rylvo envía JSON por POST a tu endpoint HTTPS, firmado — o en Rylvo — escribes un módulo de JavaScript y Rylvo lo ejecuta en un sandbox (nuevo por llamada, tu límite de tiempo, 32 MB, fetch solo a los hosts que permitas, secretos como ctx.secrets.NAME). En cualquier caso, Rylvo usa lo que respondas. Cada campo de una respuesta es opcional: un {} vacío no cambia nada.

EtapaCuándoPuedes responder
on_session_startPrimer mensaje de una conversacióncontext, instructions, state
before_turnCada mensaje, antes del modelocontext, instructions, state, reply, block
retrieveCada mensaje, junto con la base de conocimientopassages
after_turnDespués de que el bot responda, antes de enviarloreply, state, endConversation
on_session_endUna conversación terminó (reintentada)— (respuesta ignorada)
  • context — hechos que el bot ve para este mensaje (se une al contexto de ejecución); instructions — reglas adicionales para esta respuesta.
  • state — valores de detalles rastreados para guardar, como tus sistemas (el escritor de la API), p. ej. {"plan": "pro"}.
  • reply — responde tú mismo (sin llamada al modelo) o, después del turno, reemplaza la respuesta del bot; block — rechaza con tu mensaje.
  • passages — hasta 10 {title, text, url?, score?} en los que el bot basa su respuesta, citados como extractos de la base de conocimiento.
  • endConversation — true o {"reason": "…"}: el siguiente mensaje de la persona inicia una conversación nueva.
// What your endpoint receives (before_turn)
{
  "stage": "before_turn", "deliveryId": "msg_…", "test": false,
  "bot": { "id": "bot_123", "name": "Support" }, "environment": "production",
  "conversation": { "id": "conv_8f2a91", "channel": "widget" },
  "person": { "id": "user_42" },
  "message": { "text": "Where is my order A-1042?" },
  "transcript": [{ "role": "user", "text": "Hi" }, { "role": "assistant", "text": "Hello!" }],
  "state": { "session": { "order_id": null }, "person": { "plan": "free" } },
  "context": { "page": "/orders" }
}

Las llamadas se firman con el secreto de firma del bot (uno por entorno, en la pestaña Código) usando el esquema Standard Webhooks — webhook-id, webhook-timestamp, webhook-signature — para que cualquier biblioteca de Standard Webhooks las verifique. Responde dentro del límite de tiempo de la etapa (500 ms–10 s); cuando tu endpoint falla, el bot continúa sin él o, si así lo elegiste para before/after, envía tu mensaje de respaldo. Las direcciones internas nunca se llaman. Cada llamada aparece como un paso "Tu código" en el trace.

// On Rylvo: the whole stage is this module
export default async function (event, ctx) {
  const r = await fetch("https://api.yourshop.com/orders?person=" + event.person?.id, {
    headers: { authorization: "Bearer " + ctx.secrets.SHOP_KEY },
  });
  const [order] = await r.json();
  return order ? { context: { order_status: order.status, eta: order.eta } } : {};
}

En tu servidor, verifica la firma primero:

import { Webhook } from "standardwebhooks";
const wh = new Webhook(process.env.RYLVO_SIGNING_SECRET); // whsec_…

app.post("/rylvo/stage", express.raw({ type: "application/json" }), (req, res) => {
  const event = wh.verify(req.body, req.headers); // throws if forged or stale
  if (event.stage === "before_turn" && /order/i.test(event.message.text)) {
    const order = lookUpOrder(event.person?.id);
    return res.json({ context: { order_status: order.status, eta: order.eta } });
  }
  res.json({});
});

API de sesiones

Las conversaciones de un bot, para tu backend: listarlas y buscarlas — por persona, por si han terminado o por sus detalles rastreados — leer una con su transcripción, terminarla o bifurcarla en una copia para continuar desde allí. Usa una clave de API con el alcance sessions:read o sessions:write; una clave restringida a un solo bot solo alcanza a ese bot.

GET/api/v1/sessions?botId=…Más recientes primero; endUserExternalId, status=open|ended, state.<key>=<value>, limit, before
GET/api/v1/sessions/{sessionId}?botId=…La conversación y su transcripción
POST/api/v1/sessions/{sessionId}/endTerminarla; el siguiente mensaje de la persona inicia una nueva
POST/api/v1/sessions/{sessionId}/forkUna copia con la transcripción y los detalles rastreados
# Open conversations about a refund
curl "https://rylvo.com/api/v1/sessions?botId=bot_123&status=open&state.issue_type=Refund" \
  -H "Authorization: Bearer YOUR_API_KEY"

# End one, leaving a note the next conversation can carry
curl -X POST https://rylvo.com/api/v1/sessions/conv_8f2a91/end \
  -H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"botId": "bot_123", "note": "Refund issued; tracking number sent."}'

# Fork it from an earlier point to try a different reply
curl -X POST https://rylvo.com/api/v1/sessions/conv_8f2a91/fork \
  -H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"botId": "bot_123", "throughMessageId": "m_41", "stateRevision": 3}'

Una bifurcación no tiene canal propio, así que nada llega a nadie hasta que envíes un mensaje con ejecución del bot y su sessionId — con el mismo usuario final, entonces se convierte en su conversación actual. Terminar es idempotente; la nota se convierte en el resumen de cierre, que se lleva a la siguiente conversación cuando la continuidad del bot es "perfil + resumen".

Conjuntos de datosSolo panel

Los conjuntos de datos son colecciones curadas de traces o perfiles de usuarios finales para análisis, revisión y colaboración en equipo. Gestiona desde Panel → Conjuntos de datos.

Conjuntos de datos de traces

Fija traces canónicos en una colección compartida para depuración, pruebas de regresión o revisión cualitativa.

  • Fija desde la página de Traces o explora traces no fijados dentro del conjunto de datos
  • Fuente del trace: canonical, legacy o dashboard
  • Reproducción de trace en línea + panel de detalles
  • Hilo de comentarios compartido con la página de Traces
  • Archivo suave o eliminación definitiva de un conjunto de datos

Conjuntos de datos de personas

Agrupa perfiles de usuarios finales para segmentación, revisión de cohortes o exportación.

  • Recopila perfiles de usuarios finales desde Audiencia
  • Vista de detalles de solo lectura por perfil
  • Reutiliza para segmentación de audiencia de difusión

Retención y cuotas

PlanMáx. conjuntos de datosMáx. traces conservados
Gratis150
Starter1200
Lite105,000
Pro5025,000
Enterprise∞∞

Permisos

  • Viewer+ — ver conjuntos de datos
  • Operator+ — crear, editar, archivar, fijar/desfijar traces
  • Admin — eliminar definitivamente el conjunto de datos y todos los elementos fijados

Eliminar un conjunto de datos quita los fijados y el documento del conjunto. Los traces fijados en sí quedan sujetos a la política de retención normal de la organización, así que elimina con cuidado.

Entrega de correoSolo panel

Rylvo gestiona sus propios correos transaccionales (bienvenida, invitaciones de equipo, informes programados, alertas operativas) automáticamente. Las plantillas tienen marca y son conscientes del tema: no hay nada que configurar.

Para enviar tus propios correos en eventos de flujo de trabajo (p. ej., notificar a un humano cuando una sesión escala), usa un Conector de eventos o añade un canal de Correo en Automatización.

Clientes OAuthSolo panel

Servidor de autorización OAuth 2.1 de servidor a servidor para autenticación de clientes MCP (Protocolo de Contexto de Modelo). Permite que los editores de IA (Claude Code, Cursor, Windsurf, Zed) se autentiquen con Rylvo y accedan a la API de herramientas MCP. Implementa RFC 6749, 7636 (PKCE), 7591 (DCR), 7009 (revocación), 7662 (introspección), 8414 (metadatos), 8707 (vinculación de audiencia), 9728 (recurso protegido). Gestiona desde Panel → Integraciones.

Documento de registro de clientes

  • clientId: "client_" + 12 caracteres aleatorios base64url
  • clientName (1-200), redirectUris []
  • grantTypes: authorization_code, refresh_token
  • tokenEndpointAuthMethod: none | client_secret_post
  • clientSecretHash: hash SHA-256 (null para clientes públicos)
  • Colección global (no limitada por organización); el secreto en texto plano nunca se persiste

Tipos de clientes y gestión de secretos

  • Público (solo PKCE): no se emite secreto, authMethod="none"
  • Confidencial: secreto aleatorio base64url de 32 bytes, authMethod="client_secret_post"
  • El secreto se devuelve UNA VEZ en la respuesta DCR; solo se almacena el hash SHA-256
  • Comparación en tiempo constante (timingSafeEqual) previene ataques de temporización

Tipos de concesión y flujo de tokens

  • Código de autorización (PKCE requerido): authorize → consent → intercambio de tokens
  • Rotación de tokens de actualización: transacción atómica de Firestore (revocar antiguo, emitir nuevo)
  • ID de organización incrustado en token autodescriptivo: rfr_{base64url(orgId)}~{random}
  • Protección CSRF: HMAC-SHA256 en el formulario de consentimiento

Duración de tokens

  • Token de acceso: 24 horas (JWT RS256, vinculado a audiencia https://rylvo.com/mcp)
  • Token de actualización: 30 días con ventana deslizante (rotado en cada uso)
  • Límite absoluto de la familia de tokens de actualización: 365 días
  • Código de autorización: 10 minutos

Alcances (3)

  • rylvo:read — ver bots, análisis, conversaciones, base de conocimiento
  • rylvo:write — crear/actualizar bots, prompts, conocimiento, configuraciones
  • rylvo:admin — gestionar configuraciones de organización, miembros, integraciones
  • Predeterminado: "rylvo:read rylvo:write"

Características de seguridad

  • Firma JWT RS256 con versionado de claves (OAUTH_JWT_PRIVATE_KEY_PEM en producción)
  • PKCE S256 requerido (plain rechazado en producción)
  • Vinculación de audiencia (RFC 8707) previene ataques de diputado confundido
  • Vinculación de entorno: una concesión autoriza un entorno, elegido en el consentimiento y llevado en el token; el refresh no puede renegociarlo
  • Cabeceras: HSTS, X-Frame-Options DENY (widget exceptuado), CSP report-only
  • Seguimiento de JTI revocados: Firestore + LRU en memoria (máx. 10k)

Estrategia de caché

  • Metadatos de cliente: TTL de 5 min, máx. 5,000 entradas
  • Validación JWT: negativa (spam de 5s) + positiva (consciente de revocación de 2s), máx. 10k cada una
  • Sesión de Firebase: TTL de 30s, máx. 2,000 entradas
  • Revocación JTI: LRU en memoria, máx. 10,000 entradas

RBAC y límites de plan

  • oauthClients.view — viewer+ (todos los miembros)
  • oauthClients.revoke — admin+ (admin o propietario)
  • Las colecciones OAuth son solo de servidor (escrituras de Admin SDK)
  • NO limitado por plan — disponible en todos los planes (gratis → enterprise)
  • Los filtros de revocación oauthRefreshTokens.clientId por colección — el índice automático de campo único lo cubre

Endpoints de API (estándar OAuth 2.1)

  • GET /.well-known/oauth-authorization-server — metadatos RFC 8414 (30/min por IP)
  • GET /.well-known/jwks.json — JWKS RFC 7517
  • GET /oauth/authorize — endpoint de autorización (HTML de consentimiento, 30/min por IP)
  • POST /oauth/authorize/consent — envío de consentimiento (15/min por usuario)
  • POST /oauth/token — endpoint de token (10/min por client_id)
  • POST /oauth/register — Registro Dinámico de Clientes (5/min por IP)
  • POST /oauth/revoke — revocación de token (10/min por IP)
  • POST /oauth/introspect — introspección de token (30/min por IP)

Panel: GET /api/v1/oauth-clients/{orgId} (lista), POST /api/v1/oauth-clients/{orgId}/{clientId}/revoke (admin+).

Estructura de Firestore

oauthClients/{clientId}  (global, not org-scoped)
  |- clientId, clientName (1-200), redirectUris[]
  |- grantTypes[], tokenEndpointAuthMethod, scope
  |- clientSecretHash (SHA-256 | null for public)
  +- createdAt: number (unix seconds)

oauthAuthCodes/{codeHash}  (keyed by SHA-256 hash)
  |- orgId, userId, clientId, redirectUri, scope
  |- codeChallenge, codeChallengeMethod
  |- expiresAt (10 min TTL), used, consumedAt?
  +- createdAt

environmentRoot(orgId, environment)/oauthRefreshTokens/{tokenHash}
organizations/{orgId}/oauthRefreshTokens/{tokenHash}  (unbound legacy)
  |- userId, clientId, scope
  |- environment: test | production | null (grant binding)
  |- expiresAt (30d sliding), familyMaxExpiresAt (365d ceiling)
  |- revoked, revokedAt?
  +- createdAt
  Token format: rfr_{base64url({o:orgId,e:environment})}~{random}

organizations/{orgId}/oauthRevokedJtis/{jti}
  |- revokedAt
  +- expiresAt (24h, access token TTL)

TTL policies REQUIRED: authCodes (10m), refreshTokens (30d), revokedJtis (24h)

Conectores de webhook

Los conectores permiten que Rylvo llame a tus sistemas durante la ejecución del flujo de trabajo. Registra endpoints de webhook para llamadas de herramientas, sincronización de estado o notificaciones de eventos: Rylvo gestiona autenticación, reintentos y firma.

Tres tipos de conectores

Herramienta

Ejecuta acciones en tus sistemas (crear caso, consultar pedido, verificar inventario)

Sincronización de estado

Lee/escribe el estado del flujo de trabajo desde tu base de datos antes y después de decisiones

Evento

Recibe notificaciones sobre escalamiento, cambio de etapa, fallo de verificación

Registrar un conector de herramienta

curl -X POST https://rylvo.com/api/v1/connectors \
  -H "X-API-Key: YOUR_KEY" -H "Content-Type: application/json" \
  -d '{
    "company_id": "comp_001",
    "connector_type": "tool",
    "name": "Salesforce Case Creator",
    "auth": {
      "auth_type": "api_key",
      "api_key_header": "X-Salesforce-Key",
      "api_key_value": "your_salesforce_api_key"
    },
    "tool_config": {
      "tool_name": "create_salesforce_case",
      "tool_description": "Create a case in Salesforce",
      "input_schema": { "type": "object", "properties": { "issue_summary": { "type": "string" } } }
    },
    "endpoint": { "url": "https://your-app.com/rylvo/tools/create-case", "method": "POST" }
  }'

Endpoints de API

MétodoRutaDescripción
POST/v1/connectorsCrear conector
GET/v1/connectors/{company_id}Listar conectores
GET/v1/connectors/{company_id}/{id}Obtener detalle
PATCH/v1/connectors/{company_id}/{id}Actualizar
DELETE/v1/connectors/{company_id}/{id}Eliminar
POST.../{id}/activateActivar
POST.../{id}/deactivateDesactivar
POST.../{id}/testProbar endpoint
POST/v1/connectors/generate-secretGenerar secreto HMAC
GET/v1/connectors/{company_id}/tools/availableListar herramientas de webhook

7 métodos de autenticación

noneapi_keybearer_tokenhmac_sha256basicoauth2_client_credentialscustom_header

11 tipos de eventos suscribibles

lead.capturedworkflow.decision.completedworkflow.decision.failedworkflow.escalation.triggeredworkflow.stage.changedtool.execution.completedtool.execution.failedstate.updatedverification.failedsession.startedsession.closed

Envía cada lead a tu CRM

Cuando un asistente captura una dirección de correo electrónico o un número de teléfono, Rylvo registra el lead, notifica a los propietarios del espacio de trabajo y dispara lead.captured a cada conector de eventos suscrito. Crea un conector Event, marca Lead Captured y pega la URL de un "Catch Hook" de Zapier, un webhook personalizado de Make, un nodo Webhook de n8n o un disparador de webhook entrante de GoHighLevel. Mapea los campos una vez; cada nuevo lead llega allí como contacto.

{
  "event_id": "evt_lead_…",          // stable per lead — dedupe on it
  "event_type": "lead.captured",
  "bot_id": "…",
  "data": {
    "lead_id": "…",
    "email": "casey@example.com",
    "phone": null,
    "name": "Casey Morgan",
    "fields": { "email": "…", "full_name": "…", "need": "…" },
    "first_message": "Do you do implants?",
    "bot_name": "Acme Dental Assistant",
    "channel": "widget",
    "conversation_id": "…",
    "lead_url": "https://rylvo.com/dashboard/leads",
    "captured_at": "2026-09-23T10:00:00.000Z"
  }
}

Las entregas están firmadas (Standard Webhooks), se reintentan y se pueden reproducir desde el registro de entregas del conector. Los leads capturados en el entorno de Test nunca se entregan.

SDK de Python para conectores

Métodos convenientes tipados para todas las operaciones de conectores. Se incluyen variantes síncronas y asíncronas.

from core.connectors.sdk import ConnectorSDK

sdk = ConnectorSDK(base_url="https://rylvo.com", api_key="rylv_...")

# Register a tool connector
connector = sdk.create_tool_connector(
    company_id="comp_001",
    name="Salesforce Case Creator",
    endpoint_url="https://your-app.com/rylvo/tools/create-case",
    tool_name="create_salesforce_case",
    tool_description="Create a case in Salesforce",
    auth_type="api_key",
    api_key_header="X-Salesforce-Key",
    api_key_value="your_salesforce_api_key",
)

# Test + activate
test = sdk.test_connector("comp_001", connector["connector_id"])
if test["success"]:
    sdk.activate("comp_001", connector["connector_id"])

# List available tools
tools = sdk.list_available_tools("comp_001")
print(f"{tools['total']} webhook tools available")

Variante asíncrona

from core.connectors.sdk import AsyncConnectorSDK

async with AsyncConnectorSDK(base_url="...", api_key="...") as sdk:
    connector = await sdk.create_event_connector(
        company_id="comp_001",
        name="Slack Alerts",
        endpoint_url="https://hooks.slack.com/...",
        event_types=["workflow.escalation.triggered"],
    )
    await sdk.activate("comp_001", connector["connector_id"])

Manejo de errores

ConnectorNotFoundError (404)El conector no existe

ConnectorAuthError (401/403)Clave API inválida o faltante

ConnectorValidationError (422)Configuración de conector inválida

ConnectorSDKError (5xx)Clase base para todos los errores del SDK

CanalesSolo panel

Configuración de despliegue de bots multicanal. Se admiten 13 tipos de canal: despliega tu bot en widgets de sitio web, WhatsApp, Slack, Telegram, Discord, MS Teams, Messenger, Instagram, SMS, LINE, Email o webhooks personalizados. Se permiten múltiples configuraciones por bot, pero solo una habilitada por tipo de canal. Incluye monitoreo de salud, cifrado de secretos, idempotencia de webhooks y protección contra condiciones de carrera. Gestiona desde Panel → Desplegar.

13 tipos de canal

  • widget — Chat de sitio web (orígenes, color de acento, saludo, posición, marca)
  • whatsapp — Meta Cloud API (phoneNumberId, verifyToken)
  • slack — (teamId, botUserId, signingSecret, channels[])
  • telegram — (botId, webhookSecret, allowedChatIds, collectFeedback)
  • discord — (applicationId, publicKey, guildId, commandName)
  • msteams — (appId, appPasswordPrefix, tenantId)
  • messenger — (pageId, verifyToken, appSecretPrefix)
  • instagram — (igUserId, verifyToken, appSecretPrefix)
  • sms_twilio — (accountSid, fromNumber, messagingServiceSid?)
  • whatsapp_twilio — (igual que SMS, el conector agrega prefijo whatsapp:)
  • line — (channelId, channelSecret, channelAccessToken, botUserId)
  • email_inbound — (inboxAddress, fromAddress, replyMode, Resend)
  • custom — (inboundSecret, label?)

Máquina de estados del estado de configuración

  • needs_setup → verified, deprecated (incompleto; no se puede habilitar)
  • verified → live, deprecated (prueba superada; se puede habilitar)
  • live → verified, deprecated (habilitado y recibiendo)
  • deprecated → verified, needs_setup (restaurable)
  • enabled solo permitido cuando setupStatus está en [verified, live]
  • La primera prueba exitosa promueve automáticamente a live (si no hay un hermano habilitado)

Regla de uno-habilitado-por-tipo

  • Aplicada en la capa API mediante transacciones de Firestore (runTransaction)
  • Al crear/parchear con enabled=true: consulta configuraciones habilitadas existentes con el mismo botId + channelType
  • Devuelve 409 Conflict si se encuentra un duplicado
  • Las reglas de Firestore aplican inmutabilidad de botId y channelType

Monitoreo de salud

  • Estado: ok | error | idle
  • 3+ errores consecutivos cambian el estado a "error"
  • Notificación fan-out en el primer error y en 3 seguidos; enfriamiento de 15 minutos
  • Registro de eventos de solo anexión (últimos 10 eventos, búfer circular) elimina el punto caliente RMW
  • Rastrea inboundCount, outboundCount, errorCount, consecutiveErrors

Almacenamiento de secretos y redacción

  • Tokens completos en variables de entorno (p. ej., TELEGRAM_BOT_TOKEN_{prefix})
  • Tokens cifrados en Firestore como blobs AES-256-GCM v1:
  • Prefijos de token (primeros 8 caracteres) almacenados en texto plano para visualización
  • Las respuestas GET eliminan campos cifrados antes de enviarlos al cliente
  • Orden de resolución: variable de entorno → Firestore cifrado → texto plano heredado

Idempotencia de webhooks

  • Caché de huellas digitales de 24 horas en /dedup/{fingerprint}
  • Formato: {channel}:{platform_id} (p. ej., telegram:12345)
  • Los reintentos de plataforma son seguros: los duplicados se reconocen silenciosamente
  • TTL: 24 horas (política TTL de Firestore)

Flujo de webhook entrante (14 pasos)

  • 1-4: Almacenar cuerpo, analizar, reconocimiento temprano, verificación de firma preconfiguración
  • 5-8: Interruptor de apagado, búsqueda de canal, suspensión de organización, límite de tasa por organización (60 cap / 120/min)
  • 9-12: Reconocimiento postconfiguración, analizar a NormalizedInbound, resolución de sesión, verificación de deduplicación
  • 13-14: Registrar entrante, ejecutar turno del bot + enviar respuesta (3 reintentos) + registrar saliente/error
  • Todo síncrono dentro de la solicitud de webhook (tiempo de espera de 15 s)
  • Caso especial de Discord: devuelve type:5 (pensando) inmediatamente, se ejecuta en segundo plano

RBAC y límites de plan

  • channels.view — viewer+ (lectura)
  • channels.manage — admin+ (crear/actualizar/eliminar)
  • channels.test — operator+ (probar conexión)
  • channels.rotate_secret — admin+ (rotar secretos)
  • Sin límites de canal por plan: ilimitado por plan
  • La subcolección de salud es de solo lectura para clientes (escrituras solo de servidor)

Endpoints de API (BFF Next.js)

  • POST /api/channels — crear configuración de canal (admin)
  • GET /api/channels?orgId=…&botId=…&channelType=…&enabled=… — listar (viewer)
  • GET /api/channels/{configId} — obtener uno (viewer)
  • PATCH /api/channels/{configId} — actualizar (admin)
  • DELETE /api/channels/{configId} — eliminar (admin)
  • POST /api/channels/test — probar conexión (operator)

Endpoints de webhook: /api/channels/{telegram,whatsapp,slack,discord,sms,whatsapp_twilio,line,messenger,instagram,msteams,email_inbound,custom}

Forma de Firestore

{envRoot}/botChannelConfigs/{configId}
  |- botId (immutable), botName, channelType (immutable)
  |- enabled, requireExplicitConsent, defaultConsentScope
  |- config: <channel-specific config object>
  |- setupStatus: needs_setup | verified | live | deprecated
  |- lastTestedAt?, lastVerifiedAt?, apiKeyId?
  |- createdBy, createdAt, updatedAt

{envRoot}/botChannelConfigs/{configId}/health/main
  |- status: ok | error | idle
  |- lastInboundAt, lastOutboundAt, lastErrorAt
  |- lastErrorMessage (500 chars max)
  |- inboundCount, outboundCount, errorCount, consecutiveErrors
  |- recentEvents[]: { ts, kind: inbound|outbound|error, summary } (last 10)
  |- updatedAt, lastNotifiedAt?

{envRoot}/botChannelConfigs/{configId}/dedup/{fingerprint}
  |- createdAt, expireAt (24h TTL)

{envRoot}/botChannelConfigs/{configId}/health/events/log/{docId}
  |- (append-only event log, eliminates RMW hotspot)

{envRoot}/channelMediaAssets/{assetId}
  |- expiresAt (max 30 days), GCS blob reference

Captura de imágenes y vozSolo panel

Los clientes pueden enviar fotos, capturas de pantalla, documentos y notas de voz, y el bot las lee y escucha. La extracción se ejecuta con tu propia clave de LLM, como el resto de la capa de inteligencia: no hay margen por archivo.

Activación

Está desactivado por defecto en cada bot nuevo. Habilita imágenes y audio por bot en el editor de bots, y establece reglas a nivel de espacio de trabajo en Configuración → Captura de medios: qué tipos de adjuntos están permitidos, límites de tamaño y duración, cuán rigurosamente se eliminan los datos personales de las transcripciones y si los archivos de clientes pueden almacenarse en reposo.

Dónde funciona

Cada canal desplegado: Telegram, WhatsApp (Cloud API y Twilio), Slack, Discord, MS Teams, Messenger, Instagram, LINE, SMS/MMS y Email entrante — además del widget de sitio web, el chat del panel y el parámetro attachments en /v1/bot-run.

Cómo se lee cada tipo

  • Imágenes y capturas de pantalla — un modelo de visión transcribe el texto visible y describe lo que hay en la imagen.
  • Notas de voz — se transcriben a texto y luego se manejan como cualquier otro mensaje. Las respuestas son texto; el bot no habla de vuelta.
  • Documentos — PDF, Word, PowerPoint y hojas de cálculo se leen desde su propia capa de texto, que es exacta y no cuesta nada. Un documento escaneado sin capa de texto recurre al modelo de visión.

Qué cuesta

Cada plan incluye una asignación mensual de imágenes y minutos de voz (ver precios). El audio se factura en minutos completos, redondeados hacia arriba por clip. Leer la capa de texto de un documento no usa asignación alguna. El mismo archivo enviado dos veces solo se procesa una vez.

Manejo y límites

  • Los metadatos de ubicación y dispositivo se eliminan de las fotos antes de almacenarse.
  • Los datos personales se eliminan del texto extraído antes de almacenarse o enviarse a un modelo. Los nombres no se eliminan: eso requiere reconocimiento de nombres que no ejecutamos.
  • Los archivos almacenados expiran según la ventana de retención de tu plan, y el texto extraído expira con ellos.
  • El texto encontrado dentro de una imagen se trata como datos, nunca como instrucciones para el bot.
  • 25 MB por adjunto. Las grabaciones largas pueden responderse en un mensaje de seguimiento.

MCP HubSolo panel

El MCP Hub es el registro de Model Context Protocol de Rylvo: un catálogo curado de servidores MCP que tus bots pueden usar como herramientas. Gestiona desde Panel → MCP Hub.

Qué puedes hacer

  • Descubrir e instalar servidores MCP
  • Conectar servidores externos con transportes HTTP, SSE o stdio
  • Almacenar credenciales de forma segura (cifradas en reposo)
  • Permitir servidores específicos por bot
  • Ver registros de invocación y análisis por servidor
  • Enviar tu propio servidor para revisión

Controles integrados

  • Flujo de aprobación antes de que un servidor pueda usarse en producción
  • OAuth 2.1 saliente (PKCE + DCR) para servidores orientados al usuario
  • Niveles de costo (bajo / medio / alto) mostrados antes de la invocación
  • Verificaciones de salud y desactivación automática ante fallos repetidos
  • Tokens de reanudación para llamadas de herramientas de larga duración

Build Intelligence: También puedes exponer todo el espacio de trabajo de Rylvo como un servidor MCP a Claude Code, Cursor, Windsurf, Zed o Codex. Consulta la sección Build Intelligence a continuación o visita /build-intelligence.

Build IntelligenceSolo panel

Build Intelligence permite que editores y agentes de IA controlen Rylvo directamente. Conecta Claude Code, Cursor, Windsurf, Zed o Codex CLI mediante MCP y dales más de 160 herramientas para construir bots, prompts, guardarraíles, habilidades, conexiones de base de conocimiento, conectores, canales y más. Gestiona la conexión desde Panel → Build Intelligence o visita /build-intelligence.

Clientes compatibles

  • Claude Code — comando de instalación HTTP remota + autorización /mcp
  • Cursor — configuración de servidor remoto en mcp.json
  • Windsurf — configuración de servidor remoto en mcp_config.json
  • Zed — entrada de configuración context_servers
  • Codex CLI — codex mcp add + codex mcp login
  • Otros clientes Streamable HTTP — verifica el soporte de OAuth con el cliente

Modelo de seguridad

  • OAuth 2.1 con PKCE (S256) — flujo de navegador en la primera instalación
  • Tokens de acceso JWT RS256, TTL de 24 horas
  • Los tokens de actualización rotan en cada intercambio
  • Cada llamada está limitada a la organización: el org_id del token debe coincidir con el recurso
  • Un token filtrado solo puede actuar en su organización vinculada hasta su expiración o revocación

Ejemplos de instalación

# Claude Code
claude mcp add --transport http rylvo https://rylvo.com/mcp
# Then run /mcp inside Claude Code and authenticate
// Cursor — .cursor/mcp.json or ~/.cursor/mcp.json
{
  "mcpServers": {
    "rylvo": { "url": "https://rylvo.com/mcp" }
  }
}
// Windsurf — ~/.codeium/windsurf/mcp_config.json
{
  "mcpServers": {
    "rylvo": { "serverUrl": "https://rylvo.com/mcp" }
  }
}
// Zed — settings.json
{
  "context_servers": {
    "rylvo": { "url": "https://rylvo.com/mcp" }
  }
}
# Codex CLI
codex mcp add rylvo --url https://rylvo.com/mcp
codex mcp login rylvo --scopes rylvo:read,rylvo:write

Superficie de herramientas

RecursoLecturaEscrituraEliminación
Botsbots.list, bots.getbots.create, bots.updatebots.delete
Promptsprompts.list, prompts.getprompts.create, prompts.update, prompts.set_optimizationprompts.delete
Guardarraílesguardrails.list, guardrails.getguardrails.create, guardrails.updateguardrails.delete
Pruebastests.list_cases, tests.list_runs, tests.get_run_resultstests.create_case, tests.run_suitetests.delete_case
Conectoresconnectors.list, connectors.getconnectors.create, connectors.update, connectors.testconnectors.delete
Canaleschannels.list, channels.getchannels.create, channels.update, channels.register_webhook—
Servidores MCPmcp_servers.list, mcp_servers.getmcp_servers.register, mcp_servers.updatemcp_servers.delete
Habilidadesskills.list, skills.getskills.create, skills.updateskills.delete
Base de conocimientokb.list_connections, kb.get_connectionkb.create_connection, kb.update_connection, kb.add_sourcekb.delete_connection
Grupos de agentesagent_groups.listagent_groups.create, agent_groups.add_botagent_groups.delete
Automatizacionesautomations.list_tasks, broadcasts.listautomations.create_task, broadcasts.createautomations.delete_task, broadcasts.delete

Herramientas macro

  • scaffold_bot_from_description — crear un bot + prompt de sistema + guardarraíl inicial a partir de un resumen
  • clone_bot — duplicar un bot y opcionalmente copiar recursos vinculados
  • attach_mcp_server — registrar un servidor MCP externo, escribir sus herramientas y vincularlo a bots Entitlements still apply: MCP does not bypass product access or quotas. Each tool action is checked against its scope, workspace permissions, plan availability, validation, and the same limits shown in Billing & Usage.

Workspace ArchitectSolo de Dashboard

El Architect es un agente de configuración conversacional que convierte un resumen en inglés sencillo en un workspace funcional: bots, prompts, guardarraíles, conectores, conexiones de KB, reglas de evolución y pruebas. Se ejecuta en /dashboard (pestaña Architect) y también impulsa el modo de edición en lenguaje natural y la clonación de bots.

Bucle de agente en 8 fases

1. Intención

Captura objetivo, industria, tono, restricciones de cumplimiento

2. Investigación

Extrae valores predeterminados del perfil de la organización, plantillas de industria relevantes, sesiones anteriores

3. Plano

Propone bots + flujo de trabajo + guardarraíles + KB + conectores

4. Revisión

El usuario aprueba / edita el plano en lenguaje natural

5. Generación

Escribe prompts, guardarraíles, conectores, reglas, esqueletos de KB

6. Verificación

Ejecuta automáticamente pruebas de bots en los nuevos bots y puntúa la preparación

7. Aplicación

Confirma como recursos versionados, etiquetados con source=architect

8. Entrega

Resume lo construido, enlaza a Mission Control y Playground

Otras capacidades del Architect

  • Modo edición - cambia un bot existente con una frase ("hazlo más empático, prefiere email sobre teléfono")
  • Clonación de bots - duplica un bot con modificaciones (industria, idioma, tono)
  • Pruebas de bots - el architect puede ejecutar pruebas e iterar hasta alcanzar un umbral de preparación
  • Plantillas de industria - 29 puntos de partida (soporte SaaS, KYC fintech, admisión sanitaria, etc.)
  • Relleno del perfil de organización - reutiliza valores predeterminados que configuras una vez en tu perfil de organización

Knowledge BaseSolo de Dashboard

Conecta tus fuentes de datos a Rylvo para decisiones fundamentadas y respaldadas por evidencia. La Knowledge Base ofrece ocho planos de recuperación disponibles, desde RAG Clásico y Búsqueda Híbrida hasta Self-RAG, CRAG y RAG Agéntico.

Cómo funciona

1

Añade una fuente

Sube documentos, conecta APIs o apunta a URLs. Se admiten 16 tipos de fuentes.

2

Elige un plano

Elige entre ocho estrategias de recuperación disponibles, incluyendo Búsqueda Híbrida, HyDE y Self-RAG.

3

Crea una conexión

Una conexión vincula una fuente a un plano con ajustes específicos de pipeline.

4

Consulta en el playground

Prueba la calidad de recuperación antes de ponerla en producción. Ajusta el troceado, el re-ranking y los umbrales.

Planos integrados

Recuperación de FAQConsulta de PolíticasGuía de Solución de ProblemasCatálogo de ProductosLegal / CumplimientoDocumentos de IncorporaciónReferencia MédicaAvisos FinancierosManual de RRHHManuales TécnicosPlaybook de VentasPipeline Personalizado

Características del Dashboard

Conexiones

Crea, supervisa, pausa y elimina conexiones de knowledge base

Fuentes

Gestiona 16 tipos de fuentes - subida, almacenamiento en la nube, SaaS, bases de datos, API, rastreo web

Planos

Configuraciones de pipeline de recuperación preconstruidas y personalizadas

Playground

Prueba consultas, inspecciona fragmentos recuperados, ajusta ajustes en vivo

Rendimiento

Métricas de calidad de recuperación, latencia y tasas de acierto

Ajustes

Auto-ajuste, configuración de troceado, re-ranking y ajuste de umbrales

Pila de recuperación

1

Almacén vectorial

Qdrant almacena embeddings troceados. La búsqueda por palabras clave y semántica se combinan, luego se reordenan por relevancia.

2

Descifrado BYOK

Si una fuente u organización usa una clave de proveedor BYOK, se descifra en el momento de la recuperación antes de llamar al modelo de embedding.

3

Traza de recuperación

Cada llamada de KB se registra en el almacén de observabilidad canónico como una observación de recuperador limpia por conexión, con latencia, puntuación y estrategia.

4

Citas

Las respuestas fundamentadas incluyen referencias de fuente con IDs de fragmento para que puedas auditar lo que el bot realmente vio.

5

Calificación Self-RAG (opt-in)

TypeSafe Jev califica cada pasaje recuperado como relevante o no en una sola solicitud y descarta el resto; si rechazara todos los pasajes, se conservan todos. Añade un viaje de ida y vuelta de red pero ya no gasta tus tokens de modelo. Si Jev no puede responder, el calificador LLM se ejecuta con tu clave de OpenAI.

Conversation StorageSolo de Dashboard

Trae Tu Propia Base de Datos (BYODB). Cada evento de conversación que Rylvo captura — cada mensaje, respuesta recopilada, punto de control y resumen de sesión — se entrega a una base de datos o webhook que tú posees, para que tus conversaciones vivan permanentemente en infraestructura que controlas. Los eventos salen en la ejecución de entrega cada 15 minutos; sin conexión aún, hasta 500 esperan una. Gestiona desde Dashboard → Conv. Storage.

Conexiones

Añade una o más conexiones. Cada una recibe los eventos que elijas, de los bots que elijas.

  • PostgreSQL, Supabase, Neon, PlanetScale
  • MySQL, Turso, MongoDB, Redis
  • Webhook (ninguna / clave API / Bearer / autenticación HMAC)
  • Credenciales cifradas en reposo; comprueba una conexión guardada en cualquier momento

Tablas y columnas

Cada bot escribe con una plantilla — sus tablas y la columna donde va cada valor.

  • Nueve plantillas, o columnas propias de la conexión y campos personalizados
  • Ve exactamente qué columnas escribe cada evento
  • Crea las tablas con un clic, o copia el SQL — Rylvo nunca altera una tabla

Guardados en vivo, historial de entregas, eventos fallidos

Cada evento de conversación uno a uno, y cada entrega con su resultado.

  • Por qué algo sigue esperando, por evento
  • Reintentos de webhook dentro de una ejecución (0,5 s → 1 s → 2 s), luego la siguiente ejecución
  • Inspecciona la carga útil exacta que se envió
  • Después de 10 ejecuciones fallidas, los eventos pasan a Eventos fallidos — reprodúcelos o descártalos
  • Test y Producción están separados — sigue el interruptor de entorno

Retención

Cuánto tiempo mantiene Rylvo su historial de entregas (cada registro lleva el contenido del evento). Extiéndelo con un complemento de retención, o acórtalo.

Lite14 días

Pro90 días

EnterpriseIlimitado

Aislamiento Producción / Test

Cada evento de almacenamiento lleva un discriminador source:channel (en vivo), playground (chat de dashboard) o test_suite (evaluación automatizada). El tráfico en vivo aterriza en Producción y los chats de dashboard en Test — cada uno con sus propias conexiones, cola e historial. Cada página de Conversation Storage sigue el interruptor de entorno.

En vivo (canal)

  • Tráfico de canales desplegados: Telegram, WhatsApp, widget, API, etc.
  • Escribe en tablas base (p. ej. rylvo_conversations)
  • Usa la clave de cortacircuitos de producción
  • Se cuenta contra los eventos de almacenamiento de tu plan

Test (playground)

  • Turnos de Bot Chat / Group Chat del Dashboard
  • Escribe en tablas con sufijo (predeterminado *_test)
  • Sufijo configurable por destino o testDatabaseName opcional
  • Clave de cortacircuitos separada — las tablas de test faltantes nunca afectan el envío en vivo
  • Las cargas útiles de webhook incluyen source y isTest
  • Se entregan solo cuando Permitir entregas de Test verificadas está activado (Ajustes → Organización) — de lo contrario, se retienen, sin facturar

Crea las tablas primero. Rylvo solo inserta filas; nunca crea tablas por sí mismo. La pestaña Tablas de cada conexión de base de datos tiene las declaraciones exactas — para Producción, y en Test las tablas *_test correspondientes — y las ejecuta con las credenciales guardadas.

Tu base de datos es la fuente de verdad. La copia de Rylvo es una caché operativa — no una copia de seguridad. Añade una conexión para mantener tus conversaciones permanentemente en tu propia base de datos. Extender la retención del lado de Rylvo aumenta los costos de almacenamiento pero no reemplaza tu propia base de datos.

Audience HubSolo de Dashboard

El espacio de trabajo operativo central para gestionar cada usuario final en cada bot de tu organización. Reemplaza listas de usuarios dispersas con un hub escalable: navegación paginada de personas, segmentos de filtro guardados, analíticas agregadas, gobernanza de consentimiento, importación/exportación CSV y controles de política de retención. Gestiona desde Dashboard → Audience.

Personas

Lista paginada y dirigida por servidor de usuarios finales con páginas de cursor de 50 filas por defecto y máximo de 200 filas.

  • Filtra por canal, alcance de consentimiento, estado de olvido o búsqueda de texto libre
  • Filtrado por bot con predicados de campos de recopilación de datos
  • Página completa de persona con pestañas de Resumen, Sesiones, Perfiles, Actividad y Auditoría
  • Etiquetas masivas, consentimiento, sesiones, eliminación, exportación, fusión y acciones de difusión elegibles
  • Capturas de widget anónimas e identidades de test permanecen separadas de Personas de producción
  • Atajos de teclado: / buscar, j/k navegar, Enter inspeccionar

Salas de Audience

Presets de filtro guardados que actúan como vistas persistentes. Crea salas para cohortes comunes y compártelas con tu equipo.

  • Guarda cualquier combinación de filtro como una sala nombrada
  • Indicador de cambios cuando los filtros actuales divergen
  • Pines y panel de Discusión por sala
  • Enlazable en profundidad mediante el parámetro de URL ?room=

Segmentos

Filtros reutilizables que se resuelven en listas concretas de miembros para difusiones y exportaciones.

  • Predicados básicos: todos los usuarios, activos dentro de N días, por canal, conversaciones mínimas
  • Predicados de perfil: punto de control alcanzado, valor de campo, umbral de completitud
  • Vista previa en vivo con recuento de coincidencias antes de guardar
  • Enlace de un clic a la pestaña de difusión de bots

Insights

Analíticas agregadas en caché calculadas desde una instantánea (TTL de 6 h). A nivel de organización o por bot.

  • Embudo de incorporación, mezcla de canales, desglose de consentimiento
  • Profundidad de participación, actividad reciente, mapa de calor por hora del día
  • Tasas de llenado de campos, etiquetas principales, histograma de completitud
  • Tabla de clasificación de bots (solo a nivel de organización)

Importaciones y Exportaciones

Trae contactos CRM heredados y exporta segmentos para tu almacén de datos.

  • Asistente de importación CSV: subir → mapear columnas → vista previa → confirmar (idempotente)
  • Exportación de segmentos a CSV (hasta 5.000 filas)
  • Límite de archivo de 15 MB más un límite de filas específico del plan

Consentimiento y Privacidad

Gobierna cómo se recopilan y retienen los datos de usuarios finales.

  • Mosaicos de alcance de consentimiento: ninguno, short_term_only, personalizar, completo
  • Cola de usuarios olvidados GDPR con enlaces profundos
  • Política de retención: días efectivos, anulación de acortamiento, complementos de extensión
  • El barrido de retención programado purga registros caducados

Perfiles y Esquema

Catálogo de campos a nivel de organización + tarjetas de esquema por bot. Detecta desviaciones de nombres antes de que arruinen los dashboards.

Ajustes

Política de retención, niveles de complementos y gobernanza. Configuración solo para administradores.

People DatasetsSolo de Dashboard

Colecciones nombradas de usuarios finales (no trazas). Almacenadas en la misma colección de datasets que los datasets de trazas, discriminadas por kind === "people". Creadas desde pines de Audience Room o directamente desde la página de Personas. Sin mecanismos de retención/bloqueo de exportación (a diferencia de los datasets de trazas). Con límite de cuota mediante el límite del plan maxDatasets. Gestiona desde Dashboard → Datasets → People.

Documento de dataset

  • name (1-200 caracteres), description (máx. 2000)
  • kind: "people" (discriminador; documentos heredados sin kind = "trace")
  • peopleCount: recuento de usuarios finales desnormalizado
  • retentionPolicy: { mode: "inherit" } (no aplicado para people)
  • archived: bandera de borrado suave

Documento de elemento

  • externalId (1-500 caracteres, identificador de usuario final)
  • source: "audience_room" | "people_page"
  • addedBy, addedByName, addedAt
  • snapshot: canal, displayName, consentScope, turnCount, lastSeenAtMs, firstSeenAtMs
  • ID de documento = externalId → añadir/eliminar es idempotente

Discriminador de tipo: people vs trace

  • people: agrupa perfiles EndUserDoc, sin aplicación de retención, sin bloqueo de exportación
  • trace: agrupa trazas TraceView, retención activa, bloqueo de exportación
  • Ambos en la misma colección de Firestore (datasets)
  • Filtrado: .filter(r => r.data.kind === "people")

3 flujos de creación

  • Desde pines de Audience Room: createPeopleDatasetFromRoomPins() — obtiene todos los pines, source="audience_room"
  • Desde la página de People Datasets: crea un dataset vacío, añade personas individualmente
  • Desde la página de Personas: addPeopleToDataset() añadido masivo, source="people_page"

Aplicación de cuota (maxDatasets)

  • Gratis: 1 | Starter: 1 | Lite: 10 | Pro: 50 | Enterprise: ilimitado (-1)
  • Verificación de recuento transaccional (seguro contra condiciones de carrera dentro de la transacción de Firestore)
  • Datasets archivados excluidos del recuento; solo se cuentan los de kind="people"
  • Error: PlanAccessError code="quota_exceeded", estado 429

RBAC

  • Lectura: cualquier miembro de la organización (viewer+)
  • Creación: operador+ (debe establecer createdBy = auth.uid, nombre obligatorio)
  • Actualización: operador+ | Archivado: operador+
  • Eliminación: admin+ (eliminación física + todos los elementos en lotes de 500)
  • Elementos: lectura = miembro; creación = operador+; eliminación = operador+

Operaciones idempotentes

  • Agregar elemento: devuelve { added: false } si ya existe
  • Eliminar elemento: devuelve { removed: false } si no existe
  • peopleCount se incrementa/decrementa atómicamente
  • No se pueden agregar personas a un dataset archivado

Relaciones y auditoría

  • Audience Rooms: pines → elementos del dataset mediante createPeopleDatasetFromRoomPins()
  • Broadcasts: NO se usan actualmente como destinos de broadcast (futuro: tipo de destino "dataset")
  • Auditoría: people_dataset.created / updated / archived / deleted / item_added / item_removed
  • Tipo de recurso: "people_dataset"

Endpoints de API (Python FastAPI)

  • POST /v1/people-datasets/{company_id} — crear dataset (201, verificación de cuota)
  • PUT /v1/people-datasets/{company_id}/{dataset_id} — actualizar nombre/descripción
  • POST /v1/people-datasets/{company_id}/{dataset_id}/archive — archivar (eliminación suave)
  • DELETE /v1/people-datasets/{company_id}/{dataset_id} — eliminación física + todos los elementos
  • POST /v1/people-datasets/{company_id}/{dataset_id}/items — agregar persona (idempotente)
  • POST /v1/people-datasets/{company_id}/{dataset_id}/items/{external_id}/remove — eliminar persona

Todos requieren authorize_org. Agregar elemento: external_id (1-500), source?, added_by, added_by_name, snapshot?.

Estructura de Firestore

{envRoot}/datasets/{datasetId}
  |- name (1-200), description (max 2000)
  |- kind: 'people' (discriminator)
  |- createdBy, createdByName
  |- peopleCount: number (denormalized)
  |- traceCount: 0 (not used for people)
  |- retentionPolicy: { mode: 'inherit' } (not enforced)
  |- tags: [], archived: boolean
  +- createdAt, updatedAt: Timestamp

{envRoot}/datasets/{datasetId}/items/{externalId}
  |- externalId (1-500), source: audience_room | people_page
  |- addedBy, addedByName, addedAt
  +- snapshot: { externalId, channel, displayName?,
                  consentScope, turnCount, lastSeenAtMs?, firstSeenAtMs? }

Quota: maxDatasets (Free: 1 | Starter: 1 | Lite: 10 | Pro: 50 | Enterprise: -1)
  Count excludes archived; only kind='people' counted

Solo panel de Broadcasts

Mensajería multicanal saliente: envía la misma campaña a plantillas de WhatsApp, SMS, correo electrónico y en la aplicación desde un solo compositor. Las cargas de audiencia (CSV / XLSX / pegado), los límites de velocidad derivados de la plataforma, el seguimiento de entrega por destinatario y el historial con calidad de auditoría están integrados. Gestiona desde Panel → Broadcasts.

Compositor en 5 pasos

Audiencia → Canales → Contenido → Programación → Revisión. Las reglas de la plataforma se muestran al seleccionar la audiencia, nunca en el momento de la entrega.

  • 4 fuentes de audiencia: segmento guardado, carga, pegado, todos los chatters anteriores
  • Canales activables con anotación de reglas por canal
  • Plantilla + enriquecimiento con LLM + variables por fila
  • Único, recurrente (cada hora → mensual) o "Enviar ahora"

12 canales de broadcast

Correo electrónico, en la aplicación, WhatsApp, SMS (Twilio), WhatsApp (Twilio), Telegram, LINE, Slack, Discord, MS Teams, Messenger, Instagram, Widget web. Cada uno anotado con veredicto de envío en frío y límite de plataforma.

  • WhatsApp: selector de plantillas aprobadas sincronizado desde Meta Graph
  • WhatsApp (Twilio): usa Twilio Programmable Messaging con prefijo E.164 whatsapp:
  • SMS: con puerta de aceptación, Twilio REST directo desde la ruta de envío
  • LINE: respuesta/envío mediante LINE Messaging API; secreto de canal + token de acceso cifrados en reposo
  • Telegram / Widget web / Discord: envío en frío bloqueado con explicación

Cargas de audiencia

CSV / XLSX analizados en el servidor (SheetJS) y lista pegada con clasificador y deduplicación. Hasta 50k filas por carga; las columnas de variables por fila se fusionan en la plantilla al enviar.

  • Detección automática del tipo de identificador: teléfono, correo electrónico, ID de canal
  • Advertencias mostradas antes de confirmar
  • Espejo opcional "guardar en audiencia" en endUsers

Seguimiento de entrega

Cada destinatario escribe una fila botBroadcastDeliveries: en cola / enviado / fallido / omitido, más los ID de mensaje del proveedor cuando estén disponibles.

  • Documento por ejecución con recuentos enviados / fallidos / omitidos por canal
  • Panel de historial agrupa entregas por canal + estado
  • Registro de auditoría: broadcast.created / scheduled / deleted

Límites de velocidad y seguridad

Limitador de velocidad con token bucket por canal en el ejecutor cron. Los límites reflejan los techos documentados de la plataforma para que una ejecución intensa no suspenda la cuenta subyacente.

  • WhatsApp: 4,800/min (~80/s/número, predeterminado de Meta)
  • SMS: 60/min (conservador de Twilio)
  • Los operadores pueden reducir por broadcast, nunca superar el límite de la plataforma

Capacidades y RBAC

Cuatro claves de capacidad controlan la función, reflejando el resto del panel.

  • broadcasts.view — viewer+
  • broadcasts.create — operador+
  • broadcasts.send — admin+
  • broadcasts.delete — admin+

Endpoints de API

  • POST /api/bots/broadcasts/dispatch — envío por destinatario × por canal (cron + token de ID)
  • POST /api/bots/broadcasts/generate-content — enriquecimiento con LLM (cron + token de ID)
  • POST /api/broadcasts/upload — analizador de CSV / XLSX / lista pegada
  • POST /api/broadcasts/recipients/save-to-audience — espejo endUsers idempotente
  • GET /api/channels/whatsapp/templates?orgId=…&botId=… — catálogo de plantillas aprobadas por Meta

Estructura de Firestore

{envRoot}/botBroadcasts/{broadcastId}
  |- targets.type: "all" | "selected" | "segment" | "uploaded"
  |- targets.uploaded.rows: UploadedRecipient[]
  |- delivery.channels: BroadcastChannel[]
  |- delivery.whatsappTemplate: WhatsAppTemplateRef | null
  |- delivery.rateLimitPerMinute: number | null
  +- deliveries/{deliveryId}
      |- runId, channel, identifier, identifierKind
      |- status: "queued" | "sent" | "failed" | "skipped"
      |- providerMessageId, error
      +- attemptedAt, deliveredAt

{envRoot}/botBroadcastRuns/{runId}
  |- status: "success" | "partial" | "failed"
  |- perChannelStats: { [channel]: { sent, failed, skipped } }
  |- targetCount, sentCount, failedCount, skippedCount
  +- generatedContent, errors[]

Equipo y RBACSolo panel

Control de acceso basado en roles para cada superficie del panel. Cuatro roles jerárquicos, invitaciones por correo electrónico, solicitudes de unión, concesiones de acceso granular a páginas y transferencia de propiedad. SSO / SAML y aprovisionamiento SCIM están disponibles en Enterprise. Gestiona desde Panel → Equipo.

Jerarquía de roles (jerarquizada)

Cuatro roles con aplicación estricta basada en rango. Ninguna acción puede dirigirse a un miembro en o por encima de tu propio rango.

  • Propietario (rango 3) — acceso completo, facturación, transferencia de propiedad
  • Admin (rango 2) — gestionar bots, claves, equipo, aprobaciones, ver registro de auditoría
  • Operador (rango 1) — ejecutar bots, pruebas, intervenciones, aprobar solicitudes
  • Viewer (rango 0) — acceso de solo lectura al panel

Matriz de capacidades (seleccionada)

  • team.view — viewer+
  • team.invite — admin+
  • team.remove_member — admin+
  • team.change_role — admin+
  • team.transfer_ownership — propietario
  • audit.view — admin+
  • audit.export — admin+ (+ plan Pro)
  • org.manage_sso — propietario (+ Enterprise)

Invitaciones (basadas en correo electrónico)

Admin+ invita por correo electrónico. El límite del plan se aplica al invitar y al aceptar, contando los asientos en uso: los delegados de agencias trabajan en los asientos de la agencia y no se cuentan contra el límite del cliente. ID de invitación determinista a partir del hash SHA256. Límite de velocidad: 10 invitaciones/min.

  • Caducidad predeterminada: 7 días. Estado: pendiente / aceptada / caducada / cancelada
  • Escritura atómica: invitación + registro de auditoría + contador de uso de la organización en una transacción
  • Aceptación: el correo electrónico debe coincidir, se vuelve a verificar el límite del plan, se crea el documento de miembro
  • Reenviar / cancelar son acciones de admin+, ambas registradas en auditoría

Solicitudes de unión (entre organizaciones)

Los no miembros pueden solicitar unirse con un perfil (rol, tipo de trabajo, intereses, caso de uso). Los admins aprueban o deniegan con motivo opcional.

  • El perfil captura: fundador / ingeniero / PM / diseñador / operaciones / analista / otro
  • Tipo de trabajo: construir agentes, integrar API, gestionar flujos de trabajo, analizar datos, explorar
  • Acciones de auditoría: page_access.approved / page_access.denied

Concesiones de acceso a páginas

Elevación granular para dos páginas restringidas: audit_log y billing. Los no admins ven un botón "Solicitar acceso".

  • La solicitud envía una notificación en la aplicación a todos los admins
  • Aprobar → pageId se agrega al array pageAccessGrants del miembro
  • Denegar → resolverNote opcional. Revocar elimina la concesión
  • Acceso: la concesión de rol otorga capacidad O pageAccessGrant explícito

Cambio y eliminación de roles

No puedes cambiar tu propio rol, no puedes actuar sobre un rango igual o superior, no puedes asignar por encima de tu propio rango. La eliminación es solo eliminación suave.

  • La degradación pone en cola un evento de outbox duradero para efectos secundarios (revocación de claves API)
  • Eliminación: estado → "deactivated", revoca todas las claves API mediante outbox
  • Transferencia de propiedad: intercambio atómico, dos entradas de auditoría, org.ownerId actualizado
  • SSO/SAML: disponible en Enterprise; propiedad de dominio obligatoria, break-glass requerido, aplicación en el servidor
  • SCIM 2.0: aprovisionamiento y desaprovisionamiento de usuarios; escrituras de roles rechazadas, el desaprovisionamiento es una eliminación suave

Endpoints de API

  • POST /api/team/invite — crear invitación por correo electrónico (admin+)
  • POST /api/team/invite/accept — aceptar invitación (cualquier usuario autenticado)
  • POST /api/team/members/{uid}/role — cambiar rol de miembro (admin+)
  • POST /api/team/transfer-ownership — transferir propiedad de la organización (solo propietario)

Estructura de Firestore

organizations/{orgId}/members/{uid}
  |- uid, email, displayName
  |- role: owner / admin / operator / viewer
  |- status: active / deactivated
  |- pageAccessGrants?: ("audit_log" | "billing")[]
  |- joinedAt, deactivatedAt?, deactivatedBy?
  +- createdAt, updatedAt

organizations/{orgId}/invitations/{inviteId}
  |- email, role, status, invitedBy, inviterName
  |- expiresAt, acceptedAt?, emailStatus?

organizations/{orgId}/joinRequests/{requestId}
  |- userId, userEmail, orgId, status, profile, requestedRole?
  |- requestedAt, resolvedAt?, resolvedBy?, denialReason?

organizations/{orgId}/pageAccessRequests/{requestId}
  |- pageId, requesterId, requesterEmail, status
  |- requestedAt, resolvedAt?, resolvedBy?, resolverNote?

Espacios de trabajo de Agencia y ClienteSolo panel

Las agencias pueden operar muchos espacios de trabajo de clientes sin convertir el espacio de trabajo de la agencia en un inquilino compartido. Cada cliente mantiene su propio propietario, equipo, recursos, facturación, historial de auditoría y entornos de Prueba/Producción. La asociación otorga acceso aprobado; no mueve los datos del cliente. Gestiona desde Panel → Clientes y Socios.

Disponible en Pro y Enterprise

Tanto el espacio de trabajo de la agencia como el del cliente necesitan Pro o Enterprise antes de que el acceso gestionado pueda activarse. Una agencia en Free, Starter o Lite no puede enviar una solicitud. Un cliente en esos planes aún puede inspeccionar y rechazar una, pero debe actualizar antes de aprobar. Ver, rechazar, finalizar y revocar permanecen disponibles en todos los planes.

Agencia Free / Starter / Lite

Ver y cerrar registros; no puede enviar solicitudes.

Cliente Free / Starter / Lite

Ver y rechazar; no puede aprobar.

Pro / Enterprise en ambos

Flujo completo de solicitud, aprobación, delegación, cambio y revocación.

Por qué Prueba y Producción muestran la misma página

La relación agencia–cliente pertenece a todo el espacio de trabajo, por lo que /dashboard/test/clients y /dashboard/production/clients se resuelven intencionalmente a una pantalla canónica de Clientes y Socios. Esto no combina los entornos del cliente. Después de que un delegado abre el espacio de trabajo del cliente, el selector de entorno aún determina si está trabajando con recursos y datos de ejecución de Prueba o Producción.

1. El cliente comparte su ID de espacio de trabajo

  • El cliente sigue siendo una organización Rylvo completamente separada
  • El ID del espacio de trabajo identifica el destino; no otorga acceso por sí mismo
  • El propietario del cliente, los miembros directos, los recursos y los datos no se mueven

2. La agencia solicita acceso exacto

  • Un admin de la agencia selecciona los compañeros exactos a delegar
  • Cada delegado recibe acceso de admin, operador o viewer
  • La solicitud puede incluir una nota y la relación comercial

3. El propietario del cliente aprueba

  • Nada se otorga mientras la solicitud está pendiente
  • Solo el propietario del cliente puede aprobar o rechazar
  • La aprobación vuelve a verificar ambos planes, delegados y colisiones con miembros directos; no necesita un asiento de cliente gratuito

4. Los delegados trabajan dentro del cliente

  • Abrir cliente usa el cambio de espacio de trabajo normal y recarga completa
  • El RBAC normal del cliente, los límites del plan y los límites de entorno aún se aplican
  • Cada membresía delegada registra su agencia y procedencia de relación

La gobernanza permanece con el cliente

  • Los admins delegados pueden construir y desplegar, pero no pueden gobernar el espacio de trabajo del cliente
  • El equipo del cliente, la propiedad, la configuración de la organización, la facturación y las asociaciones están bloqueados
  • Las membresías directas existentes del cliente nunca se degradan ni reclasifican

Facturación y revocación segura

  • El cliente posee su suscripción, billetera, transacciones, uso y derechos
  • El modo comercial registra el acuerdo comercial; no debilita el aislamiento
  • Finalizar la asociación elimina el acceso delegado y las claves sin borrar los datos del cliente
  • Las degradaciones voluntarias por debajo de Pro están bloqueadas hasta que las relaciones activas se cierren
  • La pérdida forzada de derechos finaliza automáticamente el enlace y preserva todos los datos propiedad del cliente

Ciclo de vida de la relación

pending_client_approval → active → ended
                        ↘ declined
declined / ended → pending_client_approval (new request revision)
Pro/Enterprise entitlement lost → ended + delegated access revoked

Rutas de API del panel

  • GET /api/agency/portfolio?orgId=… — resúmenes de relación (admin+ de la organización actual)
  • POST /api/agency/relationships — solicitar acceso (admin+ de agencia y Pro/Enterprise)
  • POST /api/agency/relationships/{id}/respond — aprobar (propietario del cliente y Pro/Enterprise) o rechazar (propietario del cliente en cualquier plan)
  • DELETE /api/agency/relationships/{id} — finalizar y revocar (admin+ de agencia o propietario del cliente)

Forma del plano de control

agencyClientRelationships/{sha256(agencyOrgId:clientOrgId)}
  |- agencyOrgId, clientOrgId, relationshipId, revision
  |- status, delegates[], commercialModel, requestMessage?
  |- requestedBy/At, approvedBy/At?, declinedBy/At?, endedBy/At?
  +- server-owned: no direct browser reads or writes

organizations/{clientOrgId}/members/{delegateUid}
  |- membershipKind: "agency_delegate"
  |- agencyOrgId, agencyRelationshipId
  |- role: admin | operator | viewer
  +- delegatedAt, delegatedBy

Registro de auditoríaSolo panel

Rastro de auditoría inmutable y a prueba de manipulaciones para cada acción material en la plataforma. Más de 200 tipos de acción, escritura de outbox en dos etapas con firmas de integridad HMAC-SHA256, paginación con cursor y exportación CSV. Gestiona desde Panel → Registro de auditoría.

Patrón de escritura en dos etapas

Cada mutación prepara un evento de auditoría en el outbox en la misma transacción de Firestore: la atomicidad está garantizada. Una Cloud Function drena el outbox hacia el registro de auditoría canónico de solo lectura.

  • Etapa 1: auditOutbox (transaccional, mismo lote que la mutación)
  • Etapa 2: auditLog (duradero, solo lectura, drenado por worker)
  • Firma de integridad HMAC-SHA256 en cada documento de outbox
  • Tanto la API web (Admin SDK) como la API de Python escriben a través del mismo pipeline

Catálogo de acciones (200+)

Cubre cada acción material: equipo, claves API, organización, bots, flujos de trabajo, prompts, pruebas, casos límite, guardarraíles, KB, trazas, centro de control, evolución, automatización, MCP Hub, habilidades, audiencia, transmisiones, conectores, autenticación y sesiones de configuración.

  • 40+ tipos de recursos (miembro, bot, prompt, guardarraíl, traza, transmisión…)
  • Cada entrada: actor, acción, resourceType, resourceId, detalles, IP, UA, fuente
  • Discriminador de fuente: web / api / mcp / system

Filtrado y búsqueda

Filtra por acción, resourceType, resourceId, fuente, rango de fechas, correo del actor y nombre del actor. Búsqueda de texto completo en todos los campos, incluido el JSON de detalles.

  • Paginación basada en cursor (cursor opaco: timestamp + docId)
  • Predeterminado 25/página, máximo 500/solicitud
  • Límite de tasa: 120 req/min por IP en el endpoint BFF

Exportación y cumplimiento

Exportación CSV con todos los campos. Restringida por capacidad y plan.

  • Columnas: id, timestamp, actorName, actorEmail, actorId, action, resourceType, resourceId, details
  • Requiere audit.export (admin+) Y plan Pro+
  • Los registros de auditoría son inmutables una vez canonizados
  • La retención sigue la política específica de la organización; purga GDPR a través de endpoints de observabilidad

RBAC

La visualización y la exportación están restringidas por separado. Los no administradores pueden solicitar acceso a través del sistema de concesión de acceso a páginas.

  • audit.view — admin+ O pageAccessGrants: ["audit_log"]
  • audit.export — admin+ Y plan Pro+
  • Los no administradores ven "Solicitar acceso" en la página de registros de auditoría

Integridad y seguridad

La firma HMAC-SHA256 en cada documento de outbox previene la manipulación. Las reglas de Firestore bloquean escrituras directas a auditLog.

  • Campos firmados: idempotencyKey, action, resourceType, resourceId, actor, details, source
  • JSON canónico con claves ordenadas
  • Sin escrituras directas de cliente a auditLog — todo pasa por el staging de outbox
  • El lector maneja tanto objetos actor anidados como campos heredados planos

Endpoint de API (BFF)

  • GET /api/audit?orgId=…&action=…&resourceType=…&startDate=…&endDate=…&q=…&actorEmail=…&actorName=…&cursor=…&limit=… — lista entradas de auditoría

Autenticación: token ID de Firebase (Bearer). Respuesta: { orgId, total, records[], nextCursor }. Cache-Control: private, max-age=5, stale-while-revalidate=30.

Forma de Firestore

organizations/{orgId}/auditOutbox/{docId}   (transient staging)
  |- idempotencyKey, action, resourceType, resourceId
  |- actor: { uid, email, displayName }
  |- details: { schemaVersion, ...custom }
  |- ipAddress, userAgent, source
  |- processed: boolean, processedAt, error, retryCount
  |- stagedAt, stagedBy, integrity (HMAC-SHA256)

organizations/{orgId}/auditLog/{docId}   (canonical, read-only)
  |- idempotencyKey, action, resourceType, resourceId
  |- actor: { uid, email, displayName }
  |- details: { schemaVersion, ...custom }
  |- ipAddress, userAgent, source
  +- timestamp: Timestamp

Indexes required:
  auditOutbox: (processed, stagedAt)
  auditLog: (action, timestamp desc), (resourceType, timestamp desc),
            (source, timestamp desc), (timestamp desc, __name__ desc)

API KeysSolo panel

Generación, gestión y revocación de claves API a nivel de organización con alcance de entorno, ámbitos de permisos, anulaciones de límite de tasa y hash SHA-256. Las claves autentican solicitudes de API externas (ejecución de bot, consulta de KB, documentos de KB). Gestiona desde Panel → API Keys.

Documento de clave API

  • name — etiqueta legible por humanos
  • keyPrefix — primeros 12 caracteres para visualización
  • keyHash — SHA-256 de la clave cruda (nunca almacenar la cruda)
  • environment — production | test (staging/development heredados se asignan a test)
  • permissions — matriz de ámbitos de API
  • rateLimitOverride — llamadas/min (null = predeterminado 60)
  • botId — vinculación opcional de bot

Generación y hash de claves

  • Formato: rylv_{40 hex chars} (46 caracteres)
  • Entropía: 20 bytes = 160 bits (crypto.getRandomValues)
  • Hash: SHA-256 vía Web Crypto API
  • Solo se persiste el hash; la clave cruda se muestra una vez en la creación
  • Prefijo (primeros 12 caracteres) almacenado para identificación visual

Ámbitos de permisos (5 + 2 comodines)

  • respond — POST /api/v1/bot-run + widget-poll
  • kb:read — POST /api/v1/kb/query
  • kb:write — POST /api/v1/kb/documents
  • tests:read — POST /api/v1/tests/gate
  • trace.read — reservado para futuro
  • * — acceso completo | kb:* — todo KB
  • La normalización descarta ámbitos no reconocidos; predeterminado a ["respond"]

Flujo de autenticación

  • Encabezados: Authorization: Bearer | X-API-Key | X-Rylvo-Key
  • Hash SHA-256 de la clave cruda, consulta de grupo de colección por keyHash
  • Verificar status == "active", extraer orgId de la ruta
  • Actualización asíncrona de lastUsedAt (no fatal si falla)
  • Devuelve AuthIdentity con permisos + rateLimitOverride

Operaciones CRUD

  • create: generar + hash + normalizar, escritura por lotes (doc + contador + auditoría)
  • list: filtrar por estado, ordenado por createdAt desc
  • update: nombre, entorno, permisos, botId + auditoría
  • revoke: estado → "revoked", decrementar contador + auditoría
  • revokeAllForMember: revocación masiva al eliminar miembro
  • hardDelete: eliminación física (reversión de aprovisionamiento)

Límite de tasa

  • Predeterminado: 60 llamadas/minuto por clave
  • Anulación vía campo rateLimitOverride
  • Cubo de tokens vía consumeTokenUnified()
  • Respuesta 429 con encabezado Retry-After
  • Cubos por ruta (bot-run, kb/query, etc.)

RBAC y límites de plan

  • apiKeys.view — admin+
  • apiKeys.create — admin+
  • apiKeys.revoke — admin+
  • Gratis: 0 | Starter: 0 | Lite: 10 | Pro: 25 | Enterprise: ilimitado
  • Una clave que un espacio de trabajo Gratis ya posee sigue funcionando; solo se rechaza crear una nueva
  • Cuota aplicada en reglas de Firestore (withinApiKeyQuota)
  • Los no administradores ven RestrictedPlaceholder

Auditoría y limpieza

  • Eventos: api_key.created / updated / revoked (con actor, IP, UA)
  • Revocación masiva registra { count, memberUid }
  • Eliminación de bot: elimina físicamente claves vinculadas, decrementa solo el contador activo
  • Arquitecto de espacio de trabajo: crea automáticamente clave con permisos predeterminados, reversión vía hardDelete
  • Ruta de migración: relleno normalizeApiKeyPermissions (idempotente)

Endpoints de API (BFF)

  • POST /api/v1/bot-run — ejecuta turno de bot (permiso: respond, reproducción de idempotencia)
  • POST /api/v1/kb/query — consulta KB (permiso: kb:read)
  • POST /api/v1/kb/documents — sube documentos (permiso: kb:write, máximo 100)
  • POST /api/v1/tests/gate — puerta de liberación para CI (permiso: tests:read)

Autenticación: clave API vía encabezado Bearer / X-API-Key / X-Rylvo-Key. Límite de tasa por clave.

Forma de Firestore

{envRoot}/apiKeys/{keyId}
  |- name, keyPrefix (12 chars), keyHash (SHA-256)
  |- environment: production | test  (legacy: staging, development map to test)
  |- permissions: string[] (respond, kb:read, kb:write, trace.read, *, kb:*)
  |- status: active | revoked
  |- rateLimitOverride: number | null (calls/min)
  |- botId?, botName?
  |- createdBy, createdAt
  |- lastUsedAt?, revokedAt?, revokedBy?

Quota: usage.apiKeyCount vs settings.maxApiKeys
  Free: 0 | Starter: 0 | Lite: 10 | Pro: 25 | Enterprise: -1 (unlimited)

ApprovalsSolo panel

Flujo de trabajo de aprobación humano en el bucle para ejecución de herramientas. Dos sistemas: aprobaciones de herramientas de conector (a nivel de API, para herramientas de webhook/conector con bandera requires_approval) y aprobaciones de herramientas MCP (MCP Hub, para herramientas con permiso require_approval). Mission Control añade tiempos de espera basados en urgencia y puntuación de riesgo. Máquina de estados: pending → approved / denied / expired.

Aprobación de herramienta de conector

  • Se activa cuando la herramienta tiene safety_restrictions.requires_approval = True
  • Formato approval_id: aprv_{tool_call_id}
  • TTL predeterminado: 24 horas (86400s)
  • Fire-and-forget: la herramienta devuelve fallo con approval_id inmediatamente
  • El bot/frontend consulta el estado por separado; sin re-invocación automática al aprobar

Aprobación de herramienta MCP

  • Niveles de permiso: allow | require_approval | deny
  • Predeterminados basados en riesgo: bajo/medio → allow, alto/crítico → require_approval
  • TTL predeterminado: 10 minutos (600,000 ms)
  • argsPreview (JSON redactado, máximo ~2KB) + llmRationale opcional
  • Suscripciones Firestore en tiempo real para aprobaciones pendientes

Máquina de estados

  • pending → approved (vía service.approve)
  • pending → denied (vía service.deny con razón)
  • pending → expired (auto-caducidad cuando el TTL transcurre)
  • Solo pending → approved/denied permitido (idempotente)
  • Doble aprobación/denegación devuelve None (ya resuelto)
  • Mission Control añade: estado auto_denied

Niveles de urgencia de Mission Control

  • immediate — tiempo de espera 15s, informativo de bajo riesgo
  • standard — tiempo de espera 120s, acceso a datos / relacionado con PII
  • extended — tiempo de espera 900s, financiero / legal / cumplimiento
  • Caducidad calculada en servidor (createdAt + timeoutSeconds)
  • Incluye riskScoreAtTime + riskSignals[] + conversationContext

Métodos de ApprovalService

  • request_approval() — crear pendiente, persistir, registrar evento
  • approve() — verificar pendiente, actualizar, registrar, idempotente
  • deny() — verificar pendiente, actualizar + razón, registrar, idempotente
  • list_pending() — consultar + filtrar caducados + registrar obsoletos

Caducidad y funciones de nube

  • cleanupExpiredMcpApprovals — cada 5 min, aprobaciones MCP pasadas de TTL
  • missionControlExpireApprovals — cada 2 min, aprobaciones MC pasadas de tiempo de espera
  • Ambos escriben entradas de auditoría para caducidad iniciada por sistema
  • Sondeo de frontend: retroceso exponencial 1-30s, tiempo de espera local de 5 min

RBAC

  • Aprobaciones de conector: lectura = admin+; escritura = solo servidor (reglas: false)
  • Aprobaciones MC: lectura = miembro; crear/actualizar = operator+; eliminar = admin+
  • Aprobaciones MCP: lectura = miembro; crear/actualizar = operator+; eliminar = admin+
  • Capacidad resolve_approval: operator+ (Mission Control)
  • Página de aprobaciones de MCP Hub: admin+ para botones de aprobar/denegar

Auditoría y analítica

  • Caducidad MC escribe auditoría: eventType "approval_resolved", actor "system_sweep"
  • Analítica: MCApprovalResolvedEvent { request_id, bot_id, action_type, resolution, response_time_ms, urgency }
  • Registro de auditoría: approval.requested / approved / denied / expired / resolved
  • Clave de idempotencia en aprobaciones MC para semántica de exactamente una vez

Endpoints de API (Python FastAPI — aprobaciones de conector)

  • POST /v1/approvals/{approval_id}/approve — aprobar (consulta: approver_email?)
  • POST /v1/approvals/{approval_id}/deny — denegar (consulta: reason?, approver_email?)
  • GET /v1/approvals/pending?company_id=…&bot_id=…&session_id=… — listar pendientes

GET pending requiere authorize_org. 404 si no se encuentra o ya resuelto. Las aprobaciones MCP se gestionan vía panel en /dashboard/mcp-hub/approvals.

Forma de Firestore

{envRoot}/approvalRequests/{approvalId}   (connector + Mission Control)
  |- approval_id (aprv_{tool_call_id}), tool_call_id, tool_name
  |- arguments: dict, status: pending | approved | denied | expired
  |- company_id, org_id, bot_id?, session_id, workflow_id?
  |- requested_at, expires_at (24h default)
  |- resolved_at?, resolved_by?, denial_reason?
  |- trace_id, request_id
  |- (MC) urgency, timeoutSeconds, riskScoreAtTime, riskSignals[]
  |- (MC) conversationContext, idempotencyKey?
  +- created_at: Timestamp

{envRoot}/mcpApprovalRequests/{requestId}   (MCP Hub)
  |- requestId, serverId, serverName, toolId, toolName, toolDisplayName
  |- botId, botName, conversationId?, requestedBy, requestedByDisplay?
  |- argsPreview (redacted, ~2KB), llmRationale?
  |- status: pending | approved | denied | expired
  |- reviewedBy?, reviewedByDisplay?, decisionReason?
  |- expiresAt (10 min default), reviewedAt?
  +- createdAt, updatedAt: Timestamp

NotificationsSolo panel

Sistema de notificaciones unificado con 60+ tipos en 8 categorías. Notificaciones en la aplicación entregadas vía suscripciones Firestore en tiempo real; correo vía Resend; envío de webhooks a Slack/Discord/Teams. El gancho de bandeja de entrada unificada fusiona menciones + alertas en la aplicación en todas las organizaciones. Gestiona desde Panel → Notifications.

Documento de notificación en la aplicación

  • userId (destinatario), orgId, type
  • title, message, link?
  • data?: primitivas de Firestore (string | number | boolean)
  • read: booleano, readAt: Timestamp | null

Documento de mención de comentario de traza

  • recipientUid, type (trace_mention | comment_reply | room_mention | pin_mention)
  • payload: commentId, entityType, entityId, entityLabel, actorUid, actorName, snippet (~120 caracteres)
  • Opcional: parentRoomId, traceId, traceSource, traceLabel

77 tipos en 8 categorías

  • billing (19): credits_low, quota_exceeded, subscription_*, billing_addon_*, referral_reward
  • mission_control (20): alert_rule_triggered, channel_error, byok_unhealthy, approval_requested, bot_budget_*
  • team (15): join_request, member_joined, page_access_*, member_role_changed
  • system (12): welcome, onboarding_step, kb_indexing_*, bot_deleted, bot_import_completed, bot_import_needs_attention, timezone_unset
  • retention (4): retention_warning, retention_deleted, dormancy_*
  • edge_cases (4): edge_case_alert, guardrail_triggered, red_team_run_complete, fix_proposal_applied
  • broadcasts (2): broadcast, broadcast_failed · evolution (1): evolution_alert

Canales de entrega (4)

  • En la aplicación: suscripciones Firestore en tiempo real (<100ms)
  • Correo: Resend (correos de mención, bienvenida; opt-in por miembro)
  • Webhooks: Slack, Discord, Teams, genérico (2 reintentos, retroceso de 500ms, tiempo de espera de 8s)
  • Herramientas de bot: herramientas de runtime send_notification__{slug}__{id} (mejor esfuerzo)

Bandeja de entrada unificada en tiempo real

  • useNotificationInbox(): fusiona menciones + en la aplicación, limitado a la organización activa
  • Suscripciones Firestore paralelas por organización; otros espacios de trabajo aparecen como recuentos no leídos + opción de cambio
  • Expone: items[], unreadCount, otherOrgUnread[], loading, markItemRead, markAllRead, deleteItems
  • Máximo 100 por organización por suscripción

Ciclo de vida y disparadores

  • Creado (leer=false) → Marcar como leído → Eliminar (borrado permanente)
  • Marcar todo como leído: limitado a 200 documentos por llamada
  • Disparadores: escalaciones de guardarraíl, adjuntos degradados, alertas de observabilidad, solicitudes de unión, transmisiones, menciones, bienvenida
  • Los disparadores del motor son post-hooks de tipo "fire-and-forget" (nunca bloquean la respuesta del bot)

Canales de notificación (Mission Control)

  • Tipos: slack, email, webhook, discord, teams
  • config: webhookUrl?, emails?, headers?
  • events []: qué eventos de alerta activan este canal
  • botIds?: vinculación opcional del bot
  • lastUsedAt, lastStatus (success | failed)

RBAC y preferencias

  • En la aplicación: lectura = userId == auth.uid; actualización = solo campos read/readAt; eliminación = false (vía API)
  • Menciones: lectura = orgMember + coincidencia de recipientUid; creación = actorUid == auth.uid
  • Canales: lectura = miembro; creación/actualización/eliminación = admin+
  • API de despacho: se requiere operador+
  • Preferencias: notificationPrefs.mentionEmail (por defecto true)

Endpoints de API

  • POST /api/notifications/create — distribución a múltiples destinatarios (30/min por organización, máx. 500 destinatarios)
  • POST /api/notifications/delete — eliminación permanente (máx. 100 elementos, propiedad verificada)
  • POST /api/notifications/dispatch — despacho de webhook de Mission Control (10/min por organización, operador+)
  • POST /api/notifications/email — correos de mención vía Resend
  • POST /api/notifications/welcome — bienvenida única + correo (guardia transaccional)

Crear: tipo (validado por registro), título, mensaje, link?, data?, audiencia (all_members|admins|{userIds}). Despacho: channels[], alert{ruleName, severity, trigger, message, botName, conversationId, details}.

Estructura de Firestore

organizations/{orgId}/inAppNotifications/{notificationId}
  |- userId, orgId, type (from registry)
  |- title, message, link?, data?
  |- read: boolean, readAt: Timestamp | null
  +- createdAt: Timestamp

organizations/{orgId}/notifications/{notifId}  (trace comment mentions)
  |- recipientUid, type (trace_mention | comment_reply | room_mention | pin_mention)
  |- read: boolean
  +- payload: { commentId, entityType, entityId, entityLabel,
                actorUid, actorName, snippet, parentRoomId?, traceId? }

{envRoot}/notificationChannels/{channelId}  (Mission Control)
  |- name, type (slack|email|webhook|discord|teams), enabled
  |- config: { webhookUrl?, emails?, headers? }
  |- events[], botIds?, lastUsedAt, lastStatus
  +- createdBy, createdAt, updatedAt

organizations/{orgId}/members/{uid}.notificationPrefs:
  { mentionEmail: boolean (default true) }