Skip to main content
ai voice20 de enero de 202618 min de lectura

Cómo Construir Agentes de Voz con IA en Producción con Vapi.ai (Guía Completa 2026)

Guía paso a paso para construir agentes de voz con IA usando Vapi.ai. Aprenda la arquitectura, patrones de implementación y mejores prácticas de producción desde experiencia real.

Loic Bachellerie

Senior Product Engineer

Introducción

Recientemente construí una recepcionista con IA 24/7 para una empresa de plomería que ahora maneja más de 200 llamadas por mes. El dueño pasó de perder el 40% de las llamadas a capturar el 98%. Tiempo total de configuración: 3 horas.

Esta guía le enseña cómo construir agentes de voz con IA listos para producción usando Vapi.ai, la plataforma que hace que el desarrollo de voz con IA sea realmente viable para equipos pequeños.

Al final, comprenderá:

  • La arquitectura STT → LLM → TTS
  • Cómo configurar Vapi con llamada a funciones apropiada
  • Patrones de producción para manejo de errores
  • Estrategias de optimización de costos
  • Patrones reales de despliegue que utilizo

Comencemos.

La Arquitectura de Voz con IA

Antes de escribir código, entienda el pipeline:

Arquitectura del Pipeline de Voz con IA

Cómo la voz con IA transforma el habla en respuestas inteligentes

Voz Entrada
STT
LLM
Función
TTS
Plataforma Vapi.ai
TwilioOpenAIElevenLabsSu APICRM
Menos de 1s de latencia

El Flujo:

  1. Speech-to-Text (STT): Vapi usa Deepgram o Whisper para transcribir el habla
  2. Procesamiento LLM: OpenAI, Claude o su modelo personalizado procesa la intención
  3. Llamada a Funciones: Sus endpoints de backend manejan la lógica de negocio
  4. Text-to-Speech (TTS): ElevenLabs u OpenAI convierte la respuesta a voz
  5. Respuesta: El que llama escucha al IA hablar

¿Por qué Vapi?

  • Maneja todas las partes difíciles (latencia, interrupciones, detección de habla)
  • Tiempos de respuesta de menos de 1 segundo
  • Llamada a funciones integrada
  • API simple
  • ~$0.05-0.10 por minuto (vs construirlo usted mismo: $50k+ en tiempo de desarrollo)

Requisitos Previos

Antes de comenzar, necesitará:

  • Cuenta de Vapi (nivel gratuito disponible)
  • Cuenta de Twilio (para números telefónicos)
  • Clave de API de OpenAI (o Anthropic para Claude)
  • Conocimiento básico de TypeScript/JavaScript
  • Endpoint de backend (puede ser Vercel, Railway o su servidor)

Tiempo requerido: 2-4 horas para el primer agente.

Paso 1: Configurando su Primer Asistente

Crear el Asistente

// lib/vapi.ts
import { VapiClient } from "@vapi-ai/server-sdk";
 
const client = new VapiClient({ token: process.env.VAPI_API_KEY });
 
export async function createAssistant() {
  const assistant = await client.assistants.create({
    name: "Plumbing Receptionist",
    model: {
      provider: "openai",
      model: "gpt-4",
      temperature: 0.7,
      systemPrompt: `You are a professional receptionist for a plumbing company.
 
Your job:
- Greet callers warmly
- Collect their name, address, and issue description
- Determine if it's an emergency
- Schedule appointments for non-emergencies
- Capture lead information
 
Rules:
- Be concise (under 30 seconds per response)
- Always confirm details back to the caller
- If emergency, collect contact number and say a plumber will call within 15 minutes
- Never say "I don't know", offer to have a human call back`,
    },
    voice: {
      provider: "elevenlabs",
      voiceId: "21m00Tcm4TlvDq8ikWAM", // Rachel
    },
    firstMessage: "Hello! Thanks for calling. I'm here to help with your plumbing needs. What can I assist you with today?",
  });
 
  return assistant;
}

Explicación de la Configuración Clave

Selección de Modelo:

  • gpt-4: Mejor calidad, mayor latencia (~1.5s), $0.03/1K tokens
  • gpt-3.5-turbo: Más rápido (~0.8s), más económico, bueno para agentes simples
  • claude-3-sonnet: Excelente para razonamiento complejo

Selección de Voz:

  • Las voces de ElevenLabs suenan más naturales
  • Las voces de OpenAI son más económicas pero más robóticas
  • Pruebe múltiples voces, importa más de lo que piensa

Consejos para el System Prompt:

  • Sea específico sobre el tono y la extensión
  • Incluya ejemplos de lo que NO decir
  • Agregue barandillas para casos extremos
  • Manténgalo por debajo de 2000 tokens

Paso 2: Agregando Llamada a Funciones

Las funciones permiten que su IA interactúe con sus sistemas. Aquí hay una función de captura de leads:

// lib/vapi-functions.ts
 
interface LeadCaptureParams {
  name: string;
  phone: string;
  address: string;
  issue: string;
  isEmergency: boolean;
}
 
export async function captureLead(params: LeadCaptureParams) {
  // Save to your CRM (Airtable, HubSpot, etc.)
  await saveToCRM({
    ...params,
    source: "voice-agent",
    timestamp: new Date().toISOString(),
  });
 
  // Send notification
  if (params.isEmergency) {
    await sendEmergencyAlert(params);
  }
 
  return {
    success: true,
    message: params.isEmergency
      ? "Emergency logged. A plumber will call you within 15 minutes."
      : "Great! I've scheduled you for tomorrow between 2-4 PM. You'll get a confirmation text.",
  };
}
 
// Vapi function schema
export const captureLeadSchema = {
  name: "captureLead",
  description: "Capture lead information and schedule appointment",
  parameters: {
    type: "object",
    properties: {
      name: {
        type: "string",
        description: "Caller's full name",
      },
      phone: {
        type: "string",
        description: "Caller's phone number",
      },
      address: {
        type: "string",
        description: "Service address",
      },
      issue: {
        type: "string",
        description: "Brief description of plumbing issue",
      },
      isEmergency: {
        type: "boolean",
        description: "True if water damage, no water, or sewage backup",
      },
    },
    required: ["name", "phone", "issue", "isEmergency"],
  },
};

Llamada a Funciones del Agente de Voz

Cómo su IA se conecta a los sistemas reales del negocio

Agente de Voz
Función
Sistemas Externos
CRM / Airtable
Calendario
Email / SendGrid
Slack
Latencia menor a 1 segundo

Registrar Funciones con el Asistente

// Update your assistant creation
const assistant = await client.assistants.create({
  // ... previous config
  functions: [
    {
      name: "captureLead",
      description: captureLeadSchema.description,
      parameters: captureLeadSchema.parameters,
      async: true, // Your endpoint handles this
    },
  ],
});

Crear el Endpoint de Webhook

// app/api/vapi/webhook/route.ts
import { NextRequest, NextResponse } from "next/server";
import { captureLead } from "@/lib/vapi-functions";
 
export async function POST(request: NextRequest) {
  const body = await request.json();
 
  // Vapi sends different message types
  const { message } = body;
 
  switch (message.type) {
    case "function-call":
      if (message.functionCall.name === "captureLead") {
        const result = await captureLead(message.functionCall.parameters);
        return NextResponse.json({
          result,
        });
      }
      break;
 
    case "end-of-call-report":
      // Log call analytics
      console.log("Call ended:", message);
      break;
 
    case "speech-update":
      // Real-time transcription (optional)
      break;
  }
 
  return NextResponse.json({ status: "ok" });
}

Paso 3: Conectando un Número Telefónico

Comprar un Número en Twilio

// lib/twilio.ts
import twilio from "twilio";
 
const client = twilio(
  process.env.TWILIO_ACCOUNT_SID,
  process.env.TWILIO_AUTH_TOKEN
);
 
export async function buyPhoneNumber(areaCode: string) {
  const numbers = await client.availablePhoneNumbers("US")
    .local
    .list({ areaCode, limit: 1 });
 
  if (numbers.length === 0) {
    throw new Error("No numbers available in this area code");
  }
 
  const purchased = await client.incomingPhoneNumbers.create({
    phoneNumber: numbers[0].phoneNumber,
    voiceUrl: "https://your-domain.com/api/vapi/inbound", // We'll create this
  });
 
  return purchased.phoneNumber;
}

Crear el Handler de Llamadas Entrantes

// app/api/vapi/inbound/route.ts
import { NextRequest, NextResponse } from "next/server";
import twilio from "twilio";
 
const TWIML = `
<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Connect>
    <Stream url="wss://your-vapi-websocket-url">
      <Parameter name="assistantId" value="your-assistant-id" />
    </Stream>
  </Connect>
</Response>
`;
 
export async function POST(request: NextRequest) {
  // You can add call screening logic here
  // E.g., check if business hours, spam detection, etc.
 
  return new NextResponse(TWIML, {
    headers: {
      "Content-Type": "text/xml",
    },
  });
}

Usando el Número Telefónico de Vapi

Alternativamente, compre directamente a través de Vapi:

// Easier but less control
const phoneNumber = await client.phoneNumbers.create({
  provider: "twilio",
  areaCode: "555",
  assistantId: assistant.id,
});

Opciones de Configuración de Número Telefónico

Conecte su agente de voz a líneas telefónicas

Traiga su Propio Twilio
1Comprar número en Twilio
2Configurar URL de voz hacia Vapi
3Control total sobre enrutamiento
~$1/mesRecomendado
Números Gestionados por Vapi
1Comprar a través del dashboard de Vapi
2Cero configuración necesaria
3Incluido en tarifa por minuto
Incluido en costo por minutoInicio Rápido
Persona que llama - Teléfono - Agente de Voz - Respuesta

Paso 4: Patrones de Producción

Manejo de Errores

Los agentes de voz fallan. Planifique para ello:

// lib/vapi-error-handler.ts
 
interface ErrorContext {
  callId: string;
  assistantId: string;
  customerPhone: string;
  error: Error;
  transcript: string;
}
 
export async function handleVoiceError(context: ErrorContext) {
  // 1. Log to monitoring
  await logError(context);
 
  // 2. Send fallback SMS
  await sendSMS({
    to: context.customerPhone,
    body: "Sorry, we had a technical issue. A human will call you back within 10 minutes.",
  });
 
  // 3. Alert team
  await sendSlackAlert({
    channel: "#voice-agent-alerts",
    text: `Voice agent failed for call ${context.callId}`,
    error: context.error.message,
  });
 
  // 4. Create task for human follow-up
  await createTask({
    type: "voice-agent-fallback",
    priority: "high",
    customerPhone: context.customerPhone,
    context: context.transcript,
  });
}

Limitación de Tasa y Prevención de Abuso

// middleware.ts or API route
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";
 
const ratelimit = new Ratelimit({
  redis: Redis.fromEnv(),
  limiter: Ratelimit.slidingWindow(10, "1 m"), // 10 calls per minute per number
});
 
export async function middleware(request: NextRequest) {
  const ip = request.ip ?? "127.0.0.1";
  const { success, limit, remaining } = await ratelimit.limit(ip);
 
  if (!success) {
    return new NextResponse("Rate limit exceeded", { status: 429 });
  }
 
  return NextResponse.next();
}

Optimización de Costos

Los agentes de voz pueden volverse costosos rápidamente. Así es como mantengo los costos por debajo de $200/mes para más de 200 llamadas:

EstrategiaAhorroImplementación
Usar gpt-3.5 para consultas simples60%Enrutar basado en intención
Cachear respuestas comunes30%Redis para FAQs
Acortar prompts20%Mantener por debajo de 1000 tokens
Usar voces de OpenAI50%vs ElevenLabs
Agrupar llamadas a funciones15%Combinar operaciones
// Smart routing example
const model = detectSimpleQuery(transcript)
  ? "gpt-3.5-turbo" // $0.0015/1K tokens
  : "gpt-4";        // $0.03/1K tokens

Paso 5: Pruebas y Monitoreo

Pruebas Automatizadas

// tests/vapi.test.ts
import { test, expect } from "@playwright/test";
 
test("AI receptionist captures leads correctly", async ({ page }) => {
  // Mock a call
  const call = await startTestCall({
    phoneNumber: "+15551234567",
    scenario: "emergency_leak",
  });
 
  // Simulate conversation
  await call.speak("Hi, I have a water leak in my basement");
 
  const response = await call.waitForResponse();
  expect(response).toContain("emergency");
  expect(response).toContain("15 minutes");
 
  // Verify function was called
  const lead = await getLastLead();
  expect(lead.isEmergency).toBe(true);
  expect(lead.issue).toContain("leak");
});

Panel de Monitoreo

Haga seguimiento de estas métricas:

// Key metrics to log
interface CallMetrics {
  callId: string;
  duration: number;           // seconds
  cost: number;               // USD
  transcriptLength: number;   // characters
  functionsCalled: number;
  errors: number;
  customerSatisfaction?: number; // Post-call survey
  resolved: boolean;          // Did it solve the problem?
}
 
// Alert on:
// - >5% error rate
// - >$0.50 average cost per call
// - >10s average latency
// - <80% resolution rate

Ejemplo del Mundo Real: Resultados del Negocio de Plomería

La Configuración:

  • 1 número telefónico (código de área local)
  • GPT-4 para problemas complejos, GPT-3.5 para simples
  • 3 funciones: captureLead, scheduleAppointment, checkAvailability
  • Fallback a humano después de 3 errores

Resultados Después de 3 Meses:

  • 247 llamadas gestionadas
  • 94% capturadas (vs 60% antes)
  • Duración promedio de llamada: 2m 15s
  • Costo por llamada: $0.12
  • 23 llamadas de emergencia fuera de horario capturadas
  • Tiempo ahorrado al dueño: 15 horas/semana

Lo que Funcionó:

  • Prompt de sistema específico con ejemplos
  • Función de detección de emergencias
  • Fallback por SMS para llamadas fallidas
  • Revisión diaria de transcripciones durante las primeras 2 semanas

Lo que No Funcionó:

  • Inicialmente muy verboso (corregido con la instrucción "sea conciso")
  • No capturaba email (agregado a la función)
  • Confundía direcciones (se agregó paso de confirmación)

Próximos Pasos

Ahora que entiende lo básico:

  1. Construya su primer agente: Comience simple, agregue funciones gradualmente
  2. Pruebe con llamadas reales: Pida a amigos/familia que llamen y den retroalimentación
  3. Monitoree e itere: Revise transcripciones diariamente al principio
  4. Escale gradualmente: Agregue características a medida que entienda los modos de falla

En el próximo artículo, cubriré patrones avanzados:

  • Soporte multilenguaje
  • Fine-tuning de LLM personalizado
  • Integración con sistemas CRM
  • Construcción de agentes de voz que suenen verdaderamente humanos

Preguntas Frecuentes

P: ¿Cuánto cuesta Vapi? R: ~$0.05-0.15 por minuto dependiendo de la configuración. Una llamada de 2 minutos cuesta aproximadamente $0.20.

P: ¿Puedo usar mi propio número telefónico? R: Sí, a través de la integración con Twilio. O compre directamente a través de Vapi.

P: ¿Qué pasa si la IA no entiende? R: Construya lógica de fallback. Después de 2 malentendidos, ofrezca transferir o tomar un mensaje.

P: ¿Es compatible con HIPAA? R: Vapi es compatible con SOC 2. Para HIPAA, necesitará un BAA y salvaguardas adicionales.

P: ¿Puede manejar acentos? R: Sí, pero pruebe con su base de clientes específica. Deepgram maneja bien la mayoría de los acentos.


¿Necesita ayuda implementando esto para su negocio? Reserve una llamada gratuita de 30 minutos y le ayudaré a diseñar su agente de voz.

Navegación de la Serie: ← Anterior: [Voice AI Architecture Overview] | Siguiente: [Advanced Vapi Patterns: Functions & Workflows] →

Share:

Recibe perspectivas prácticas de ingeniería

Agentes de voz con IA, flujos de automatización y lanzamientos rápidos. Sin spam, cancela cuando quieras.