Créer avec l’IA

Comment créer un agent vocal avec GPT-Realtime-2?

· Par Robert Scales · 5 min de lecture

Réponse courte

Concevez d’abord le déroulement de l’appel (accueil, ce que l’agent peut consulter, ce qu’il doit confirmer, quand il passe le relais à une personne), puis connectez-vous à la Realtime API d’OpenAI avec le modèle gpt-realtime-2, décrivez vos outils dans un événement session.update et répondez à chaque appel de fonction depuis votre propre code. Commencez avec l’effort de raisonnement faible par défaut et ne l’augmentez que pour les étapes qui échouent aux tests.

Un agent vocal est un programme auquel vous parlez à voix haute et qui peut aussi agir : consulter une commande, réserver une plage horaire, envoyer une confirmation. La Realtime API d’OpenAI permet à un seul modèle d’écouter la parole et de répondre directement à voix haute, sans étape de transcription distincte ni étape de synthèse vocale distincte. Le 7 mai 2026, OpenAI a ajouté GPT-Realtime-2 à cette API et l’a décrit comme son premier modèle vocal doté d’un « raisonnement de la classe de GPT‑5 ». Concrètement, il peut réfléchir un peu avant de parler et appeler des outils de façon plus fiable que les modèles en temps réel précédents.

Ce qui rend un agent vocal agréable ou exaspérant, c’est la conception autour du modèle : les actions qu’il a le droit de faire, ce qu’il doit d’abord relire à voix haute, et ce qui se passe quand l’appelant l’interrompt ou qu’un outil échoue.

Ce que GPT-Realtime-2 change pour les développeurs

L’annonce d’OpenAI énumère plusieurs fonctions qui comptent quand vous planifiez un appel :

FonctionCe que cela signifie pour votre conception
Effort de raisonnement : minimal, low, medium, high, xhigh (low par défaut)Plus d’effort donne de meilleures réponses aux demandes difficiles, mais des réponses plus lentes. Gardez-le faible pour les consultations simples.
PréambulesDe courtes phrases parlées, comme « un instant, je vérifie », pendant que le modèle travaille, pour que l’appelant n’entende pas de silence.
Appels d’outils en parallèleLe modèle peut demander à votre code d’exécuter plusieurs fonctions à la fois, par exemple vérifier deux dates.
Contexte de 128 000 jetons (contre 32 000 auparavant)Les appels plus longs conservent une plus grande part de ce qui a été dit. Un jeton est un petit morceau de texte ou d’audio, l’unité que l’API compte et facture.
Tarifs32 $ US par million de jetons audio en entrée et 64 $ US par million de jetons audio en sortie.

Les politiques d’utilisation d’OpenAI exigent aussi que les gens sachent qu’ils parlent à une IA, à moins que ce ne soit déjà évident : votre accueil devrait donc le dire.

Étape 1 : concevoir le déroulement de l’appel sur papier

Prenons une petite boulangerie qui veut un agent téléphonique pour les précommandes de gâteaux. Avant d’écrire du code, écrivez le déroulement :

  1. Accueillir et dire qu’il s’agit d’un assistant automatisé.
  2. Recueillir le type de gâteau, la taille, la date de cueillette et le nom de l’appelant.
  3. Vérifier la disponibilité avec un outil : check_pickup_slot(date).
  4. Relire chaque détail à voix haute et attendre un « oui » clair.
  5. Agir avec un deuxième outil : place_preorder(...).
  6. Passer le relais au personnel pour les allergies, les gâteaux de mariage ou tout ce dont l’agent n’est pas sûr.

La règle de l’étape 4 est la plus importante. Relire les noms, les dates et les nombres avant toute action qui modifie quelque chose, c’est ce qui empêche un « seize » mal entendu de devenir un « treize ».

Étape 2 : se connecter et configurer la session

Pour un programme serveur, la documentation d’OpenAI recommande un WebSocket, une connexion qui reste ouverte pour que les deux côtés puissent envoyer des messages à tout moment. (Pour les applications de navigateur et mobiles, elle recommande plutôt WebRTC.) Chaque message est un événement JSON. Voici un serveur Node.js minimal qui utilise le paquet ws, avec les deux outils de la boulangerie :

import WebSocket from "ws";

const ws = new WebSocket("wss://api.openai.com/v1/realtime?model=gpt-realtime-2", {
  headers: { Authorization: "Bearer " + process.env.OPENAI_API_KEY },
});

ws.on("open", () => {
  ws.send(JSON.stringify({
    type: "session.update",
    session: {
      type: "realtime",
      model: "gpt-realtime-2",
      output_modalities: ["audio"],
      audio: {
        input: { format: { type: "audio/pcm", rate: 24000 }, turn_detection: { type: "semantic_vad" } },
        output: { voice: "marin" },
      },
      instructions: "Tu es l’assistant automatisé de précommandes d’une boulangerie. Dis que tu es une IA dès le début. " +
        "Recueille le type de gâteau, la taille, la date de cueillette et le nom. Avant d’appeler place_preorder, relis chaque détail " +
        "et attends un oui clair. Pour les allergies ou les gâteaux de mariage, propose de transférer l’appel au personnel.",
      tools: [
        { type: "function", name: "check_pickup_slot", description: "Vérifie s’il reste de la place à une date de cueillette.",
          parameters: { type: "object", properties: { date: { type: "string" } }, required: ["date"] } },
        { type: "function", name: "place_preorder", description: "Enregistre une précommande confirmée.",
          parameters: { type: "object", properties: {
            cake: { type: "string" }, size: { type: "string" }, date: { type: "string" }, name: { type: "string" } },
            required: ["cake", "size", "date", "name"] } },
      ],
      tool_choice: "auto",
    },
  }));
});

semantic_vad est le réglage de détection d’activité vocale (voice activity detection) : l’API décide quand l’appelant a fini de parler et quand répondre. L’audio circule en morceaux encodés en Base64 dans des événements input_audio_buffer.append (vers le modèle) et response.output_audio.delta (en provenance du modèle).

Étape 3 : répondre aux appels d’outils depuis votre code

Le modèle ne touche jamais à votre base de données. Quand il veut un outil, l’événement response.done contient un élément de type function_call avec un nom, ses arguments sous forme de chaîne JSON et un call_id. Votre code exécute la fonction, renvoie le résultat avec le même call_id, puis demande au modèle de continuer :

ws.on("message", async (raw) => {
  const event = JSON.parse(raw.toString());
  if (event.type === "response.done") {
    for (const item of event.response.output) {
      if (item.type !== "function_call") continue;
      const args = JSON.parse(item.arguments);
      const result = await runTool(item.name, args);   // votre propre code : agenda, système de commandes
      ws.send(JSON.stringify({ type: "conversation.item.create",
        item: { type: "function_call_output", call_id: item.call_id, output: JSON.stringify(result) } }));
    }
    if (event.response.output.some(i => i.type === "function_call")) {
      ws.send(JSON.stringify({ type: "response.create" }));
    }
  }
});

À essayer : ouvrez le Playground d’OpenAI, choisissez GPT-Realtime-2, collez les consignes de la boulangerie ci-dessus et commandez un gâteau à voix haute. À mi-chemin, changez votre date de cueillette. Notez si l’agent relit la nouvelle date avant de passer la commande, et s’il reconnaît être une IA dans son accueil.

Comment gérer les interruptions et les erreurs?

Les appelants interrompent, et un bon agent cesse de parler quand ils le font. Avec la détection d’activité vocale activée, l’API remarque que l’appelant parle (un événement input_audio_buffer.speech_started) et annule sa propre réponse. Par WebSocket, toutefois, c’est votre programme qui fait jouer l’audio : il a donc deux tâches. Arrêter la lecture tout de suite, et envoyer un événement conversation.item.truncate avec l’identifiant de la dernière réponse du modèle et le nombre de millisecondes réellement jouées. Cela retire de la conversation la partie qui n’a pas été entendue, pour que le modèle ne suppose pas que l’appelant a entendu une phrase qui a été coupée. Avec WebRTC ou une connexion téléphonique (SIP), le serveur suit la lecture et coupe automatiquement.

Pour les erreurs, le serveur envoie un événement error. Si vous ajoutez votre propre event_id à chaque événement que vous envoyez, l’erreur portera le même identifiant, et vous saurez quelle requête a échoué. Les échecs d’outils sont différents : ils relèvent de votre code, et la meilleure solution est de renvoyer un résultat clair, comme {"ok": false, "reason": "calendar unavailable"}, plutôt que rien du tout. Le modèle peut alors dire qu’il éprouve des difficultés et offrir de passer le relais au personnel; OpenAI compte une meilleure récupération parmi les améliorations de GPT-Realtime-2. Consignez chaque appel d’outil, n’oubliez pas que les sessions prennent fin après 60 minutes, et testez les cas délicats : une date marmonnée, un changement d’idée, un outil qui ne répond pas à temps.

Sources

  1. Advancing voice intelligence with new models in the API — OpenAI, 7 mai 2026
  2. Realtime conversations (Managing conversations) — OpenAI, 19 mai 2026
  3. Realtime API with WebSocket — OpenAI, 15 mai 2026

Recevez gratuitement le Guide de l’intelligence artificielle

Abonnez-vous à l’infolettre hebdomadaire et recevez le guide gratuit : ce qui a changé en IA cette semaine, une leçon, un prompt à essayer. Désabonnement en un clic.

Ce que nous faisons de votre adresse

Retour en haut

Affichage

Vos choix sont enregistrés dans ce navigateur seulement. Aucune donnée n’est transmise.

Taille du texte
100 %
Couleurs
Lecture
Autres réglages
Déclaration d’accessibilité