For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
Navigation principale

Utilisation d’outils avec Realtime

Permettez aux agents vocaux en temps réel d’appeler des outils de type fonction et des serveurs MCP distants.

Vous pouvez associer des outils à une session Realtime pour permettre au modèle de consulter des données, d’effectuer des actions ou d’appeler des services pendant une conversation en direct. La configuration des outils repose sur la même interface événementielle, que votre client utilise un canal de données WebRTC ou une connexion WebSocket.

Utilisez des outils de type fonction lorsque votre application doit exécuter l’outil et renvoyer le résultat. Utilisez des outils MCP lorsque Realtime API doit se connecter à un serveur d’outils distant pour vous.

Choisissez un type d’outil

Type d’outilCas d’utilisationQui l’exécute
functionVotre application gère la logique métier, les vérifications d’approbation ou l’accès aux systèmes privés.Votre client ou serveur reçoit un appel de fonction et renvoie function_call_output.
mcp avec server_urlVous souhaitez que le modèle appelle des outils exposés par un serveur MCP distant.Realtime API appelle le serveur MCP distant.
mcp avec connector_idVous utilisez un ancien connecteur intégré avec un modèle existant.Realtime API appelle le connecteur avec l’autorisation que vous fournissez.

Ajoutez des outils à l’un des deux niveaux suivants :

  • Au niveau de la session , avec session.tools dans session.update, si vous souhaitez que l’outil soit disponible pendant toute la session.
  • Au niveau de la réponse , avec response.tools dans response.create, si vous n’avez besoin de l’outil que pour un seul tour.

Configurez un outil de type fonction

Les outils de type fonction sont le choix à privilégier lorsque l’outil doit s’exécuter dans votre application. Le modèle émet les arguments de l’appel de fonction, votre code exécute l’action, puis renvoie le résultat dans un élément function_call_output.

Configurez un outil de type fonction avec session.update
const event = {
  type: "session.update",
  session: {
    type: "realtime",
    model: "gpt-realtime-2.1",
    tools: [
      {
        type: "function",
        name: "lookup_order",
        description: "Look up an order by its order number.",
        parameters: {
          type: "object",
          properties: {
            order_number: {
              type: "string",
              description: "The customer-facing order number.",
            },
          },
          required: ["order_number"],
        },
      },
    ],
    tool_choice: "auto",
  },
};

ws.send(JSON.stringify(event));

Lorsque le modèle appelle la fonction, écoutez l’arrivée de l’élément d’appel de fonction, exécutez la logique de votre application, puis renvoyez le résultat :

Envoyez le résultat de l’appel de fonction
const event = {
  type: "conversation.item.create",
  item: {
    type: "function_call_output",
    call_id: functionCall.call_id,
    output: JSON.stringify({
      status: "shipped",
      delivery_date: "2026-05-09",
    }),
  },
};

ws.send(JSON.stringify(event));
ws.send(JSON.stringify({ type: "response.create" }));

Pour une présentation complète de l’appel de fonction, événement par événement, consultez Gestion des conversations.

Configurez un outil MCP

Les outils MCP sont utiles lorsque l’outil est déjà accessible via un serveur MCP distant, ou lorsqu’un modèle existant utilise un ancien connecteur intégré. Contrairement aux outils de type fonction, les outils MCP sont exécutés par Realtime API elle-même.

Dans Realtime, un outil MCP a la structure suivante :

  • type: "mcp"
  • server_label
  • L’un des deux champs : server_url ou connector_id
  • authorization et headers facultatifs
  • allowed_tools facultatif
  • require_approval facultatif
  • server_description facultatif

Cet exemple rend un serveur MCP de documentation disponible pendant toute la session :

Configurez un outil MCP avec session.update
const event = {
  type: "session.update",
  session: {
    type: "realtime",
    model: "gpt-realtime-2.1",
    output_modalities: ["text"],
    tools: [
      {
        type: "mcp",
        server_label: "openai_docs",
        server_url: "https://developers.openai.com/mcp",
        allowed_tools: ["search_openai_docs", "fetch_openai_doc"],
        require_approval: "never",
      },
    ],
  },
};

ws.send(JSON.stringify(event));

Anciens connecteurs

connector_id est déprécié pour les modèles publiés après le 1er septembre 2026. Utilisez server_url pour vous connecter à un serveur MCP distant, ou tunnel_id pour vous connecter à un serveur MCP local via le Tunnel MCP sécurisé. Les modèles existants continuent de prendre en charge les connecteurs. L’exemple ci-dessous utilise gpt-realtime-1.5, publié avant cette date limite.

Les connecteurs intégrés utilisent la même structure d’outil MCP, mais transmettent connector_id à la place de server_url. Par exemple, Google Calendar utilise connector_googlecalendar. Dans Realtime, utilisez ces connecteurs intégrés pour des opérations de lecture, telles que la recherche ou la lecture d’événements ou d’e-mails. Transmettez le token d’accès OAuth de l’utilisateur dans authorization et limitez les outils accessibles avec allowed_tools lorsque c’est possible :

Configurez un connecteur Google Calendar
const event = {
  type: "session.update",
  session: {
    type: "realtime",
    model: "gpt-realtime-1.5",
    output_modalities: ["text"],
    tools: [
      {
        type: "mcp",
        server_label: "google_calendar",
        connector_id: "connector_googlecalendar",
        authorization: "<google-oauth-access-token>",
        allowed_tools: ["search_events", "read_event"],
        require_approval: "never",
      },
    ],
  },
};

ws.send(JSON.stringify(event));

Les serveurs MCP distants ne reçoivent pas automatiquement tout le contexte de la conversation, mais ils peuvent voir toutes les données que le modèle transmet dans un appel d’outil. Limitez les outils accessibles avec allowed_tools, et exigez une approbation pour toute action que vous n’exécuteriez pas automatiquement.

Déroulement des appels MCP dans Realtime

Contrairement aux outils function de Realtime, les outils MCP distants sont exécutés directement par Realtime API. Votre client n’exécute pas l’outil distant et ne renvoie pas de function_call_output. Il configure l’accès, écoute les événements du cycle de vie MCP et envoie, le cas échéant, une réponse d’approbation si le serveur en demande une.

Voici un déroulement typique :

  1. Vous envoyez session.update ou response.create avec une entrée dans tools dont le champ type vaut mcp.
  2. Le serveur commence à importer les outils et émet mcp_list_tools.in_progress.
  3. Tant que la récupération de la liste est en cours, le modèle ne peut pas appeler un outil qui n’a pas encore été chargé. Si vous souhaitez attendre avant de démarrer un tour qui dépend de ces outils, écoutez l’événement mcp_list_tools.completed. L’événement conversation.item.done dont le champ item.type vaut mcp_list_tools indique les noms des outils effectivement importés. Si l’importation échoue, vous recevez mcp_list_tools.failed.
  4. L’utilisateur parle ou envoie du texte, et une réponse est créée, soit par votre client, soit automatiquement selon la configuration de la session.
  5. Si le modèle choisit un outil MCP, vous recevez response.mcp_call_arguments.delta et response.mcp_call_arguments.done.
  6. Si une approbation est requise, le serveur ajoute un élément à la conversation dont le champ item.type vaut mcp_approval_request. Votre client doit y répondre avec un élément mcp_approval_response.
  7. Lorsque l’outil s’exécute, vous recevez response.mcp_call.in_progress. En cas de réussite, vous recevez ensuite un événement response.output_item.done dont le champ item.type vaut mcp_call ; en cas d’échec, vous recevez response.mcp_call.failed.
  8. L’événement response.done d’une réponse peut arriver avant la fin de ses appels MCP. Une fois la réponse terminée et tous ses appels MCP achevés, envoyez un nouvel événement response.create pour permettre au modèle d’utiliser les résultats et de poursuivre la conversation. Répétez cette étape si le modèle effectue d’autres appels MCP. Realtime API ne crée pas automatiquement ces réponses de suivi.

Ce gestionnaire d’événements journalise les principaux événements du cycle de vie MCP ; il ne gère pas les réponses de suivi :

Écoutez les événements MCP pendant une session Realtime
function parseRealtimeEvent(rawMessage) {
  if (typeof rawMessage === "string") {
    return JSON.parse(rawMessage);
  }

  if (typeof rawMessage?.data === "string") {
    return JSON.parse(rawMessage.data);
  }

  return JSON.parse(rawMessage.toString());
}

function getOutputText(item) {
  if (item.type !== "message") return "";

  return (item.content ?? [])
    .filter((part) => part.type === "output_text")
    .map((part) => part.text)
    .join("");
}

ws.on("message", (rawMessage) => {
  const event = parseRealtimeEvent(rawMessage);

  switch (event.type) {
    case "mcp_list_tools.in_progress":
      console.log("Listing MCP tools for item:", event.item_id);
      break;

    case "mcp_list_tools.completed":
      console.log("MCP tool listing complete for item:", event.item_id);
      break;

    case "mcp_list_tools.failed":
      console.error("MCP tool listing failed for item:", event.item_id);
      break;

    case "conversation.item.done":
      if (event.item.type === "mcp_list_tools") {
        const names = event.item.tools.map((tool) => tool.name).join(", ");
        console.log(`MCP tools ready on ${event.item.server_label}: ${names}`);
      }

      if (event.item.type === "mcp_approval_request") {
        console.log(
          "Approval required for:",
          event.item.name,
          event.item.arguments
        );
      }
      break;

    case "response.mcp_call_arguments.done":
      console.log("Final MCP call arguments:", event.arguments);
      break;

    case "response.mcp_call.in_progress":
      console.log("Running MCP tool for item:", event.item_id);
      break;

    case "response.mcp_call.failed":
      console.error("MCP tool call failed for item:", event.item_id);
      break;

    case "response.output_item.done":
      if (event.item.type === "mcp_call") {
        console.log(
          `MCP output from ${event.item.server_label}.${event.item.name}:`,
          event.item.output
        );
      }

      if (event.item.type === "message") {
        console.log("Assistant:", getOutputText(event.item));
      }
      break;

    case "response.done":
      console.log("Realtime turn complete.");
      break;
  }
});

Échecs courants

  • mcp_list_tools.failed : Realtime API n’a pas pu importer les outils du serveur distant ou du connecteur. Vérifiez server_url ou connector_id, l’authentification, la connectivité du serveur et les noms éventuellement spécifiés dans allowed_tools.
  • response.mcp_call.failed : le modèle a sélectionné un outil, mais l’appel à cet outil n’a pas abouti. Examinez les données de l’événement et l’élément mcp_call reçu ensuite pour détecter d’éventuelles erreurs de protocole MCP, d’exécution ou de transport.
  • mcp_approval_request sans mcp_approval_response correspondant : l’appel à l’outil ne peut pas se poursuivre tant que votre client ne l’a pas explicitement approuvé ou rejeté.
  • Un tour commence alors que mcp_list_tools.in_progress est encore actif : seuls les outils dont le chargement est déjà terminé peuvent être utilisés pendant ce tour.
  • Une réponse utilise tool_choice: "required", mais aucun outil n’est disponible pour le moment : le modèle n’a aucun outil à appeler. Attendez mcp_list_tools.completed, vérifiez qu’au moins un outil a été importé ou utilisez une autre valeur de tool_choice pour les tours qui ne nécessitent pas d’outil.
  • La validation de la définition d’un outil MCP échoue avant le début de l’importation. Les causes fréquentes sont les suivantes : un server_label en double dans le même tableau tools, la présence simultanée de server_url et de connector_id, l’absence de ces deux paramètres dans la requête initiale de création de session, une valeur connector_id non valide ou l’envoi simultané de authorization et de headers.Authorization. Pour les connecteurs, n’envoyez jamais headers.Authorization.

Approuvez ou rejetez les appels aux outils MCP

Si un outil nécessite une approbation, la Realtime API insère un élément mcp_approval_request dans la conversation. Pour continuer, envoyez un nouvel événement conversation.item.create dont le champ item.type vaut mcp_approval_response.

Approuvez une demande MCP
function approveMcpRequest(approvalRequestId) {
  const event = {
    type: "conversation.item.create",
    item: {
      id: `mcp_approval_${approvalRequestId}`,
      type: "mcp_approval_response",
      approval_request_id: approvalRequestId,
      approve: true,
    },
  };

  ws.send(JSON.stringify(event));
}

Si vous rejetez la demande, définissez approve sur false et, si vous le souhaitez, indiquez un motif dans reason.

Utilisez MCP pour une seule réponse

Si MCP doit être disponible pour un seul tour, ajoutez le même objet d’outil MCP à response.tools au lieu de session.tools :

Ajoutez des outils MCP à une seule réponse
const event = {
  type: "response.create",
  response: {
    output_modalities: ["text"],
    input: [
      {
        type: "message",
        role: "user",
        content: [
          {
            type: "input_text",
            text: "Which transport should I use for browser clients in the Realtime API?",
          },
        ],
      },
    ],
    tools: [
      {
        type: "mcp",
        server_label: "openai_docs",
        server_url: "https://developers.openai.com/mcp",
        allowed_tools: ["search_openai_docs", "fetch_openai_doc"],
        require_approval: "never",
      },
    ],
  },
};

ws.send(JSON.stringify(event));

Cette approche est utile lorsqu’une seule réponse nécessite un contexte externe ou lorsque différents tours doivent utiliser différents serveurs MCP.

Réutilisez un libellé de serveur déjà défini

server_label est l’identifiant stable d’une définition d’outil dans la session Realtime en cours. Une fois que vous avez défini un serveur ou un connecteur avec server_label et server_url ou connector_id, les événements session.update ou response.create suivants peuvent simplement faire référence à ce même server_label. La Realtime API réutilise alors la définition précédente, sans que vous ayez à renvoyer l’objet d’outil complet.

Réutilisez un connecteur déjà défini
const event = {
  type: "response.create",
  response: {
    output_modalities: ["text"],
    input: [
      {
        type: "message",
        role: "user",
        content: [
          {
            type: "input_text",
            text: "Check my schedule for this afternoon.",
          },
        ],
      },
    ],
    // Reuses the google_calendar connector defined earlier in this session.
    tools: [
      {
        type: "mcp",
        server_label: "google_calendar",
      },
    ],
  },
};

ws.send(JSON.stringify(event));

Cette réutilisation se limite à la session en cours. Si vous démarrez une nouvelle session Realtime, renvoyez la définition MCP complète afin que le serveur puisse importer sa liste d’outils.