Skip to main content
ai voice20 de janeiro de 202618 min de leitura

Construindo Agentes de Voz com IA em Produção com Vapi.ai (Guia Completo 2026)

Guia passo a passo para construir agentes de voz com IA usando Vapi.ai. Aprenda a arquitetura, padrões de implementação e boas práticas de produção com experiência real.

Loic Bachellerie

Senior Product Engineer

Introdução

Recentemente construí uma recepcionista IA 24/7 para uma empresa de encanamento que agora gerencia mais de 200 chamadas por mês. O dono passou de perder 40% das chamadas para capturar 98%. Tempo total de configuração: 3 horas.

Este guia ensina como construir agentes de voz com IA prontos para produção usando Vapi.ai, a plataforma que torna o desenvolvimento de voice AI realmente viável para equipes pequenas.

Ao final, você vai entender:

  • A arquitetura STT → LLM → TTS
  • Como configurar o Vapi com function calling adequado
  • Padrões de produção para tratamento de erros
  • Estratégias de otimização de custos
  • Padrões reais de deploy que eu uso

Vamos começar.

A Arquitetura Voice AI

Antes de escrever código, entenda o pipeline:

Arquitetura do Pipeline Voice AI

Como a voice AI transforma fala em respostas inteligentes

Voz Entrada
STT
LLM
Função
TTS
Plataforma Vapi.ai
TwilioOpenAIElevenLabsSua APICRM
Menos de 1s de latência

O Fluxo:

  1. Speech-to-Text (STT): Vapi usa Deepgram ou Whisper para transcrever a fala
  2. Processamento LLM: OpenAI, Claude ou seu modelo customizado processa a intenção
  3. Function Calling: Seus endpoints de backend gerenciam a lógica de negócio
  4. Text-to-Speech (TTS): ElevenLabs ou OpenAI converte a resposta em voz
  5. Resposta: O chamador ouve a IA falar

Por que Vapi?

  • Gerencia todas as partes difíceis (latência, interrupções, detecção de fala)
  • Tempos de resposta inferiores a 1 segundo
  • Function calling integrado
  • API simples
  • ~$0,05-0,10 por minuto (vs construir você mesmo: $50k+ em tempo de dev)

Pré-requisitos

Antes de começar, você vai precisar de:

  • Conta Vapi (tier gratuito disponível)
  • Conta Twilio (para números de telefone)
  • Chave API OpenAI (ou Anthropic para Claude)
  • Conhecimento básico de TypeScript/JavaScript
  • Endpoint backend (pode ser Vercel, Railway ou seu servidor)

Tempo de dedicação: 2-4 horas para o primeiro agente.

Passo 1: Configurando Seu Primeiro Assistente

Criar o Assistente

// 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;
}

Configuração Principal Explicada

Seleção de Modelo:

  • gpt-4: Melhor qualidade, maior latência (~1,5s), $0,03/1K tokens
  • gpt-3.5-turbo: Mais rápido (~0,8s), mais barato, bom para agentes simples
  • claude-3-sonnet: Excelente para raciocínio complexo

Seleção de Voz:

  • Vozes ElevenLabs soam mais naturais
  • Vozes OpenAI são mais baratas mas mais robóticas
  • Teste múltiplas vozes — importa mais do que você imagina

Dicas para o System Prompt:

  • Seja específico sobre tom e comprimento
  • Inclua exemplos do que NÃO dizer
  • Adicione guardrails para casos extremos
  • Mantenha abaixo de 2000 tokens

Passo 2: Adicionando Function Calling

Funções permitem que sua IA interaja com seus sistemas. Aqui está uma função 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"],
  },
};

Function Calling do Agente de Voz

Como sua IA se conecta a sistemas reais de negócio

Agente de Voz
Função
Sistemas Externos
CRM / Airtable
Calendário
Email / SendGrid
Slack
Latência inferior a 1 segundo

Registrar Funções com o Assistente

// 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
    },
  ],
});

Criar o 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" });
}

Passo 3: Conectando um Número de Telefone

Comprar um Número no 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;
}

Criar Handler de Chamadas Recebidas

// 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 Número de Telefone do Vapi

Alternativamente, compre diretamente pelo Vapi:

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

Opções de Configuração de Número de Telefone

Conecte seu agente de voz a linhas telefônicas

Traga Seu Próprio Twilio
1Compre número no Twilio
2Configure a URL de voz para o Vapi
3Controle total sobre roteamento
~$1/mêsRecomendado
Números Gerenciados pelo Vapi
1Compre pelo dashboard do Vapi
2Zero configuração necessária
3Incluído na tarifa por minuto
Incluído no custo por minInício Rápido
Chamador - Telefone - Agente de Voz - Resposta

Passo 4: Padrões de Produção

Tratamento de Erros

Agentes de voz falham. Planeje para isso:

// 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,
  });
}

Rate Limiting e Prevenção 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();
}

Otimização de Custos

Agentes de voz podem ficar caros rapidamente. Veja como mantenho os custos abaixo de $200/mês para mais de 200 chamadas:

EstratégiaEconomiaImplementação
Usar gpt-3.5 para consultas simples60%Roteamento baseado em intenção
Cachear respostas comuns30%Redis para FAQs
Encurtar prompts20%Manter abaixo de 1000 tokens
Usar vozes OpenAI50%vs ElevenLabs
Agrupar chamadas de função15%Combinar operações
// Smart routing example
const model = detectSimpleQuery(transcript)
  ? "gpt-3.5-turbo" // $0.0015/1K tokens
  : "gpt-4";        // $0.03/1K tokens

Passo 5: Testes e Monitoramento

Testes Automatizados

// 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");
});

Dashboard de Monitoramento

Monitore 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

Exemplo Real: Resultados do Negócio de Encanamento

A Configuração:

  • 1 número de telefone (código de área local)
  • GPT-4 para questões complexas, GPT-3.5 para simples
  • 3 funções: captureLead, scheduleAppointment, checkAvailability
  • Fallback para humano após 3 erros

Resultados Após 3 Meses:

  • 247 chamadas gerenciadas
  • 94% capturadas (vs 60% antes)
  • Duração média de chamada: 2m 15s
  • Custo por chamada: $0,12
  • 23 chamadas de emergência fora do horário capturadas
  • Tempo economizado do dono: 15 horas/semana

O Que Funcionou:

  • System prompt específico com exemplos
  • Função de detecção de emergência
  • Fallback por SMS para chamadas com falha
  • Revisão diária de transcrições nas primeiras 2 semanas

O Que Não Funcionou:

  • Inicialmente muito verboso (corrigido com instrução "seja conciso")
  • Não capturava email (adicionado à função)
  • Confundia endereços (adicionado passo de confirmação)

Próximos Passos

Agora que você entende o básico:

  1. Construa seu primeiro agente: Comece simples, adicione funções gradualmente
  2. Teste com chamadas reais: Peça a amigos/família para ligar e dar feedback
  3. Monitore e itere: Revise transcrições diariamente no início
  4. Escale gradualmente: Adicione funcionalidades conforme entende os modos de falha

No próximo post, vou cobrir padrões avançados:

  • Suporte multi-idioma
  • Fine-tuning de LLM customizado
  • Integração com sistemas CRM
  • Construindo agentes de voz que soam verdadeiramente humanos

FAQ

P: Quanto custa o Vapi? R: ~$0,05-0,15 por minuto dependendo da configuração. Uma chamada de 2 minutos custa cerca de $0,20.

P: Posso usar meu próprio número de telefone? R: Sim, via integração com Twilio. Ou compre diretamente pelo Vapi.

P: E se a IA não entender? R: Construa lógica de fallback. Após 2 mal-entendidos, ofereça transferir ou deixar uma mensagem.

P: É compatível com HIPAA? R: Vapi tem certificação SOC 2. Para HIPAA, você vai precisar de um BAA e salvaguardas adicionais.

P: Consegue lidar com sotaques? R: Sim, mas teste com sua base de clientes específica. Deepgram lida bem com a maioria dos sotaques.


Precisa de ajuda para implementar isso no seu negócio? Agende uma chamada gratuita de 30 minutos e vou ajudar você a projetar seu agente de voz.

Navegação da Série: ← Anterior: [Voice AI Architecture Overview] | Próximo: [Advanced Vapi Patterns: Functions & Workflows] →

Share:

Receba insights práticos de engenharia

Agentes de voz com IA, fluxos de automação e entregas rápidas. Sem spam, cancele quando quiser.