Aller au contenu principal

Function calling vocal

Exécuter des fonctions depuis la voix

Le function calling vocal permet à votre agent de déclencher des actions concrètes pendant une conversation : consulter une base de données, passer une commande, envoyer un email ou interroger une API externe. L’agent décide quand appeler une fonction en fonction de ce que l’utilisateur dit.

1

L'agent identifie le besoin

L'utilisateur dit quelque chose qui nécessite un appel de fonction. L'agent génère les arguments.

2

Votre application exécute la fonction

Vous recevez les arguments via l'événement function_call_arguments.done et exécutez la logique métier.

3

Vous renvoyez le résultat

Envoyez conversation.item.create avec le type function_call_output et le call_id.

4

L'agent continue la conversation

Envoyez response.create pour que l'agent formule sa réponse vocale avec le résultat.

Déclarer une fonction

Les fonctions se déclarent dans le tableau tools de session.update :

{
  "type": "session.update",
  "session": {
    "tools": [
      {
        "type": "function",
        "name": "consulter_solde",
        "description": "Consulte le solde du compte bancaire d'un client",
        "parameters": {
          "type": "object",
          "properties": {
            "client_id": {
              "type": "string",
              "description": "Identifiant du client"
            }
          },
          "required": ["client_id"]
        }
      }
    ]
  }
}

Recevoir et traiter un appel de fonction

Quand l’agent décide d’appeler une fonction, vous recevez les arguments en streaming puis en bloc :

let functionArgs = "";

ws.on("message", (data) => {
  const event = JSON.parse(data);

  switch (event.type) {
    case "response.function_call_arguments.delta":
      functionArgs += event.delta;
      break;

    case "response.function_call_arguments.done":
      const args = JSON.parse(event.arguments);
      const callId = event.call_id;
      const functionName = event.name;

      // Exécuter la fonction
      handleFunctionCall(functionName, args, callId);
      break;
  }
});

async function handleFunctionCall(name, args, callId) {
  let result;

  switch (name) {
    case "consulter_solde":
      result = await getSolde(args.client_id);
      break;
    default:
      result = { error: "Fonction inconnue" };
  }

  // Renvoyer le résultat
  ws.send(JSON.stringify({
    type: "conversation.item.create",
    item: {
      type: "function_call_output",
      call_id: callId,
      output: JSON.stringify(result)
    }
  }));

  // Demander à l'agent de continuer
  ws.send(JSON.stringify({
    type: "response.create"
  }));
}

Appels de fonctions parallèles

L’agent peut décider d’appeler plusieurs fonctions simultanément. Dans ce cas, vous recevez plusieurs événements function_call_arguments.done. La règle est :

  1. Résoudre toutes les fonctions avant de répondre
  2. Soumettre tous les résultats avec autant de conversation.item.create
  3. Envoyer un seul response.create à la fin
const pendingCalls = new Map();
let expectedCalls = 0;

case "response.function_call_arguments.done":
  const result = await executeFunction(event.name, event.arguments);
  pendingCalls.set(event.call_id, result);

  if (pendingCalls.size === expectedCalls) {
    // Toutes les fonctions sont résolues
    for (const [callId, output] of pendingCalls) {
      ws.send(JSON.stringify({
        type: "conversation.item.create",
        item: {
          type: "function_call_output",
          call_id: callId,
          output: JSON.stringify(output)
        }
      }));
    }
    // Un seul response.create pour toutes les sorties
    ws.send(JSON.stringify({ type: "response.create" }));
    pendingCalls.clear();
  }
  break;

Bonnes pratiques

  • Descriptions claires : la qualité des descriptions de fonctions détermine quand l’agent les utilise
  • Exécution rapide : une fonction qui prend plus de 2-3 secondes crée un silence gênant
  • Gestion des erreurs : renvoyez un message d’erreur lisible plutôt qu’une exception technique
  • Confirmation vocale : pour les actions sensibles (paiement, suppression), faites confirmer par l’utilisateur avant d’exécuter

Points clés à retenir

  • Le function calling vocal suit un cycle en 4 étapes : détection, exécution, retour du résultat, continuation
  • Les fonctions se déclarent dans session.update avec un schéma JSON de paramètres
  • Le résultat doit être renvoyé via conversation.item.create avec type: "function_call_output"
  • Envoyez toujours response.create après avoir soumis les résultats
  • Pour les appels parallèles, attendez tous les résultats avant d’envoyer un seul response.create