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
- 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.
- 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.
- 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.
- 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
- 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. - Siempre OpenRouter — cada chat se ejecuta con tu clave de OpenRouter, incluso cuando existe una clave directa.
- Solo claves nativas — OpenRouter nunca se usa; los modelos sin clave directa están bloqueados.
- 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 nativogenerateContent) - 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_stateopcional 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étodo | Ruta | Descripción |
|---|---|---|
| POST | /api/v1/bot-run | Ejecuta un turno de un bot o grupo de agentes (alcance: respond) |
| POST | /api/v1/kb/query | Consulta una conexión de base de conocimiento (alcance: kb:read) |
| POST | /api/v1/kb/documents | Sube 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 | /health | Vitalidad (proceso activo) |
| GET | /ready | Disponibilidad (puede manejar solicitudes) |
| GET | /live | Sonda de tiempo activo |
| GET | /flags | Banderas 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
| Campo | Tipo | Descripción |
|---|---|---|
| botId | string | Identificador del bot (desde Panel → Bots). Se requiere botId o groupId. |
| message | string | El mensaje actual del usuario final |
Campos opcionales
| Campo | Tipo | Descripción |
|---|---|---|
| groupId | string | Identificador del grupo de agentes (ejecuta un equipo multi-bot en lugar de un solo bot) |
| conversationHistory | object[] | Turnos anteriores: { role: 'user' | 'assistant', content } |
| sessionId | string | Identificador de conversación/sesión; se devuelve como conversationId |
| endUserExternalId | string | Identificador estable del usuario final en tu espacio de nombres (≤256). Requerido para nombre mostrado / correo. |
| endUserDisplayName | string | Nombre legible por humanos mostrado en Trazas (≤200) |
| endUserEmail | string | Correo del usuario final para transferencia de soporte (validado) |
| known_facts | object[] | 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. |
| channel | string | api (predeterminado) | widget | whatsapp | slack | unknown |
| model | string | Modelo de anulación (p. ej., openai/gpt-4.1-mini, anthropic/claude-sonnet-4.6) |
| maxTokens | number | Máximo de tokens de salida para este turno |
| temperature | number | Temperatura de muestreo para este turno |
| disableTools | boolean | Desactiva las llamadas a herramientas/conectores para este turno |
| maxToolIterations | number | Limita las iteraciones del bucle de llamadas a herramientas |
| responseFormat | object | Salida estructurada: {type:"json_object"} o {type:"json_schema", json_schema:{...}} — restringe la respuesta final (solo modelos compatibles con OpenAI) |
| stream | boolean | Transmisió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
| Campo | Descripción |
|---|---|
| response | El texto de respuesta del asistente para mostrar al usuario |
| runId | Identificador único de este turno — encuéntralo en Panel → Trazas |
| conversationId | Devuelve el sessionId de la solicitud |
| model | El modelo que realmente sirvió el turno |
| latencyMs | Latencia del turno en el servidor (ms) |
| tokens | Conteos 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 |
| toolCalls | Herramientas invocadas en este turno (nombre, disposición, latencia, costo) |
| sessionEnd | Se establece cuando el bot terminó la sesión ({ reason, summary? }) |
| kb | Telemetría de fundamentación de KB incl. citas (cuando se ejecutó la recuperación) |
| pendingApproval | Presente 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.
| Plan | Mensual | Respuestas del bot |
|---|---|---|
| Free | $0 | Uso justo |
| Lite | $40 | Uso justo |
| Pro | $100 | Uso justo · guía ≈ 100K/mes |
| Enterprise | Personalizado | Establecido 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
| Plan | Precio | Límites principales | Notas |
|---|---|---|---|
| Free | $0 | 1 bot · retención de trazas de 7 días | Tu propia clave de IA, sin margen; las respuestas del bot son de uso justo |
| Lite | $40 | 3 bots · retención de trazas de 14 días | Kit para constructores individuales; sin suite avanzada de IA ni broadcasts |
| Pro | $100 | 25 bots · retención de trazas de 90 días | Suite avanzada de IA + broadcasts |
| Enterprise | Personalizado | Negociado | DPA 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
| Encabezado | Significado |
|---|---|
| X-RateLimit-Limit | Capacidad de solicitudes por minuto de la clave |
| X-RateLimit-Remaining | Solicitudes restantes en la ventana de límite de tasa actual |
| X-RateLimit-Reset | Segundos Unix cuando se restablece la ventana |
| Retry-After | Segundos a esperar antes de reintentar (en 429) |
| Idempotent-Replay | true 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 degradadarequireQuota— uso ≥ límite del planrequireProviderKey— la función de IA necesita tu propia clave de LLM (BYOK, gratuita)requireStorageEventsBudget— grupo de almacenamiento agotado- Devuelve
PlanAccessErrorconupgradeTarget
Arquitectura de outbox duradera
- Las rutas de API publican en un
billingOutboxduradero antes de Pub/Sub - La Cloud Function
billingOutboxWorkeres el único escritor de cuentas - Transacciones atómicas con idempotencia + límite negativo
- El
billingReconciliationdiario 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étodo | Ruta | Descripción |
|---|---|---|
| GET | /v1/traces/{trace_id}/replay | Carga completa de reproducción para una traza (pila de prompts, guardrails, llamadas a herramientas, tiempos por etapa) |
| GET | /v1/sessions/{session_id}/traces?limit=50 | Lista cada ejecución en una sesión, más reciente primero |
| GET | /v1/analytics/companies/{company_id}/overview?limit=500&top_n=10 | Tasa de escalación, latencia promedio y resúmenes de tokens/costos en la ventana |
| GET | /v1/analytics/companies/{company_id}/runs?limit=100 | Ejecuciones 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-rowsagregados 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_spendenvironment: production, test, o null para ambos;botIdnull = 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
minTracesrespuestas, luego esperacooldownMinutes
Roles
analytics.view— espectadoranalytics.edit,analytics.annotate— operadoranalytics.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
| Clave | Predeterminado | Descripción |
|---|---|---|
| {{company_name}} | Acme Corp | El nombre de la empresa del cliente |
| {{user_name}} | John | El nombre para mostrar del usuario final |
| {{product_name}} | Widget Pro | El producto en discusión |
| {{industry}} | Technology | El sector vertical de la industria del cliente |
| {{tone}} | professional | Tono de respuesta (formal, casual, empático) |
| {{language}} | English | Idioma de respuesta |
| {{max_length}} | 256 | Longitud 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ón | Predeterminado | Descripción |
|---|---|---|
| Estrategia | OPRO | Qué algoritmo de optimización usar |
| Métrica de evaluación | Tasa de éxito | success_rate | verification_pass | user_satisfaction | latency |
| Frecuencia de ejecución | Diaria | hourly | daily | weekly | manual |
| Auto-promoción | Desactivada | Promover automáticamente variantes ganadoras a activas |
| Umbral de mejora | 2% | Mejora mínima requerida para calificar como ganadora |
| Máx. variantes por ejecución | 5 | Número de variantes candidatas generadas por ejecución de optimización |
| Tamaño mínimo de muestra | 50 | Solicitudes 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
- Escaneo de traces —
POST /v1/edge-cases/{org}/scanarchiva 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 - 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)
- 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
- Observar — muestrear trazas recientes del bot
- Detectar — agrupar fallos y cuasi-errores
- Inferir — el LLM revisor nombra el patrón y la causa raíz
- Generar — redactar una regla, edición de prompt o guardarraíl
- Inyectar — adjuntar al bot detrás de una bandera de experimento
- 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
drafto 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,descriptionmode: guiado | estrictostart_step_id: paso de entrada (debe estar definido)steps: FlowStep[]enabled: booleano
Estructura de paso (FlowStep)
id(único),namegoal: inyectado en el prompt del sistema para este pasocollect: información a solicitar antes de avanzar — el flujo conserva lo que la recopilación de datos del bot no puede guardarallowed_tools: string[] | "all" | "none" — aplicado en modo estricto, orientación en modo guiadoallowed_agent_id: sub-agente para este paso (grupos)terminal: finaliza el flujo
Transición
to: id del paso objetivokind: siempre | datos_completos | intención | condición | resultado_herramientaintent(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_idvisited: ids de pasos vistos en esta sesióndone: el flujo alcanzó un paso terminaldata: 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
/attachpara 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 .../versionslista 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 tipoincrement,max,min— números (máx/mín también fechas)append,append_unique— listasmerge— 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}/config | Los 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}/revisions | Historial, más reciente primero |
| POST | /api/v1/state/{botId}/records/{scope}/{subjectId}/restore | Restaurar 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}/config | Reemplazar 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_busyconRetry-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
rememberyforget), 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}/memories | Recordar 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}/search | Buscar 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.
| Etapa | Cuándo | Puedes responder |
|---|---|---|
| on_session_start | Primer mensaje de una conversación | context, instructions, state |
| before_turn | Cada mensaje, antes del modelo | context, instructions, state, reply, block |
| retrieve | Cada mensaje, junto con la base de conocimiento | passages |
| after_turn | Después de que el bot responda, antes de enviarlo | reply, state, endConversation |
| on_session_end | Una 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—trueo{"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}/end | Terminarla; el siguiente mensaje de la persona inicia una nueva |
| POST | /api/v1/sessions/{sessionId}/fork | Una 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,legacyodashboard - 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
| Plan | Máx. conjuntos de datos | Máx. traces conservados |
|---|---|---|
| Gratis | 1 | 50 |
| Starter | 1 | 200 |
| Lite | 10 | 5,000 |
| Pro | 50 | 25,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 base64urlclientName(1-200),redirectUris[]grantTypes: authorization_code, refresh_tokentokenEndpointAuthMethod: none | client_secret_postclientSecretHash: 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 conocimientorylvo:write— crear/actualizar bots, prompts, conocimiento, configuracionesrylvo: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.clientIdpor 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étodo | Ruta | Descripción |
|---|---|---|
| POST | /v1/connectors | Crear 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}/activate | Activar |
| POST | .../{id}/deactivate | Desactivar |
| POST | .../{id}/test | Probar endpoint |
| POST | /v1/connectors/generate-secret | Generar secreto HMAC |
| GET | /v1/connectors/{company_id}/tools/available | Listar 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)
enabledsolo 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
botIdychannelType
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
| Recurso | Lectura | Escritura | Eliminación |
|---|---|---|---|
| Bots | bots.list, bots.get | bots.create, bots.update | bots.delete |
| Prompts | prompts.list, prompts.get | prompts.create, prompts.update, prompts.set_optimization | prompts.delete |
| Guardarraíles | guardrails.list, guardrails.get | guardrails.create, guardrails.update | guardrails.delete |
| Pruebas | tests.list_cases, tests.list_runs, tests.get_run_results | tests.create_case, tests.run_suite | tests.delete_case |
| Conectores | connectors.list, connectors.get | connectors.create, connectors.update, connectors.test | connectors.delete |
| Canales | channels.list, channels.get | channels.create, channels.update, channels.register_webhook | — |
| Servidores MCP | mcp_servers.list, mcp_servers.get | mcp_servers.register, mcp_servers.update | mcp_servers.delete |
| Habilidades | skills.list, skills.get | skills.create, skills.update | skills.delete |
| Base de conocimiento | kb.list_connections, kb.get_connection | kb.create_connection, kb.update_connection, kb.add_source | kb.delete_connection |
| Grupos de agentes | agent_groups.list | agent_groups.create, agent_groups.add_bot | agent_groups.delete |
| Automatizaciones | automations.list_tasks, broadcasts.list | automations.create_task, broadcasts.create | automations.delete_task, broadcasts.delete |
Herramientas macro
scaffold_bot_from_description— crear un bot + prompt de sistema + guardarraíl inicial a partir de un resumenclone_bot— duplicar un bot y opcionalmente copiar recursos vinculadosattach_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
testDatabaseNameopcional - Clave de cortacircuitos separada — las tablas de test faltantes nunca afectan el envío en vivo
- Las cargas útiles de webhook incluyen
sourceyisTest - 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/knavegar,Enterinspeccionar
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 desnormalizadoretentionPolicy: { 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,addedAtsnapshot: 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:
PlanAccessErrorcode="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— propietarioaudit.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 humanoskeyPrefix— primeros 12 caracteres para visualizaciónkeyHash— 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 APIrateLimitOverride— 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-pollkb:read— POST /api/v1/kb/querykb:write— POST /api/v1/kb/documentstests:read— POST /api/v1/tests/gatetrace.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 eventoapprove()— verificar pendiente, actualizar, registrar, idempotentedeny()— verificar pendiente, actualizar + razón, registrar, idempotentelist_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,typetitle,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 canalbotIds?: 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) }