À proposExpertiseProjetsParcoursBlogContact
Discuter
À proposExpertiseProjetsParcoursBlogContactDiscuter

Yao David Logan

Software Engineer fullstack spécialisé en SaaS, automatisation métier et plateformes web/mobile scalables.

NavigationExpertiseProjetsParcoursBlogContact
LiensGitHubLinkedInEmail
© 2026 Yao David Logan. Tous droits réservés.
Agents LLM autonomes au téléphone — REX Vapi + SIP + GPT-4 en production
Retour au blog

Tech

Xin@

Agents LLM autonomes au téléphone — REX Vapi + SIP + GPT-4 en production

YDLYao David Logan17 min de lecture18 septembre 2026

CatégorieTech

Lecture17 min de lecture

Publié18 septembre 2026

Vues0

Partages0

Commentaires0

Sommaire
  1. 011. Le contexte
  2. 022. Pourquoi c'est tentant et piégeur
  3. 033. Architecture cible
  4. 044. Pattern 1 — Streaming partout
  5. 055. Pattern 2 — Le system prompt comme une checklist
  6. 066. Pattern 3 — Détection de barge-in
  7. 077. Pattern 4 — Function calling pour les actions réelles
  8. 088. Pattern 5 — Conformité dès le bonjour
  9. 099. Pattern 6 — Handover humain
  10. 1010. Mesures et qualité
  11. 1111. Pièges à éviter
  12. 1212. Économie
  13. 1313. Conclusion

Streaming partout, function calling pour la vérité, barge-in, opt-out conforme, handover humain : les six patterns qui transforment un agent vocal LLM en outil de production.

Brancher un agent LLM sur une ligne téléphonique via Vapi + SIP (IllyVoIP, Vonage), c'est techniquement séduisant. En production, c'est un terrain miné. Retour d'expérience.

1. Le contexte

Sur une mission d'agence, le client voulait automatiser ses appels sortants de qualification (B2B, prise de rendez-vous, relance). Cahier des charges : agent vocal naturel, intégration au CRM, opérateurs humains qui prennent le relais sur demande, conformité légale (consentement, opt-out).

Le stack final : Vapi pour l'orchestration vocale + SIP (IllyVoIP en backup, Vonage en principal) pour la connectivité PSTN, OpenAI GPT-4 pour la logique conversationnelle, N8N pour le pipeline CRM, PostgreSQL pour les logs.

L'objectif de cet article : partager ce qui a marché, ce qui a explosé en vol, et comment je relancerais aujourd'hui.

2. Pourquoi c'est tentant et piégeur

L'agent vocal LLM coche toutes les cases du buzz : automatisation, IA générative, scale, ROI marketing. Mais sous le capot, c'est l'intégration de cinq systèmes asynchrones qui dialoguent en temps réel :

  • Le LLM (OpenAI/Anthropic) : latence 800-2000 ms, parfois plus
  • Le TTS (Vapi/ElevenLabs) : latence 200-500 ms par phrase
  • Le STT (Deepgram/Whisper) : latence 100-300 ms streaming
  • Le SIP (IllyVoIP/Vonage) : latence 50-150 ms par paquet RTP
  • Le CRM (HubSpot/Pipedrive) : latence 200-1000 ms

À 3 secondes de latence cumulée, l'agent paraît "lent et perdu". À 1.2 seconde, "robot mais OK". Sous 800 ms, "presque humain". L'optimisation de latence est le projet, pas un détail.

3. Architecture cible

Plain Text
1[Utilisateur] ← PSTN/SIP → [IllyVoIP / Vonage]
2 │
3 ▼
4 [Vapi]
5 ╱ │ ╲
6 [Deepgram] │ [ElevenLabs]
7 STT │ TTS
8 ▼
9 [Agent API]
10 Node.js
11 │
12 ┌──────────┼──────────┐
13 ▼ ▼ ▼
14 [OpenAI] [Postgres] [N8N]
15 reasoning logs CRM

Vapi orchestre la boucle audio (STT → agent → TTS) avec un streaming bidirectionnel. L'Agent API (mon code) reçoit le texte transcrit, appelle OpenAI, retourne la réponse à parler. Postgres trace tout. N8N intègre avec le CRM.

4. Pattern 1 — Streaming partout

La règle absolue : jamais attendre la fin d'une étape pour commencer la suivante.

TypeScript
1// src/agent/handleTurn.ts
2export async function handleTurn(userText: string, context: TurnContext) {
3 // 1. Stream OpenAI dès que disponible
4 const stream = await openai.chat.completions.create({
5 model: "gpt-4o",
6 messages: [...context.history, { role: "user", content: userText }],
7 stream: true,
8 temperature: 0.4,
9 });
10 
11 let buffer = "";
12 for await (const chunk of stream) {
13 const delta = chunk.choices[0]?.delta?.content ?? "";
14 buffer += delta;
15 
16 // 2. Émettre par phrase (split sur la ponctuation forte)
17 const sentenceEnd = buffer.search(/[.!?]\s/);
18 if (sentenceEnd > 0) {
19 const sentence = buffer.slice(0, sentenceEnd + 1);
20 buffer = buffer.slice(sentenceEnd + 2);
21 
22 // 3. Pousser à TTS sans attendre la fin du stream LLM
23 await vapi.speak(sentence);
24 }
25 }
26 
27 // 4. Flush le reste
28 if (buffer.trim()) await vapi.speak(buffer);
29}

Bénéfice mesuré : latence perçue divisée par 3. Au lieu d'attendre 2 secondes de génération puis 1 seconde de TTS, l'utilisateur entend la première phrase au bout de 700 ms.

5. Pattern 2 — Le system prompt comme une checklist

Un agent vocal n'est pas un chatbot textuel. Trois exigences spécifiques :

  1. Phrases courtes — pas de listes à puces (impossible à dire), pas de paragraphes longs
  2. Une question par tour — sinon l'utilisateur en oublie
  3. Confirmation explicite — l'utilisateur ne voit pas le texte, il faut répéter les infos critiques
Plain Text
1Tu es Sarah, assistante commerciale chez Acme Corp.
2 
3Règles obligatoires :
4- Phrases courtes (max 15 mots)
5- Une question par tour, jamais plus
6- Confirme à voix haute les noms, emails, dates et numéros
7- Si tu n'as pas compris, dis "je n'ai pas bien entendu, pouvez-vous répéter ?"
8- N'invente jamais une information
9 
10Objectif de l'appel :
11- Qualifier le prospect (budget, besoin, échéance)
12- Proposer un rendez-vous dans la semaine prochaine
13- Récupérer email et meilleur créneau
14 
15Si le prospect refuse : remercie poliment et propose un opt-out définitif.

L'ordre des règles compte. Les modèles GPT-4 et Claude appliquent mieux les contraintes formulées en premier.

6. Pattern 3 — Détection de barge-in

L'utilisateur va interrompre l'agent. C'est normal et c'est sain. L'agent doit s'arrêter immédiatement, pas continuer à parler pendant 3 secondes par-dessus l'utilisateur.

Vapi expose un événement barge-in quand le STT détecte que l'utilisateur commence à parler. Côté agent :

TypeScript
1vapi.on("barge-in", () => {
2 // 1. Couper le TTS immédiatement
3 vapi.stopSpeaking();
4 
5 // 2. Marquer le tour LLM en cours comme abandonné
6 currentTurn?.abort();
7 
8 // 3. Reprendre l'écoute
9 vapi.resumeListening();
10});

Sans ça, l'agent paraît "sourd" et l'expérience devient frustrante. C'est le détail qui fait passer "robot bizarre" à "agent acceptable".

7. Pattern 4 — Function calling pour les actions réelles

L'agent ne doit JAMAIS s'inventer un numéro de téléphone, un email ou une disponibilité. Tout ce qui touche au monde réel passe par function calling structuré.

TypeScript
1const tools = [
2 {
3 type: "function",
4 function: {
5 name: "checkAvailability",
6 description: "Vérifie les créneaux disponibles dans le calendrier",
7 parameters: {
8 type: "object",
9 properties: {
10 startDate: { type: "string", format: "date" },
11 endDate: { type: "string", format: "date" },
12 durationMin: { type: "number" },
13 },
14 required: ["startDate", "endDate", "durationMin"],
15 },
16 },
17 },
18 {
19 type: "function",
20 function: {
21 name: "bookAppointment",
22 description: "Réserve un rendez-vous (à n'appeler qu'après confirmation utilisateur)",
23 parameters: {
24 type: "object",
25 properties: {
26 email: { type: "string", format: "email" },
27 name: { type: "string" },
28 slotIso: { type: "string", format: "date-time" },
29 },
30 required: ["email", "name", "slotIso"],
31 },
32 },
33 },
34];

Quand GPT-4 décide d'appeler checkAvailability, mon code consulte vraiment le Google Calendar du commercial, retourne les créneaux, et GPT-4 formule la réponse. Pas de hallucination possible.

Important : bookAppointment n'est appelable qu'après confirmation explicite ("Je confirme votre RDV mardi 14h, c'est bien ça ?" → "oui"). Le system prompt impose cette discipline.

8. Pattern 5 — Conformité dès le bonjour

Trois exigences légales en France/UE pour l'appel sortant automatisé :

  1. Information : "Cet appel peut être enregistré et traité par un système automatisé"
  2. Consentement Bloctel/RGPD : vérifier que le numéro n'est pas sur liste rouge avant d'appeler
  3. Opt-out explicite : à la demande "ne m'appelez plus", l'opt-out est instantané et journalisé
TypeScript
1// src/agent/optOut.ts
2const OPT_OUT_PHRASES = [
3 "ne m'appelez plus",
4 "ne plus me contacter",
5 "supprimez-moi",
6 "rgpd",
7 "opt out",
8];
9 
10export function detectOptOut(userText: string): boolean {
11 const normalized = userText.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
12 return OPT_OUT_PHRASES.some((phrase) => normalized.includes(phrase));
13}
14 
15// dans la boucle conversationnelle
16if (detectOptOut(userText)) {
17 await vapi.speak("Très bien, je note votre demande. Vous ne recevrez plus d'appels de notre part. Bonne journée.");
18 await OptOut.create({ phone: context.phone, reason: "user_request", at: new Date() });
19 await vapi.endCall();
20 return;
21}

L'opt-out est non négociable. Pas de "êtes-vous sûr ?", pas de "puis-je vous proposer autre chose ?". On ferme, on log, on respecte.

9. Pattern 6 — Handover humain

Aucun agent LLM ne remplace un humain pour les cas sensibles. Détecter quand transférer :

  • Demande explicite ("je veux parler à un humain")
  • Conversation qui patine (3 incompréhensions de suite)
  • Sujet hors périmètre (réclamation, litige, urgence)
  • Émotion négative détectée (sentiment analysis sur le texte transcrit)
TypeScript
1async function transferToHuman(reason: string, context: TurnContext) {
2 await vapi.speak("Je vais vous mettre en contact avec un conseiller, ne quittez pas.");
3 await Transfer.create({ callId: context.callId, reason, at: new Date() });
4 await vapi.transferCall({ destination: HUMAN_QUEUE_NUMBER });
5}

L'agent doit savoir "je ne sais pas faire ça" sans honte, et passer la main rapidement.

10. Mesures et qualité

Tracer chaque appel sur trois plans :

MétriqueDéfinitionSeuil acceptable
Latence p95 par tourTemps user-parle-fini → agent-commence-à-parler< 1200 ms
Taux de barge-in% d'appels avec ≥1 interruptionStable autour de 20-30 %
Taux d'opt-out% d'appels finissant par opt-out< 5 %
Taux de handover% d'appels transférés à un humain< 15 %
Taux de complétion% d'appels atteignant l'objectif (RDV pris, qualif faite)> 30 %

Si la latence dérive, l'expérience explose en deux jours. Surveiller en continu.

11. Pièges à éviter

PiègeSymptômeCorrection
TTS sans streamingLatence perçue insupportableStreaming phrase par phrase
Pas de barge-inAgent parle par-dessusListener barge-in + stopSpeaking
Hallucination sur dates/emailsMauvais RDV pris, email fauxFunction calling pour tout fait réel
Opt-out flouRisque légalDétection lexicale + journal + fin d'appel
Pas de handoverFrustration garantieDétection multi-signaux + transfert
System prompt trop longModèle hallucine plusMaximum 800 tokens, règles ordonnées
Pas de BloctelRisque légalVérification systématique avant chaque appel

12. Économie

Coût mesuré par appel (qualif B2B, durée moyenne 3 min) :

  • Vapi (orchestration) : ~0,15 €
  • IllyVoIP/Vonage (SIP) : ~0,02 €
  • OpenAI GPT-4o : ~0,05 €
  • ElevenLabs TTS : ~0,10 €
  • Deepgram STT : ~0,02 €
  • Total : ~0,34 € par appel

Vs un commercial humain : ~3 à 5 € par appel (salaire chargé + frais). L'économie est réelle, mais elle suppose un volume d'appels conséquent — sous 200 appels/jour, l'humain reste meilleur en qualité de relation.

13. Conclusion

L'agent vocal LLM n'est pas un gadget. C'est un outil professionnel quand on respecte trois principes : streaming partout, function calling pour la vérité, conformité légale par défaut. Sans ces trois, c'est un démo qui ne tient pas en production.

L'agent n'est pas non plus un remplaçant universel du commercial humain. Il excelle sur la qualification massive et standardisée. Il échoue sur la nuance, la négociation et l'émotion. Hybride humain + agent reste le meilleur calcul économique.

Si vous démarrez : Vapi + GPT-4o + Deepgram + ElevenLabs est la stack qui a le mieux marché pour moi en 2026. Mais comptez 6 à 10 semaines pour livrer un agent réellement utilisable en production, pas le sprint week-end vendu sur LinkedIn.

Commentaires

Réactions des lecteurs

Aucun commentaire pour l'instant

Aucun spam — l'email sert uniquement à vérifier votre identité.

·

Soyez le premier à réagir à cet article.

←PrécédentClean code et dette technique — REX neuf mois de formation fullstackRetour d'experience · 15 min de lectureSuivantNext.js 14 App Router en production — leçons après 6 mois sur NexusRetour d'experience · 16 min de lecture→
Prochain échange

Transformer cette lecture en décision produit.

Si ce sujet ressemble à un problème réel dans votre produit, je peux intervenir sur le diagnostic, l'architecture, le backend, l'interface et les automatisations qui rendent une plateforme exploitable.

Format
CDI, freelance, mission longue
Focus
SaaS, API, back-office, automatisation
Discuter du sujetTélécharger le CV

Newsletter

Recevoir les prochaines notes techniques.

Une sélection courte sur SaaS, architecture backend, automatisation métier et qualité produit. Pas de bruit, seulement des idées applicables.