For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
Navegación principal

Tiempo real con herramientas

Permite que los agentes de voz en tiempo real llamen a herramientas de función y servidores MCP remotos.

Puedes agregar herramientas a una sesión de Realtime para que el modelo consulte datos, realice acciones o llame a servicios durante una conversación en vivo. La configuración de herramientas usa la misma interfaz de eventos, tanto si tu cliente usa un canal de datos WebRTC como si usa un WebSocket.

Usa herramientas de función cuando tu aplicación deba ejecutar la herramienta y devolver el resultado. Usa herramientas MCP cuando la Realtime API deba conectarse a un servidor de herramientas remoto por ti.

Elige un tipo de herramienta

Tipo de herramientaCuándo usarloQuién lo ejecuta
functionTu aplicación se encarga de la lógica de negocio, las verificaciones de aprobación o el acceso a sistemas privados.Tu cliente o servidor recibe una llamada a función y devuelve function_call_output.
mcp con server_urlQuieres que el modelo llame a herramientas expuestas por un servidor MCP remoto.La Realtime API llama al servidor MCP remoto.
mcp con connector_idUsas un conector integrado heredado con un modelo existente.La Realtime API llama al conector con la autorización que proporcionas.

Agrega herramientas en uno de estos dos lugares:

  • A nivel de sesión , con session.tools en session.update, si quieres que la herramienta esté disponible durante toda la sesión.
  • A nivel de respuesta , con response.tools en response.create, si solo necesitas la herramienta para un turno.

Configura una herramienta de función

Las herramientas de función son la opción predeterminada adecuada cuando la herramienta debe ejecutarse en tu aplicación. El modelo emite los argumentos de la llamada a función, tu código ejecuta la acción y envía el resultado mediante un elemento function_call_output.

Configura una herramienta de función con 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));

Cuando el modelo llame a la función, espera a recibir el elemento de llamada a función, ejecuta la lógica de tu aplicación y luego envía el resultado:

Envía el resultado de la llamada a función
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" }));

Para ver una explicación completa de las llamadas a funciones, evento por evento, consulta Gestión de conversaciones.

Configura una herramienta MCP

Las herramientas MCP son útiles cuando la herramienta ya está disponible a través de un servidor MCP remoto o cuando un modelo existente usa un conector integrado heredado. A diferencia de las herramientas de función, las herramientas MCP las ejecuta la propia Realtime API.

En Realtime, la estructura de una herramienta MCP es la siguiente:

  • type: "mcp"
  • server_label
  • Uno de estos dos campos: server_url o connector_id
  • authorization y headers, opcionales
  • allowed_tools, opcional
  • require_approval, opcional
  • server_description, opcional

Este ejemplo hace que un servidor MCP de documentación esté disponible durante toda la sesión:

Configura una herramienta MCP con 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));

Conectores heredados

connector_id está en desuso para los modelos lanzados después del 1 de septiembre de 2026. Usa server_url para conectarte a un servidor MCP remoto, o tunnel_id para conectarte a un servidor MCP local a través de Túnel MCP seguro. Los modelos existentes mantienen la compatibilidad con los conectores. El siguiente ejemplo usa gpt-realtime-1.5, que se lanzó antes de esa fecha límite.

Los conectores integrados usan la misma estructura de herramienta MCP, pero se les pasa connector_id en lugar de server_url. Por ejemplo, Google Calendar usa connector_googlecalendar. En Realtime, usa estos conectores integrados para acciones de lectura, como buscar o leer eventos o correos electrónicos. Pasa el token de acceso OAuth del usuario en authorization y limita las herramientas disponibles con allowed_tools cuando sea posible:

Configura un conector de 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));

Los servidores MCP remotos no reciben automáticamente el contexto completo de la conversación, pero pueden ver cualquier dato que el modelo envíe en una llamada a herramienta. Mantén limitado el conjunto de herramientas disponibles con allowed_tools, y exige aprobación para cualquier acción que no ejecutarías automáticamente.

Flujo de MCP en Realtime

A diferencia de las herramientas function de Realtime, las herramientas MCP remotas las ejecuta la propia Realtime API. Tu cliente no ejecuta la herramienta remota ni devuelve un function_call_output. En cambio, tu cliente configura el acceso, escucha los eventos del ciclo de vida de MCP y, de manera opcional, envía una respuesta de aprobación si el servidor la solicita.

Un flujo típico es el siguiente:

  1. Envías session.update o response.create con una entrada en tools cuyo type es mcp.
  2. El servidor comienza a importar herramientas y emite mcp_list_tools.in_progress.
  3. Mientras se sigue obteniendo la lista de herramientas, el modelo no puede llamar a una herramienta que aún no se haya cargado. Si quieres esperar antes de iniciar un turno que dependa de esas herramientas, espera a recibir mcp_list_tools.completed. El evento conversation.item.done cuyo item.type es mcp_list_tools muestra los nombres de las herramientas que se importaron realmente. Si la importación falla, recibirás mcp_list_tools.failed.
  4. El usuario habla o envía texto y se crea una respuesta, ya sea desde tu cliente o automáticamente según la configuración de la sesión.
  5. Si el modelo elige una herramienta MCP, verás response.mcp_call_arguments.delta y response.mcp_call_arguments.done.
  6. Si se requiere aprobación, el servidor agrega un elemento a la conversación cuyo item.type es mcp_approval_request. Tu cliente debe responder con un elemento mcp_approval_response.
  7. Cuando la herramienta se ejecute, verás response.mcp_call.in_progress. Si se ejecuta correctamente, más adelante recibirás un evento response.output_item.done cuyo item.type es mcp_call; si falla, recibirás response.mcp_call.failed.
  8. El evento response.done de una respuesta puede llegar antes de que finalicen sus llamadas MCP. Una vez que hayan finalizado la respuesta y todas sus llamadas MCP, envía otro evento response.create para que el modelo use los resultados y continúe la conversación. Repite este paso si el modelo realiza más llamadas MCP. La Realtime API no crea estas respuestas de seguimiento automáticamente.

Este manejador de eventos registra los principales eventos del ciclo de vida de MCP; no gestiona las respuestas de seguimiento:

Escucha eventos MCP durante una sesión de 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;
  }
});

Fallas comunes

  • mcp_list_tools.failed: la Realtime API no pudo importar herramientas del servidor remoto o del conector. Revisa server_url o connector_id, la autenticación, la conectividad del servidor y los nombres que hayas especificado en allowed_tools.
  • response.mcp_call.failed: el modelo seleccionó una herramienta, pero la llamada a la herramienta no se completó. Inspecciona el contenido del evento y el elemento mcp_call posterior para detectar errores del protocolo MCP, de ejecución o de transporte.
  • mcp_approval_request sin un mcp_approval_response correspondiente: la llamada a la herramienta no puede continuar hasta que tu cliente la apruebe o rechace explícitamente.
  • Un turno comienza mientras mcp_list_tools.in_progress sigue activo: solo las herramientas que ya terminaron de cargarse pueden usarse en ese turno.
  • Una respuesta usa tool_choice: "required", pero no hay herramientas disponibles en ese momento: el modelo no tiene ninguna herramienta que pueda llamar. Espera a que se emita mcp_list_tools.completed, confirma que se haya importado al menos una herramienta o usa un valor diferente de tool_choice para los turnos que no requieran una herramienta.
  • La validación de la definición de la herramienta MCP falla antes de que comience la importación: las causas comunes son un server_label duplicado en el mismo arreglo tools, configurar tanto server_url como connector_id, omitir ambos en la solicitud inicial de creación de la sesión, usar un connector_id no válido o enviar tanto authorization como headers.Authorization. Para los conectores, no envíes headers.Authorization en ningún caso.

Aprobar o rechazar llamadas a herramientas MCP

Si una herramienta requiere aprobación, la Realtime API inserta un elemento mcp_approval_request en la conversación. Para continuar, envía un nuevo evento conversation.item.create cuyo item.type sea mcp_approval_response.

Aprobar una solicitud 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 rechazas la solicitud, establece approve en false y, de forma opcional, incluye reason.

Usar MCP para una sola respuesta

Si MCP debe estar disponible solo durante un turno, agrega el mismo objeto de herramienta MCP a response.tools en lugar de session.tools:

Agregar herramientas MCP a una respuesta
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));

Esto es útil cuando solo una respuesta necesita contexto externo o cuando distintos turnos deben usar distintos servidores MCP.

Reutilizar una etiqueta de servidor definida previamente

server_label es el identificador estable de una definición de herramienta en la sesión Realtime actual. Después de definir un servidor o conector una vez con server_label junto con server_url o connector_id, los eventos session.update o response.create posteriores pueden hacer referencia únicamente a ese mismo server_label, y la Realtime API reutilizará la definición anterior sin que tengas que volver a enviar el objeto completo de la herramienta.

Reutilizar un conector definido previamente
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));

Esta reutilización se limita a la sesión actual. Si inicias una nueva sesión Realtime, vuelve a enviar la definición completa de MCP para que el servidor pueda importar su lista de herramientas.