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

Utiliser des outils avec Realtime

Permettez à vos agents vocaux d’appeler des fonctions et des serveurs MCP distants en temps réel.

Vous pouvez associer des outils à une session Realtime pour que le modèle puisse rechercher des données, exécuter des actions ou appeler des services au cours d’une conversation en direct. Les événements de configuration des outils sont les mêmes, que votre client utilise un canal de données WebRTC ou une connexion WebSocket.

Utilisez un outil de type fonction si votre application doit exécuter l’outil et renvoyer le résultat. Utilisez un outil MCP si vous souhaitez que la Realtime API se connecte pour vous à un serveur d’outils distant.

Choisissez un type d’outil

Type d’outil Quand l’utiliser Qui l’exécute
function Votre application gère la logique métier, les vérifications d’approbation ou l’accès à des systèmes privés. Votre client ou votre serveur reçoit un appel de fonction et renvoie un élément function_call_output.
mcp avec server_url Vous souhaitez que le modèle appelle les outils mis à disposition par un serveur MCP distant. La Realtime API appelle le serveur MCP distant.
mcp avec connector_id Vous utilisez un ancien connecteur intégré avec un modèle existant. La Realtime API appelle le connecteur avec l’autorisation que vous fournissez.

Ajoutez les 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 avez besoin de l’outil pour un seul tour de conversation.

Configurez un outil de type fonction

Privilégiez les outils de type fonction lorsque l’exécution doit se faire dans votre application. Le modèle fournit les arguments de l’appel de fonction, puis votre code exécute l’action et 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 les événements pour détecter l’élément correspondant à l’appel de fonction, exécutez la logique de votre application, puis renvoyez le résultat :

Renvoyez 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",
    response: { output_modalities: ["text"], tool_choice: "none" },
  })
);

Pour suivre le déroulement complet d’un appel de fonction, événement par événement, consultez le guide Gestion des conversations.

Configurez un outil MCP

Les outils MCP sont utiles lorsqu’un serveur MCP distant propose déjà l’outil ou qu’un modèle existant utilise un ancien connecteur intégré. Contrairement aux outils de type fonction, les outils MCP sont exécutés directement par la Realtime API.

Dans Realtime, la définition d’un outil MCP comporte les champs suivants :

  • type: "mcp"
  • server_label
  • Soit server_url, soit connector_id
  • authorization et headers (facultatifs)
  • allowed_tools (facultatif)
  • require_approval (facultatif)
  • server_description (facultatif)

Cet exemple rend un serveur MCP de documentation accessible 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 obsolète 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 un 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.

Les connecteurs intégrés se configurent comme les autres outils MCP, mais utilisent connector_id à la place de server_url. Par exemple, Google Agenda utilise connector_googlecalendar. Dans Realtime, utilisez ces connecteurs intégrés pour les opérations de lecture, comme la recherche ou la consultation d’événements ou d’e-mails. Transmettez le jeton d’accès OAuth de l’utilisateur dans authorization et, si possible, limitez les outils accessibles avec allowed_tools :

Configurez un connecteur Google Agenda
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 lors d’un appel d’outil. Limitez les outils accessibles avec allowed_tools et exigez une approbation pour toute action que vous ne lanceriez pas automatiquement.

Déroulement des appels MCP dans Realtime

Contrairement aux outils Realtime de type function, les outils MCP distants sont exécutés directement par la Realtime API. Votre client n’exécute pas l’outil distant et ne renvoie donc pas d’élément function_call_output. Il configure l’accès, écoute les événements du cycle de vie MCP et peut envoyer une réponse à une demande d’approbation du serveur.

Voici le déroulement habituel :

  1. 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 le serveur établit la liste des outils, le modèle ne peut appeler que les outils déjà chargés. Si vous souhaitez attendre avant de lancer un tour de conversation 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. Votre client crée alors une réponse, ou la session la crée automatiquement selon sa configuration.
  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 à la conversation un élément 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 commence à s’exécuter, vous recevez response.mcp_call.in_progress. Si l’appel aboutit, 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 des appels MCP associés. Une fois la réponse et tous ses appels MCP terminés, envoyez un nouvel événement response.create pour que le modèle puisse utiliser les résultats et poursuivre la conversation. Répétez cette étape si le modèle effectue d’autres appels MCP. La Realtime API ne crée pas automatiquement ces réponses de suivi.

Ce gestionnaire consigne 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;
  }
});

Erreurs courantes

  • mcp_list_tools.failed : la Realtime API n’a pas pu importer les outils du serveur distant ou du connecteur. Vérifiez la valeur de server_url ou de connector_id, l’authentification, la connexion au serveur et les noms d’outils que vous avez indiqués dans allowed_tools.
  • response.mcp_call.failed : le modèle a sélectionné un outil, mais l’appel n’a pas abouti. Examinez le contenu de l’événement, puis celui de l’élément mcp_call reçu ultérieurement, pour repérer les erreurs de protocole MCP, d’exécution ou de transport.
  • Vous recevez un élément mcp_approval_request sans élément mcp_approval_response correspondant : l’appel d’outil reste en attente tant que votre client ne l’a pas explicitement approuvé ou rejeté.
  • Un tour de conversation commence alors que mcp_list_tools.in_progress est toujours actif : seuls les outils déjà chargés peuvent être appelés pendant ce tour.
  • Une réponse utilise tool_choice: "required" alors qu’aucun outil n’est disponible : le modèle ne peut appeler aucun outil. Attendez mcp_list_tools.completed, vérifiez qu’au moins un outil a été importé ou choisissez une autre valeur de tool_choice pour les tours qui ne nécessitent pas d’outil.
  • La validation de la définition de l’outil MCP échoue avant le début de l’importation : les causes fréquentes sont 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 champs dans la requête initiale de création de session, une valeur de 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 d’outils MCP

Si un outil nécessite une approbation, la Realtime API insère un élément mcp_approval_request dans la conversation. Pour poursuivre, 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: {
      type: "mcp_approval_response",
      approval_request_id: approvalRequestId,
      approve: true,
    },
  };

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

Pour rejeter la demande, définissez approve sur false et, si vous le souhaitez, indiquez le motif dans reason.

Utilisez MCP pour une seule réponse

Si MCP doit être disponible pour un seul tour de conversation, associez le même objet de configuration de l’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"],
    tool_choice: "required",
    parallel_tool_calls: false,
    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 configuration est utile lorsqu’une seule réponse nécessite des informations externes ou que vous souhaitez utiliser des serveurs MCP différents selon le tour de conversation.

Réutilisez un identifiant 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 le serveur ou le connecteur défini avec server_label et l’un des deux champs server_url ou connector_id, vous pouvez, dans les événements session.update ou response.create suivants, indiquer uniquement ce même server_label. La Realtime API réutilise la définition associée sans que vous ayez à renvoyer l’objet de configuration 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 définition reste valable uniquement dans la session en cours. Si vous démarrez une nouvelle session Realtime, renvoyez la définition MCP complète pour que le serveur puisse importer sa liste d’outils.