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
Theme

Realtime con herramientas

Permite que los agentes de voz en tiempo real llamen a herramientas de tipo función y a 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. Los eventos para configurar las herramientas son los mismos tanto si tu cliente usa un canal de datos WebRTC como si usa un WebSocket.

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

Elige un tipo de herramienta

Tipo de herramienta Cuándo usarla Quién la ejecuta
function Tu 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 una función y devuelve function_call_output.
mcp con server_url Quieres que el modelo llame a las herramientas que ofrece un servidor MCP remoto. La Realtime API llama al servidor MCP remoto.
mcp con connector_id Usas un conector integrado heredado con un modelo existente. La Realtime API llama al conector con la autorización que proporcionas.

Agrega las herramientas en uno de estos dos niveles:

  • 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 tipo función

Si la herramienta debe ejecutarse en tu aplicación, elige una herramienta de tipo función como opción predeterminada. El modelo genera los argumentos de la llamada a la función. Tu código ejecuta la acción y devuelve el resultado mediante un elemento function_call_output.

Configura una herramienta de tipo 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 correspondiente a la llamada, ejecuta la lógica de tu aplicación y devuelve el resultado:

Envía el resultado de la llamada a la 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",
    response: { output_modalities: ["text"], tool_choice: "none" },
  })
);

Para ver cómo funciona la llamada a funciones, evento por evento, consulta Gestión de conversaciones.

Configura una herramienta MCP

Las herramientas MCP son útiles cuando un servidor MCP remoto ya ofrece la herramienta o cuando un modelo existente usa un conector integrado heredado. A diferencia de las herramientas de tipo función, las herramientas MCP las ejecuta la propia Realtime API.

En Realtime, una herramienta MCP tiene la siguiente estructura:

  • 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)

En este ejemplo, un servidor MCP de documentación queda 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 mediante un túnel MCP seguro. Los modelos existentes siguen admitiendo conectores. El siguiente ejemplo usa gpt-realtime-1.5, que se lanzó antes de esa fecha.

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

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 todo el contexto de la conversación, pero pueden ver cualquier dato que el modelo envíe en una llamada a una herramienta. Limita las 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 de tipo function de Realtime, las herramientas MCP remotas las ejecuta la propia Realtime API. Tu cliente no ejecuta la herramienta remota ni devuelve un elemento function_call_output. En cambio, configura el acceso, escucha los eventos del ciclo de vida de MCP y, si el servidor solicita aprobación, puede enviar una respuesta a esa solicitud.

El 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 empieza a importar las herramientas y emite mcp_list_tools.in_progress.
  3. Mientras se genera la lista, el modelo no puede llamar a una herramienta que aún no haya terminado de cargarse. Si quieres esperar antes de iniciar un turno que dependa de esas herramientas, escucha el evento 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. Si la importación falla, recibirás mcp_list_tools.failed.
  4. El usuario habla o envía texto. Tu cliente crea una respuesta o esta se crea 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 a la conversación un elemento cuyo item.type es mcp_approval_request. Tu cliente debe responder con un elemento mcp_approval_response.
  7. Cuando la herramienta empiece a ejecutarse, verás response.mcp_call.in_progress. Si la ejecución se completa correctamente, luego 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 terminen sus llamadas MCP. Cuando hayan terminado tanto la respuesta como 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 hace más llamadas MCP. La Realtime API no crea automáticamente estas respuestas de seguimiento.

Este manejador de eventos registra los principales eventos del ciclo de vida de MCP. No gestiona las respuestas de seguimiento.

Escucha los 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;
  }
});

Errores comunes

  • mcp_list_tools.failed: la Realtime API no pudo importar las 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 eligió una herramienta, pero la llamada no se completó. Revisa los datos del evento y el elemento mcp_call que llega después para identificar errores del protocolo MCP, de ejecución o de transporte.
  • Hay un elemento mcp_approval_request sin un mcp_approval_response correspondiente: la llamada a la herramienta no puede continuar hasta que tu cliente la apruebe o la rechace explícitamente.
  • Un turno comienza mientras mcp_list_tools.in_progress sigue activo: en ese turno solo se pueden usar las herramientas que ya terminaron de cargarse.
  • Una respuesta usa tool_choice: "required", pero en ese momento no hay herramientas disponibles: el modelo no tiene ninguna herramienta a la que pueda llamar. Espera a recibir mcp_list_tools.completed, confirma que se haya importado al menos una herramienta o usa otro valor de tool_choice para los turnos que no requieran herramientas.
  • La validación de la definición de una herramienta MCP falla antes de que empiece la importación. Entre las causas comunes están duplicar server_label en el mismo arreglo tools, especificar tanto server_url como connector_id, omitir ambos campos 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. Si usas conectores, nunca envíes headers.Authorization.

Aprueba o rechaza 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.

Aprueba una solicitud 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));
}

Si rechazas la solicitud, establece approve en false y, si quieres, incluye el motivo en reason.

Usa 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:

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

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

Reutiliza una etiqueta de servidor definida previamente

server_label es el identificador estable de una definición de herramienta en la sesión de Realtime actual. Una vez que definas un servidor o conector con server_label y con uno de los campos server_url o connector_id, en los eventos session.update o response.create posteriores basta con indicar ese mismo server_label. La Realtime API reutilizará la definición anterior sin que tengas que volver a enviar el objeto completo de la herramienta.

Reutiliza 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));

Solo puedes reutilizar la definición dentro de la misma sesión. Si inicias una nueva sesión de Realtime, vuelve a enviar la definición MCP completa para que el servidor pueda importar su lista de herramientas.