For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
Navegação principal

Uso de ferramentas em tempo real

Permita que agentes de voz em tempo real chamem ferramentas de função e servidores MCP remotos.

Você pode adicionar ferramentas a uma sessão Realtime para que o modelo consulte dados, execute ações ou chame serviços durante uma conversa em tempo real. A configuração das ferramentas usa a mesma interface de eventos, independentemente de o cliente usar um canal de dados WebRTC ou um WebSocket.

Use ferramentas de função quando seu aplicativo precisar executar a ferramenta e retornar o resultado. Use ferramentas MCP quando a Realtime API precisar se conectar a um servidor remoto de ferramentas para você.

Escolha um tipo de ferramenta

Tipo de ferramentaQuando usarQuem executa
functionSeu aplicativo é responsável pela lógica de negócios, pelas verificações de aprovação ou pelo acesso a sistemas privados.Seu cliente ou servidor recebe uma chamada de função e retorna function_call_output.
mcp com server_urlVocê quer que o modelo chame ferramentas disponibilizadas por um servidor MCP remoto.A Realtime API chama o servidor MCP remoto.
mcp com connector_idVocê usa um conector integrado legado com um modelo existente.A Realtime API chama o conector com a autorização que você fornece.

Adicione ferramentas em um de dois lugares:

  • No nível da sessão , com session.tools em session.update, se quiser que a ferramenta fique disponível durante toda a sessão.
  • No nível da resposta , com response.tools em response.create, se precisar da ferramenta apenas para um turno.

Configure uma ferramenta de função

Ferramentas de função são a opção padrão adequada quando a ferramenta deve ser executada no seu aplicativo. O modelo emite os argumentos da chamada de função, seu código executa a ação e envia o resultado de volta em um item function_call_output.

Configure uma ferramenta de função com 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));

Quando o modelo chamar a função, aguarde o item de chamada de função, execute a lógica do seu aplicativo e envie a saída de volta:

Envie a saída da chamada de função
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 um passo a passo completo da chamada de função, evento por evento, consulte Gerenciamento de conversas.

Configure uma ferramenta MCP

As ferramentas MCP são úteis quando a ferramenta já está disponível por meio de um servidor MCP remoto ou quando um modelo existente usa um conector integrado legado. Ao contrário das ferramentas de função, as ferramentas MCP são executadas pela própria Realtime API.

No Realtime, a estrutura de uma ferramenta MCP é:

  • type: "mcp"
  • server_label
  • Um dos campos: server_url ou connector_id
  • authorization e headers opcionais
  • allowed_tools opcional
  • require_approval opcional
  • server_description opcional

Este exemplo disponibiliza um servidor MCP de documentação durante toda a sessão:

Configure uma ferramenta MCP com 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 legados

connector_id está obsoleto para modelos lançados após 1º de setembro de 2026. Use server_url para se conectar a um servidor MCP remoto ou tunnel_id para se conectar a um servidor MCP local por meio do Túnel MCP seguro. Os modelos existentes mantêm o suporte a conectores. O exemplo abaixo usa gpt-realtime-1.5, lançado antes dessa data.

Os conectores integrados usam a mesma estrutura de ferramenta MCP, mas passam connector_id em vez de server_url. Por exemplo, o Google Calendar usa connector_googlecalendar. No Realtime, use esses conectores integrados para ações de leitura, como pesquisar ou ler eventos ou e-mails. Passe o token de acesso OAuth do usuário em authorization e restrinja as ferramentas disponíveis com allowed_tools sempre que possível:

Configure um conector do 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));

Servidores MCP remotos não recebem automaticamente todo o contexto da conversa, mas podem ver quaisquer dados que o modelo envie em uma chamada de ferramenta. Restrinja as ferramentas disponíveis com allowed_tools, e exija aprovação para qualquer ação que você não executaria automaticamente.

Fluxo de MCP no Realtime

Ao contrário das ferramentas function do Realtime, as ferramentas MCP remotas são executadas pela própria Realtime API. Seu cliente não executa a ferramenta remota nem retorna um function_call_output. Em vez disso, ele configura o acesso, escuta os eventos do ciclo de vida do MCP e, opcionalmente, envia uma resposta de aprovação se o servidor solicitar.

Um fluxo típico funciona assim:

  1. Você envia session.update ou response.create com uma entrada em tools cujo type é mcp.
  2. O servidor começa a importar as ferramentas e emite mcp_list_tools.in_progress.
  3. Enquanto a listagem estiver em andamento, o modelo não poderá chamar uma ferramenta que ainda não tenha sido carregada. Se quiser aguardar antes de iniciar um turno que dependa dessas ferramentas, escute mcp_list_tools.completed. O evento conversation.item.done cujo item.type é mcp_list_tools mostra os nomes das ferramentas que foram efetivamente importadas. Se a importação falhar, você receberá mcp_list_tools.failed.
  4. O usuário fala ou envia texto, e uma resposta é criada pelo seu cliente ou automaticamente, conforme a configuração da sessão.
  5. Se o modelo escolher uma ferramenta MCP, você verá response.mcp_call_arguments.delta e response.mcp_call_arguments.done.
  6. Se for necessária aprovação, o servidor adicionará um item à conversa cujo item.type é mcp_approval_request. Seu cliente deverá responder a ele com um item mcp_approval_response.
  7. Quando a ferramenta for executada, você verá response.mcp_call.in_progress. Em caso de sucesso, você receberá depois um evento response.output_item.done cujo item.type é mcp_call; em caso de falha, receberá response.mcp_call.failed.
  8. O evento response.done de uma resposta pode chegar antes que as chamadas MCP dessa resposta terminem. Depois que a resposta e todas as suas chamadas MCP forem concluídas, envie outro evento response.create para que o modelo use os resultados e prossiga com a conversa. Repita essa etapa se o modelo fizer outras chamadas MCP. A Realtime API não cria essas respostas de continuação automaticamente.

Este manipulador de eventos registra os principais eventos do ciclo de vida do MCP; ele não gerencia as respostas de continuação:

Escute eventos MCP durante uma sessão 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;
  }
});

Falhas comuns

  • mcp_list_tools.failed: a Realtime API não conseguiu importar ferramentas do servidor remoto ou do conector. Verifique server_url ou connector_id, a autenticação, a conectividade do servidor e os nomes que você especificou em allowed_tools.
  • response.mcp_call.failed: o modelo selecionou uma ferramenta, mas a chamada da ferramenta não foi concluída. Inspecione o payload do evento e o item mcp_call recebido posteriormente para identificar erros de protocolo MCP, execução ou transporte.
  • mcp_approval_request sem um mcp_approval_response correspondente: a chamada da ferramenta não pode continuar até que seu cliente a aprove ou rejeite explicitamente.
  • Um turno começa enquanto mcp_list_tools.in_progress ainda está ativo: somente ferramentas que já terminaram de carregar podem ser usadas nesse turno.
  • Uma resposta usa tool_choice: "required", mas nenhuma ferramenta está disponível no momento: o modelo não tem nenhuma ferramenta que possa chamar. Aguarde mcp_list_tools.completed, confirme que pelo menos uma ferramenta foi importada ou use outro valor de tool_choice para turnos que não exigem uma ferramenta.
  • A validação da definição da ferramenta MCP falha antes do início da importação: as causas comuns são um server_label duplicado no mesmo array tools, definir tanto server_url quanto connector_id, omitir ambos na solicitação inicial de criação da sessão, usar um connector_id inválido ou enviar tanto authorization quanto headers.Authorization. Para conectores, nunca envie headers.Authorization.

Aprove ou rejeite chamadas de ferramentas MCP

Se uma ferramenta exigir aprovação, a Realtime API insere um item mcp_approval_request na conversa. Para continuar, envie um novo evento conversation.item.create cujo item.type seja mcp_approval_response.

Aprove uma solicitação 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));
}

Se você rejeitar a solicitação, defina approve como false e, opcionalmente, inclua um reason.

Use MCP em apenas uma resposta

Se o MCP deve ficar disponível apenas em um único turno, adicione o mesmo objeto de ferramenta MCP a response.tools em vez de session.tools:

Adicione ferramentas MCP a uma única resposta
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));

Isso é útil quando apenas uma resposta precisa de contexto externo ou quando turnos diferentes devem usar servidores MCP diferentes.

Reutilize um rótulo de servidor definido anteriormente

server_label é o identificador estável de uma definição de ferramenta na sessão Realtime atual. Depois de definir um servidor ou conector uma vez com server_label e server_url ou connector_id, eventos posteriores de session.update ou response.create podem fazer referência apenas a esse mesmo server_label, e a Realtime API reutilizará a definição anterior sem exigir que você envie o objeto completo da ferramenta novamente.

Reutilize um conector definido anteriormente
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));

Essa reutilização se limita à sessão. Se você iniciar uma nova sessão Realtime, envie a definição completa do MCP novamente para que o servidor possa importar sua lista de ferramentas.