Relay

En vivo

Proyecto personal explorando IA de voz en tiempo real. El caso de uso es una recepcionista de clínica; el objetivo real era alcanzar un presupuesto de latencia percibida por el usuario de menos de un segundo con instrumentación completa por tramo.

Rol
Solo — arquitectura, pipeline de voz, frontend, deploy
Período
nov 2025 – Actual
Stack
  • Next.js 16
  • TypeScript
  • LiveKit Cloud
  • Twilio
  • Deepgram
  • Claude Haiku 4.5
  • Cartesia Sonic-3
  • Cal.com
  • Inngest
  • Supabase
  • PostgreSQL
  • Prisma
  • Tailwind v4

Qué hace

Un administrador de clínica se registra, crea una organización y configura un agente — prompt de persona, voz, horario de atención, base de conocimiento con preguntas frecuentes. Apunta un número de Twilio al SIP trunk y listo.

Un llamante marca. Aproximadamente medio segundo después de terminar de hablar, el agente responde con una voz natural. Mientras la llamada está en curso:

  1. Una forma de onda en vivo pulsa al ritmo del audio entrante.
  2. La transcripción se llena token a token con etiquetas de hablante por turno.
  3. Un medidor de latencia muestra STT, LLM TTFT, TTS TTFA y p95 end-to-end en tiempo real, con cada tramo en rojo cuando supera su presupuesto.
  4. Cada herramienta que invoca el agente — check_availability, lookup_kb, book_appointment, transfer_to_human — aparece en una línea de tiempo inline con entrada, salida y duración.
Vista de llamada en vivo de Relay: una forma de onda pulsante, una transcripción en streaming con etiquetas de hablante y sentimiento, un medidor de latencia de seis tramos y una línea de tiempo inline de herramientas.
Una llamada en curso: forma de onda, transcripción en streaming, medidor de latencia por tramo y las llamadas a herramientas del agente, todo en vivo.

El operador puede tomar el control de la llamada desde el dashboard en cualquier momento.

Cuando la llamada termina, un job de Inngest descarga la grabación, le pide a Claude Sonnet 4.6 que genere un resumen estructurado, clasifica el resultado (SCHEDULED, QUALIFIED, TRANSFERRED, NOT_QUALIFIED, NO_ANSWER), puntúa el sentimiento y extrae los temas. La página de detalle muestra la grabación en un reproductor con scrubbing y la transcripción resaltando el segmento que se está escuchando.

Dashboard de operador de Relay: tiles de llamadas-hoy, agentes-activos, números-conectados y conversión sobre una lista de llamadas-en-curso, una lista de llamadas-recientes y gráficos de resultados-de-hoy y volumen-de-llamadas.
El dashboard del operador: llamadas en vivo, resultados recientes y las métricas con las que realmente opera una clínica.

El mismo dashboard incluye campañas salientes (carga de CSV, respeto de horario laboral, reintentos con cooldown), una página de analíticas (volumen, conversión, latencia p95, heatmap por hora y día de la semana) y una integración con Cal.com para agendar citas durante la llamada.

Pantalla de campaña saliente de Relay mostrando una campaña en ejecución con progreso de llamadas, ventanas de horario laboral y configuración de reintentos.
Campañas salientes: carga de CSV, ventanas de horario laboral y reintentos con cooldown.

Por qué lo construí

No es un producto — es un proyecto personal. Quería construir la experiencia de IA de cara al usuario más difícil que se me ocurriera (voz) sobre un stack donde el presupuesto de latencia es la restricción principal. El caso de uso de recepcionista de clínica es el ejemplo canónico porque tiene volumen real y consecuencias reales por llamadas perdidas, lo que hace que el objetivo de latencia sea significativo en lugar de académico.

Cómo funciona

Pipeline de voz en tiempo real

  • Twilio termina la llamada PSTN y la conecta a LiveKit Cloud vía SIP.
  • Un worker Node de larga duración se une a la sala de LiveKit y ejecuta el loop de conversación. El worker se despliega por separado de la app Next.js — las funciones de Vercel no pueden mantener un websocket abierto durante una llamada de 10 minutos.
  • Deepgram maneja STT, VAD y detección de turno en una sola API en streaming. Los eventos de fin de turno disparan el LLM, eliminando la varianza de 150–300ms de pipelines separados de VAD + temporizador de silencio.
  • Claude Haiku 4.5 conduce la conversación. Los tokens en streaming se dividen oración por oración y se pasan a Cartesia Sonic-3 para que el audio empiece a reproducirse antes de que el LLM termine de generar.
  • El uso de herramientas es nativo al llamado del SDK de Anthropic. Cuatro herramientas están disponibles durante la llamada: check_availability, book_appointment, lookup_kb, transfer_to_human. Cada herramienta se valida con Zod, se registra con entrada/salida/duración, y el LLM continúa con el resultado de la herramienta como un turno normal.
  • La interrupción adaptativa / barge-in cancela la generación del LLM en curso y vacía la cola de audio TTS en el momento en que el usuario empieza a hablar.
  • La latencia se instrumenta por tramo y se escribe en la base de datos para el medidor en vivo y el dashboard de analíticas.

Multi-tenant B2B

Tres capas de aislamiento de tenant — scoping por fila en Postgres, guards a nivel de aplicación en cada server action, y credenciales de sub-cuenta de Twilio por organización. El worker de LiveKit lee la org desde los headers SIP para que una ruta mal configurada nunca pueda conectarse a la sala de otro tenant.

Estado

En vivo en relay.picoral.me. El walkthrough en Loom y el caso de estudio completo vienen después.

Preguntas

¿Qué es Relay?

Relay es una recepcionista de IA de voz multi-tenant para negocios de servicios como clínicas. Atiende llamadas entrantes 24/7, califica leads, agenda citas vía Cal.com y transfiere a un humano cuando hace falta. Los operadores ven cada llamada en vivo en el dashboard con forma de onda, transcripción en streaming y medidor de latencia por tramo.

¿Cuál es el presupuesto de latencia de Relay?

El objetivo es p95 ≤ 900ms de respuesta percibida por el usuario, medida desde el fin del habla del usuario hasta el inicio del audio del agente. Cada tramo se instrumenta por separado — STT finalize, LLM TTFT, LLM total, TTS TTFA, tool total, end-to-end — y se expone como un medidor en vivo que se pone rojo cuando algún tramo supera su presupuesto.

¿Por qué LiveKit + Deepgram + Cartesia en lugar de un solo proveedor?

Cada tramo es lo mejor de su clase y se puede reemplazar de forma independiente. LiveKit maneja la terminación SIP desde Twilio y la sala de audio. El STT en streaming de Deepgram incluye VAD y detección de turno en una sola API, eliminando la varianza de 150–300ms de pipelines separados de VAD + temporizador de silencio. Cartesia Sonic-3 es un TTS genuinamente más rápido que el tiempo real, que es lo que hace posible el presupuesto de menos de un segundo.

¿Cómo funciona el aislamiento multi-tenant en Relay?

Tres capas — scoping por organizationId a nivel de fila en Postgres, guards a nivel de aplicación en cada server action, y credenciales de sub-cuenta de Twilio por organización. El worker de LiveKit lee la organización desde los headers SIP para que una ruta mal configurada nunca pueda conectarse a la sala de otro tenant.