Agente de voz IA con traspaso a humano: Twilio y ElevenLabs

2 de octubre de 2026 • 10 min de lectura

Inicio / Blog / Agente de voz IA con traspaso a humano: Twilio y ElevenLabs

Sobre el autor

Author

Gonzalo Gomez

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.

Suscríbete a mi newsletter

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.

Agente de voz IA con traspaso a humano: Twilio y ElevenLabs | Cómo pasar la llamada de un agente de voz IA a una persona con Twilio ConversationRelay y ElevenLabs: costos reales por minuto y el código que decide cuándo.

Un agente de voz IA puede responder todas las preguntas frecuentes que recibe una concesionaria, con el tono y los horarios correctos, y aun así perder al cliente. No porque las respuestas estén mal. Porque cuando la llamada necesita una persona, o el agente no lo detecta o el traspaso es tan torpe que el cliente corta antes.

 

En el 80 a 90 por ciento de los flujos de voz con agentes que audité para clientes, ese paso falta o está agregado a último momento. Este post recorre la versión mínima que funciona en producción. Son cinco piezas: un número de Twilio, ConversationRelay para el loop de audio, una voz de ElevenLabs, un modelo chico vía OpenRouter y un traspaso que dispara el propio agente. También te muestra la factura, porque la factura cambia el diseño.

 

El escenario: una concesionaria que responde y deriva

 

La empresa de la demo es una concesionaria de autos. El agente tiene la identidad de la empresa y los horarios (lunes a viernes de 9 a 19, sábados de 9 a 13). También conoce el inventario nuevo y usado, las reglas de financiación y de test drive, el taller, los repuestos, las garantías y las preguntas frecuentes. Y tiene una instrucción explícita: cuando el pedido requiere una persona, por ejemplo agendar un test drive, tiene que derivar al equipo de ventas.

 

Ese alcance es deliberado. Cuando un negocio está arrancando con agentes de voz, no le das mucha libertad al agente. Responde preguntas frecuentes, y lo que no puede responder va a ventas. Es un primer despliegue común y correcto, y el traspaso es la pieza que lo hace seguro.

 

Una llamada real de la demo, resumida: pregunto si están abiertos y me da los horarios. Pregunto por sedanes y me dice "sedanes nuevos desde 32 millones de pesos más usados seleccionados". Pregunto por test drives y me da el requisito (reservar un turno con un asesor y traer el registro vigente) y la oferta de transferirme. Digo que sí, y dos segundos después la llamada suena en mi navegador con un resumen de lo que pregunté ya en pantalla.

 

Arquitectura: qué maneja Twilio y qué manejás vos

 

Las capas, en orden:

 

  • El que llama marca un número de Twilio. Twilio hace un POST a mi endpoint /voice (corriendo local a través de un túnel durante el desarrollo, en un VPS en producción).
  • /voice devuelve TwiML que conecta la llamada a ConversationRelay, con el proveedor de TTS, el id de la voz y el idioma.
  • ConversationRelay resuelve el speech to text y el text to speech en la nube de Twilio y abre un WebSocket a mi endpoint /relay. De acá en adelante mi servidor solo ve texto.
  • /relay contiene al agente: el contexto de la empresa, el prompt, las tools y el log de turnos. Las respuestas vuelven al teléfono en streaming, a medida que se generan.
  • Cuando el agente decide hacer el traspaso, un endpoint /handoff separado guarda el motivo y le manda al asesor un SMS con el resumen. Después redirige la llamada a un número de teléfono o a un cliente en el navegador.

 

El endpoint de voz es corto. Esta es su forma:

 

app.post("/voice", (req, res) => {
  const twiml = `
    <Response>
      <Connect>
        <ConversationRelay
          url="wss://${process.env.HOST}/relay"
          ttsProvider="ElevenLabs"
          voice="${process.env.ELEVENLABS_VOICE_ID}"
          language="es-AR"
          interruptible="true"
          reportInputDuringAgentSpeech="true"
        />
      </Connect>
    </Response>`;
  res.type("text/xml").send(twiml);
});

 

Dos atributos importan más de lo que parece. interruptible es lo que permite que el que llama hable encima del agente y que el agente se calle al instante. Lo probé interrumpiendo a mitad de frase y cortó inmediatamente. Y el proveedor y la voz son configuración, no código: ConversationRelay soporta varios proveedores de TTS, y cambiar ElevenLabs por otro es cambiar un atributo.

 

Streaming, porque el silencio es el modo de falla

 

Si esperás a que el modelo termine toda la respuesta antes de mandarle texto a ConversationRelay, el que llama escucha segundos de nada. En una llamada telefónica, eso se lee como "se cortó la línea". El relay manda los tokens en streaming a medida que llegan:

 

for await (const chunk of stream) {
  const token = chunk.choices?.[0]?.delta?.content;
  if (!token) continue;
  ws.send(JSON.stringify({ type: "text", token, last: false }));
}
ws.send(JSON.stringify({ type: "text", token: "", last: true }));

 

La segunda palanca de latencia es la carga de contexto. Mandar todo el contexto de la empresa en el primer turno hacía que la primera respuesta fuera notablemente más lenta. Por eso el proyecto tiene dos estrategias detrás de una variable de entorno. La estrategia full manda todo en el primer turno. La lazy manda primero la parte vital y carga el resto mientras se dice la primera respuesta, así que en el segundo turno el agente ya está completo. Para un agente de preguntas frecuentes, gana lazy.

 

El traspaso es una tool, no un parche al final

 

El archivo más importante del repo es la definición de tools en la carpeta del agente. El traspaso es una tool que el modelo puede llamar, con dos disparadores escritos en su descripción. O el que llama pide explícitamente una persona, o el pedido es algo que el agente no puede hacer. Una segunda tool termina la conversación cuando el que llama se despide.

 

export const tools = [
  {
    type: "function",
    function: {
      name: "request_handoff",
      description:
        "Transfer the call to a human advisor. Use when the caller asks to speak with a person, or when the request is outside what you can resolve (booking a test drive, complaints, anything requiring action on an account).",
      parameters: {
        type: "object",
        properties: {
          reason: { type: "string", description: "Short summary of why the caller needs a human, in the caller's language." },
          department: { type: "string", enum: ["sales", "support"] },
        },
        required: ["reason"],
      },
    },
  },
  {
    type: "function",
    function: {
      name: "end_conversation",
      description: "End the call when the caller says goodbye or has nothing else to ask.",
      parameters: { type: "object", properties: {} },
    },
  },
];

 

Cuando se dispara request_handoff, el relay guarda la decisión y el motivo, le manda un resumen por SMS al asesor y le pide a Twilio que redirija la llamada. El asesor atiende sabiendo ya por qué llama la persona. En la demo hay un solo departamento, pero la misma estructura permite rutear a ventas, soporte o taller, cada uno con su número.

 

Sumarle capacidades al agente es sumar entradas a ese array. Esa es toda la historia de extensibilidad, y alcanza para la mayoría de los primeros despliegues.

 

El prompt: decile al agente qué día es

 

El system prompt dice quién es el agente, que responde solo con el contexto de abajo, cómo tiene que hablar, cuándo terminar la llamada y que tiene request_handoff disponible. También inyecta la fecha y la hora actuales en cada llamada:

 

export function systemPrompt(context: string) {
  const now = new Date().toLocaleString("es-AR", { timeZone: process.env.TIMEZONE ?? "America/Argentina/Buenos_Aires" });
  return `You answer the phone for ${process.env.COMPANY_NAME}.
Answer only with the information in the context below. If something is not there, say you don't know and offer a human advisor.
Current date and time: ${now}. Use it to answer whether the business is open, how long until it opens, and any relative date.
Speak briefly, in a warm and direct tone, in Rioplatense Spanish.
End the call with end_conversation when the caller says goodbye.
Use request_handoff when the caller asks for a person or asks for something you cannot do.

Context:
${context}`;
}

 

Pasar la fecha parece trivial. Es el bug más común que encuentro en agentes de voz y de mensajería: un modelo no tiene reloj, y sin uno responde "¿están abiertos ahora?" con seguridad y mal. Cada pregunta de fecha relativa de la demo (si están abiertos ahora, cuánto falta para el lunes) se resuelve con esa sola línea.

 

El modelo: chico a propósito

 

El proyecto habla con los modelos a través de OpenRouter, así que el proveedor es una variable de entorno. Usé Claude Haiku 4.5. Es un modelo liviano, y es uno de los mejores que usé para conversación en tiempo real justamente porque es liviano. Un modelo que "piensa" dos segundos de más antes de hablar hace que el agente suene robótico. Y el que espera en la línea corta antes de que llegue la respuesta inteligente.

 

Algo que me sorprendió: Whisper transcribió "tre drives" en lugar de "test drives". Igual el modelo entendió y respondió sobre test drives. El STT no tiene que ser perfecto para un agente de preguntas frecuentes cuando el modelo tiene contexto suficiente para recuperarse.

 

Cuánto cuesta por minuto

 

Dos facturas.

 

OpenRouter, Haiku 4.5: unos 5 centavos de dólar por aproximadamente 5 minutos de conversación. Digamos 1 centavo por minuto de modelo.

 

Twilio ConversationRelay: 9 minutos de llamadas, 63 centavos. Eso cubre la telefonía, el speech to text y el text to speech con la voz de ElevenLabs. Unos 7 centavos por minuto.

 

Entonces el total ronda los 8 centavos por minuto, y el modelo es un centavo de eso. Si estás optimizando tu agente de voz cambiando de modelo, estás optimizando la línea equivocada. Lo que mueve la factura es la duración de la llamada, y el traspaso es lo que acorta las llamadas que el agente no puede resolver.

 

Tres criterios antes de dejar que un agente atienda tu teléfono

 

La infraestructura como cuello de botella. Muchos de los clientes con los que trabajo no quieren correr servidores ni infraestructura de audio. Para ellos el camino gestionado es el correcto: pagar un fee encima del stack de comunicaciones que ya tienen y olvidarse de la operación. Twilio pone el audio y ElevenLabs el loop conversacional. Es un despliegue legítimo y lo recomiendo seguido.

 

Si necesitás ajustar cada paso. Puede que el flujo necesite que el agente decida cuándo escuchar y cuándo hablar. O que participe de una conferencia entre un cliente y una persona de soporte y solo intervenga cuando le hablan. O que salga de la llamada con un criterio distinto de "el que llama se despidió". En cualquiera de esos casos necesitás tu propio cerebro y control total de la lógica de turnos. Un proveedor de telefonía no debería decidir cuándo escucha tu agente.

 

La lógica de traspaso siempre es tuya. El reclamo por facturación es el caso típico: alguien que llama enojado, un agente sin tools para corregir el cobro, y un agente que igual prueba arreglarlo. El cliente se frustra más, ahora con una máquina, y el problema escala en lugar de resolverse. Tiene que haber una persona supervisando, o por lo menos disponible. Y el agente necesita una salida limpia que pueda disparar ante pedidos explícitos y, cuando llegues ahí, también por sentimiento. Suena básico. En 8 de cada 10 flujos que reviso, es el paso que se saltearon.

 

Elegí el camino gestionado si hace falta. Pero la decisión de cuándo derivar a una persona dejala igual en tu propio código.

 

-Gonza

6
Twilio,  AI Agents,  OpenRouter,  ConversationRelay,  ElevenLabs,  Voice AI
Publicado el 2 de octubre de 2026

¿Estás construyendo algo así sobre Twilio? Ayudo a empresas a diseñar y operar estos sistemas en producción. Conoce mi servicio de consultoría y desarrollo Twilio.

Descubre cuánto te está costando tu sistema de comunicaciones.

Obtén la auditoría de comunicaciones

Posts relacionados

Llamadas salientes con IA usando n8n, Twilio y ElevenLabs

30 de enero de 2026
IntroducciónLas llamadas salientes de ventas son uno de los canales más difíciles de automatizar con IA. La latencia importa.Los costos se acumulan rápido.Las alucinaciones no se... Leer más

Cómo correr un agente de IA gratis en tu VPS con Hermes

18 de agosto de 2026
Tengo un agente de IA corriendo 24/7 en un VPS que ya estaba pagando y casi no usaba. Me manda un resumen de noticias de... Leer más

Recuperación de leads con IA: N8N, Twilio y ElevenLabs

27 de abril de 2026
Sistema de recuperación de leads con IA: cómo lo armé con N8N, Twilio y ElevenLabs IntroducciónLa mayoría de los negocios pierde leads no porque el producto... Leer más

Claude Agent Skills para un agente de WhatsApp en producción

11 de septiembre de 2026
Lo primero que hizo mi agente frente a la cámara fue fallar una tool call. Llamó a create_client con argumentos que mi función no aceptaba... Leer más