27 de mayo de 2026 • 7 min de lectura
Especialista en IA y Automatización
Diseño sistemas de comunicación impulsados por IA. Mi trabajo se centra en agentes de voz, chatbots de WhatsApp, asistentes de IA y automatización de flujos, construidos principalmente sobre Twilio, n8n y LLM modernos como OpenAI y Claude. En los últimos 7 años he entregado más de 30 proyectos de automatización que manejan más de 250 000 interacciones mensuales.
Si te gusta el contenido que hago, puedes suscribirte y recibir información valiosa por correo. No se envía spam, solo novedades sobre publicaciones interesantes o contenido especializado del que hablo.
Casi todas las demos de voz con IA te muestran una llamada funcionando en el navegador. Lo que saltean es la parte donde tenés que pasar de una llamada a 500 simultáneas sin rehacer todo.
El sistema que recorro acá resuelve exactamente eso. Llamadas sueltas, campañas masivas desde un CSV, y contexto configurable por contacto que llega directo al agente. Todo sobre la nube de LiveKit más la red telefónica global de Twilio. El techo, una vez bien configurado, supera las 1000 llamadas concurrentes por minuto.
La interfaz web expone dos modos. El modo de llamada única toma un número, un nombre de contacto opcional, una configuración de voz y la selección de idioma (inglés o español). Además, un bloque de texto libre donde describís la situación que el agente tiene que conocer. En la demo que corrí, el contexto era que un cliente había sumado un Smart TV de 43 pulgadas al carrito y no completó la compra. El agente manejó el rechazo con soltura y cortó.
El modo campaña toma un CSV. Las columnas mapean a número, nombre y cualquier columna extra de contexto que quieras que el agente lea al momento de llamar. Eso último importa: el contexto no es estático en toda la campaña. Cada contacto puede traer sus propios datos, que el agente lee antes de discar. Esa es la diferencia entre un discador masivo y algo que de verdad personaliza a escala.
Entre los proveedores de voz están Cartesia, Deepgram, Rime y ElevenLabs, cada uno con sus variantes de idioma. Podés escuchar una previa antes de decidir. También hay una vista de llamadas activas que muestra qué está corriendo en cada momento.
La arquitectura
El camino del request arranca en el frontend web, que dispara un POST /call al backend FastAPI. Desde ahí el backend despacha esa llamada como task a la nube de LiveKit. Nunca intenta manejar el media él mismo.

Cuando se crea la Room de LiveKit, se suman tres participantes: el worker del agente, el modelo de IA y, después, quien recibe la llamada. El speech-to-text corre con la inferencia nativa de Deepgram del lado de LiveKit. La capa de LLM es GPT-4o Mini de OpenAI. El text-to-speech pasa por Cartesia. Todo eso corre dentro de la infraestructura de LiveKit, no la tuya.
La conexión entre LiveKit y Twilio va por SIP trunks. Esa es la pieza que hace posible la concurrencia.
Los SIP trunks son un estándar de telefonía para mandar y recibir llamadas sobre una red privada o pública. Acá estás conectando la red SIP de LiveKit con la de Twilio. Cada plataforma se encarga de su lado del relay de media, del ruteo y de la distribución geográfica. No provisionás servidores, no manejás latencia entre regiones, no te preocupás por si tu backend aguanta 400 streams de audio simultáneos. Configurás el trunk una vez y las dos plataformas hacen el resto.
La configuración va así:
Del lado de Twilio, creás un SIP trunk, definís una credential list para la autenticación (usuario y contraseña) y asociás tu número de Twilio a ese trunk. Los settings de termination definen adónde se rutean las llamadas salientes cuando dejan la red de Twilio.
Twilio Console:
- Voice → SIP Trunks → [your trunk]
- Termination: set trunk name
- Credentials: create user/pass pair
- Numbers: associate your Twilio phone number
Del lado de LiveKit, andá a Telephony → SIP Trunks → crear outbound trunk. El campo address toma la SIP URI de Twilio que sacaste de la configuración del trunk. Sumás los números de tu cuenta de Twilio y cargás las credenciales que creaste del lado de Twilio.
LiveKit Console:
- Telephony → SIP Trunks → New Outbound Trunk
- Address: [Twilio SIP termination URI]
- Phone numbers: [your Twilio number(s)]
- Auth: user/pass from Twilio credential list
Con los dos lados configurados, LiveKit y Twilio ya saben hablarse. Tu backend solo despacha tasks de llamada y el trunk se ocupa del camino del media.
Hay dos procesos de Python que tienen que correr en paralelo.
server.py es el backend FastAPI. Expone endpoints para llamadas sueltas, despacho de campañas, listado de llamadas activas y un health check. Maneja la normalización de números, CORS y el despacho a LiveKit. Para la mayoría de los casos no vas a necesitar tocar nada acá.
agent.py es el worker del agente de LiveKit. Ahí vive el comportamiento real de la IA.
# Simplified entry point from agent.py
async def entrypoint(ctx: JobContext):
# Base instructions fallback if none passed from UI
instructions = ctx.job.metadata.get("instructions") or DEFAULT_INSTRUCTIONS
language = ctx.job.metadata.get("language", "en")
if language == "es":
instructions += "\nSiempre responde en español."
# Create SIP participant for outbound call
await ctx.connect()
participant = await ctx.room.create_sip_participant(
sip_trunk_id=SIP_TRUNK_ID,
phone_number=ctx.job.metadata["phone_number"],
...
)
# Initialize agent with GPT-4o Mini
agent = VoicePipelineAgent(
vad=silero.VAD.load(),
stt=deepgram.STT(),
llm=openai.LLM(model="gpt-4o-mini"),
tts=cartesia.TTS(),
chat_ctx=ChatContext(messages=[
ChatMessage(role="system", content=instructions)
])
)
agent.start(ctx.room, participant)
El archivo .env necesita seis valores:
OPENAI_API_KEY=...
LIVEKIT_URL=...
LIVEKIT_API_KEY=...
LIVEKIT_API_SECRET=...
SIP_TRUNK_ID=...
SIP_TRUNK_ADDRESS=…
La key de OpenAI sale de platform.openai.com, en API keys. Las credenciales de LiveKit salen de la consola, en Settings → API Keys, que genera la URL, la key y el secret juntos. El ID y la dirección del SIP trunk salen de la sección Telephony de LiveKit, una vez creado el outbound trunk.
Para correr el sistema:
# Terminal 1: backend
python server.py
# Terminal 2: agent worker (keeps connection to LiveKit cloud open)
python agent.py dev
El proceso del agente mantiene una conexión persistente con LiveKit. Cuando se despacha una llamada, LiveKit la rutea a una instancia de worker disponible. Así es como el mismo código escala horizontal sin que cambies nada.
El plan builder de LiveKit hoy es gratis y cubre volumen suficiente para pruebas y cargas de producción moderadas. OpenAI cobra las transcripciones de STT y TTS en las dos direcciones, pero con los precios actuales, 500 a 1000+ llamadas por mes salen razonables.
Twilio cobra por minuto las llamadas salientes por su red PSTN. Esa es la variable de costo principal a modelar si planeás campañas de alto volumen.
El caso de uso de la arquitectura es genérico a propósito. El contexto del agente se configura en el momento de la llamada, así que no quedás atado a un solo caso. El carrito abandonado es la demo, pero el mismo armado sirve para recordatorios de turnos, seguimiento de leads o encuestas post-compra. Sirve para cualquier flujo saliente donde el agente necesite saber algo puntual de la persona a la que llama.
El modo campaña con contexto por fila en el CSV es lo que lo saca de la categoría de curiosidad. Si tu CRM exporta un CSV con datos por cliente, tu agente lee esos datos antes de discar.
El link del repo está en la descripción del video. El README tiene los pasos completos de setup. Si lo extendés, la dirección más obvia es sumar un endpoint de webhook que mande los resultados de cada llamada a tu CRM.
-Gonza
Tags: livekit, twilio, voice-ai, outbound-calling, sip-trunks, llm-agents
Descubre cuánto te está costando tu sistema de comunicaciones.
Obtén la auditoría de comunicaciones