Skip to main content
ai voice20 janvier 202618 min de lecture

Créer des agents vocaux IA en production avec Vapi.ai (Guide complet 2026)

Guide étape par étape pour créer des agents vocaux IA avec Vapi.ai. Architecture, patterns d'implémentation et bonnes pratiques de production issues d'une expérience terrain.

Loic Bachellerie

Senior Product Engineer

Introduction

J'ai récemment construit un réceptionniste IA 24h/24 pour une entreprise de plomberie qui gère désormais plus de 200 appels par mois. Le propriétaire est passé de 40 % d'appels manqués à 98 % d'appels captés. Temps de mise en place : 3 heures.

Ce guide vous apprend à construire des agents vocaux IA prêts pour la production avec Vapi.ai, la plateforme qui rend le développement d'IA vocale réellement faisable pour les petites équipes.

À la fin, vous comprendrez :

  • L'architecture STT → LLM → TTS
  • Comment configurer Vapi avec un function calling approprié
  • Les patterns de production pour la gestion des erreurs
  • Les stratégies d'optimisation des coûts
  • Les patterns de déploiement réels que j'utilise

Allons-y.

L'architecture de l'IA vocale

Avant d'écrire du code, comprenez le pipeline :

Architecture du pipeline d'IA vocale

Comment l'IA vocale transforme la parole en réponses intelligentes

Voix entrante
STT
LLM
Fonction
TTS
Plateforme Vapi.ai
TwilioOpenAIElevenLabsVotre APICRM
Latence inférieure à 1 s

Le flux :

  1. Speech-to-Text (STT) : Vapi utilise Deepgram ou Whisper pour transcrire la parole
  2. Traitement LLM : OpenAI, Claude ou votre modèle personnalisé traite l'intention
  3. Function calling : Vos endpoints backend gèrent la logique métier
  4. Text-to-Speech (TTS) : ElevenLabs ou OpenAI convertit la réponse en voix
  5. Réponse : L'appelant entend l'IA parler

Pourquoi Vapi ?

  • Gère toutes les parties difficiles (latence, interruptions, détection de parole)
  • Temps de réponse inférieur à 1 seconde
  • Function calling intégré
  • API simple
  • ~0,05-0,10 $ par minute (vs construction en interne : 50 000 $+ de temps de développement)

Prérequis

Avant de commencer, vous aurez besoin de :

  • Compte Vapi (offre gratuite disponible)
  • Compte Twilio (pour les numéros de téléphone)
  • Clé API OpenAI (ou Anthropic pour Claude)
  • Connaissances de base en TypeScript/JavaScript
  • Endpoint backend (peut être Vercel, Railway ou votre serveur)

Temps d'investissement : 2-4 heures pour le premier agent.

Étape 1 : Configurer votre premier assistant

Créer l'assistant

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

Explication de la configuration clé

Sélection du modèle :

  • gpt-4 : Meilleure qualité, latence plus élevée (~1,5 s), 0,03 $/1 000 tokens
  • gpt-3.5-turbo : Plus rapide (~0,8 s), moins cher, adapté aux agents simples
  • claude-3-sonnet : Excellent pour le raisonnement complexe

Sélection de la voix :

  • Les voix ElevenLabs sonnent le plus naturel
  • Les voix OpenAI sont moins chères mais plus robotiques
  • Testez plusieurs voix, cela compte plus que vous ne le pensez

Conseils pour le prompt système :

  • Soyez spécifique sur le ton et la longueur
  • Incluez des exemples de ce qu'il NE FAUT PAS dire
  • Ajoutez des garde-fous pour les cas limites
  • Restez sous 2 000 tokens

Étape 2 : Ajouter le function calling

Les fonctions permettent à votre IA d'interagir avec vos systèmes. Voici une fonction de capture 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 de l'agent vocal

Comment votre IA se connecte aux systèmes métier réels

Agent vocal
Fonction
Systèmes externes
CRM / Airtable
Calendrier
Email / SendGrid
Slack
Latence inférieure à 1 seconde

Enregistrer les fonctions avec l'assistant

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

Créer l'endpoint 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" });
}

Étape 3 : Connecter un numéro de téléphone

Acheter un numéro sur 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;
}

Créer le handler d'appels entrants

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

Utiliser le numéro de téléphone Vapi

Alternativement, achetez directement via Vapi :

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

Options de configuration du numéro de téléphone

Connectez votre agent vocal aux lignes téléphoniques

Apportez votre propre Twilio
1Achetez un numéro sur Twilio
2Configurez l'URL vocale vers Vapi
3Contrôle total sur le routage
~1 $/moisRecommandé
Numéros managés Vapi
1Achetez via le tableau de bord Vapi
2Zéro configuration nécessaire
3Inclus dans le tarif à la minute
Inclus dans le coût/minDémarrage rapide
Appelant - Téléphone - Agent vocal - Réponse

Étape 4 : Patterns de production

Gestion des erreurs

Les agents vocaux échouent. Préparez-vous :

// 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 et prévention d'abus

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

Optimisation des coûts

Les agents vocaux peuvent devenir chers rapidement. Voici comment je maintiens les coûts sous 200 $/mois pour plus de 200 appels :

StratégieÉconomieImplémentation
Utiliser gpt-3.5 pour les requêtes simples60 %Routage basé sur l'intention
Mettre en cache les réponses courantes30 %Redis pour les FAQ
Raccourcir les prompts20 %Rester sous 1 000 tokens
Utiliser les voix OpenAI50 %vs ElevenLabs
Regrouper les appels de fonction15 %Combiner les opérations
// Smart routing example
const model = detectSimpleQuery(transcript)
  ? "gpt-3.5-turbo" // $0.0015/1K tokens
  : "gpt-4";        // $0.03/1K tokens

Étape 5 : Tests et monitoring

Tests automatisés

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

Tableau de bord de monitoring

Suivez ces métriques :

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

Exemple concret : Résultats pour l'entreprise de plomberie

La configuration :

  • 1 numéro de téléphone (indicatif local)
  • GPT-4 pour les problèmes complexes, GPT-3.5 pour les simples
  • 3 fonctions : captureLead, scheduleAppointment, checkAvailability
  • Bascule vers un humain après 3 erreurs

Résultats après 3 mois :

  • 247 appels gérés
  • 94 % capturés (vs 60 % avant)
  • Durée moyenne d'appel : 2 min 15 s
  • Coût par appel : 0,12 $
  • 23 appels d'urgence hors horaires captés
  • Temps économisé pour le propriétaire : 15 heures/semaine

Ce qui a fonctionné :

  • Prompt système spécifique avec des exemples
  • Fonction de détection d'urgence
  • SMS de secours pour les appels échoués
  • Revue quotidienne des transcriptions les 2 premières semaines

Ce qui n'a pas fonctionné :

  • Initialement trop verbeux (corrigé avec l'instruction "soyez concis")
  • Ne capturait pas l'email (ajouté à la fonction)
  • Confondait les adresses (ajout d'une étape de confirmation)

Prochaines étapes

Maintenant que vous comprenez les bases :

  1. Construisez votre premier agent : Commencez simple, ajoutez des fonctions progressivement
  2. Testez avec de vrais appels : Faites appeler des amis/famille et demandez du feedback
  3. Surveillez et itérez : Revoyez les transcriptions quotidiennement au début
  4. Montez en charge progressivement : Ajoutez des fonctionnalités au fur et à mesure que vous comprenez les modes de défaillance

Dans le prochain article, je couvrirai les patterns avancés :

  • Support multilingue
  • Fine-tuning de LLM personnalisé
  • Intégration avec les systèmes CRM
  • Construire des agents vocaux qui sonnent vraiment humains

FAQ

Q : Combien coûte Vapi ? R : ~0,05-0,15 $ par minute selon la configuration. Un appel de 2 minutes coûte environ 0,20 $.

Q : Puis-je utiliser mon propre numéro de téléphone ? R : Oui, via l'intégration Twilio. Ou achetez directement via Vapi.

Q : Et si l'IA ne comprend pas ? R : Intégrez une logique de secours. Après 2 incompréhensions, proposez de transférer ou de prendre un message.

Q : Est-ce conforme HIPAA ? R : Vapi est certifié SOC 2. Pour HIPAA, vous aurez besoin d'un BAA et de garde-fous supplémentaires.

Q : Peut-elle gérer les accents ? R : Oui, mais testez avec votre base de clients spécifique. Deepgram gère bien la plupart des accents.


Besoin d'aide pour implémenter cela dans votre entreprise ? Réservez un appel gratuit de 30 minutes et je vous aiderai à concevoir votre agent vocal.

Navigation dans la série : ← Précédent : [Vue d'ensemble de l'architecture IA vocale] | Suivant : [Patterns avancés Vapi : fonctions et workflows] →

Share:

Recevez des perspectives d'ingénierie pratiques

Agents vocaux IA, workflows d'automatisation et livraison rapide. Pas de spam, désabonnement à tout moment.