English
主导航

旧版 API

实时工具调用

让实时语音智能体调用函数工具、远程 MCP 服务器和连接器。

你可以将工具附加到 Realtime 会话中,以便模型在实时对话期间查找数据、执行操作或调用服务。无论客户端使用的是 WebRTC 数据通道 or a WebSocket.

当你的应用程序需要自行执行工具并返回结果时,请使用函数工具。当你希望 Realtime API 代为连接到远程工具服务器时,请使用 MCP 工具或内置连接器。

选择工具类型

工具类型适用场景执行者
function你的应用程序负责处理业务逻辑、审批检查或私有系统的访问。你的客户端或服务器会接收到函数调用,并返回 function_call_output.
mcp with server_url你希望模型调用由远程 MCP 服务器提供的工具。Realtime API 调用该远程 MCP 服务器。
mcp with connector_id你希望使用如 Google Calendar 这样的内置连接器。Realtime API 使用你提供的授权信息调用该连接器。

在以下 两个位置之一添加工具:

  • 会话级别 with session.tools in session.update,如果您希望该工具在整个会话期间可用。
  • 响应级别 with response.tools in response.create,如果您仅需在一轮对话中使用该工具。

配置函数工具

当工具需要在你的应用程序中运行时,函数工具是合适的默认选项。模型输出函数调用参数,你的代码执行相应操作,然后你的代码通过 function_call_output item.

使用 session.update 配置函数工具
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const event = {
  type: "session.update",
  session: {
    type: "realtime",
    model: "gpt-realtime-2",
    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));

当模型调用该函数时,监听函数调用项,运行你的应用程序逻辑,然后将输出发送回去:

发送函数调用输出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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" }));

有关函数调用从事件到事件的完整演练,请参见 管理对话.

配置 MCP 工具

当工具已存在于远程 MCP 服务器之后,或者当你想使用 OpenAI 托管的连接器时,MCP 工具非常有用。与函数工具不同,MCP 工具由 Realtime API 自身执行。

在 Realtime 中,MCP 工具的结构为:

  • type: "mcp"
  • server_label
  • 其中之一 server_url or connector_id
  • 可选 authorization and headers
  • 可选 allowed_tools
  • 可选 require_approval
  • 可选 server_description

此示例使文档 MCP 服务器在整个会话期间可用:

使用 session.update 配置 MCP 工具
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const event = {
  type: "session.update",
  session: {
    type: "realtime",
    model: "gpt-realtime-2",
    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));

内置连接器使用相同的 MCP 工具结构,但在可能的情况下传入 connector_id 而不是 server_url。例如,Google Calendar 使用 connector_googlecalendar。在 Realtime 中,请使用这些内置连接器进行读取操作,例如搜索或读取事件及电子邮件。将用户的 OAuth 访问令牌传入 authorization,并使用以下方式缩小工具的作用范围: allowed_tools 在可能的情况下:

配置 Google Calendar 连接器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const event = {
  type: "session.update",
  session: {
    type: "realtime",
    model: "gpt-realtime-2",
    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));

远程 MCP 服务器 不会自动接收完整的对话上下文,但是 它们可以看到模型在工具调用中发送的任何数据. 保持工具的范围最小化 with allowed_tools,并且对任何您不希望自动运行的操作要求审批。

Realtime MCP 流程

与 Realtime function 工具不同,远程 MCP 工具 由 Realtime API 自身执行. 你的客户端不会运行远程工具 and return a function_call_output。相反,您的客户端会配置访问权限、监听 MCP 生命周期事件,并在服务器请求时选择性地发送审批响应。

典型流程如下:

  1. 你发送 session.update or response.create with a tools 条目,其 type is mcp.
  2. 服务器开始导入工具并发出 mcp_list_tools.in_progress.
  3. 在列表仍在处理时,模型无法调用尚未加载的工具。如果你想在开始依赖于这些工具的轮次之前等待,请监听 mcp_list_tools.completed。该 conversation.item.done 事件,其 item.type is mcp_list_tools 显示实际导入了哪些工具名称。如果导入失败,你将收到 mcp_list_tools.failed.
  4. 用户说话或发送文本,随后会创建一个响应,这可以由你的客户端完成,也可以由会话配置自动完成。
  5. 如果模型选择了 MCP 工具,你会看到 response.mcp_call_arguments.delta and response.mcp_call_arguments.done.
  6. 如果需要审批,服务器会添加一个对话项,其 item.type is mcp_approval_request。您的客户端必须使用 mcp_approval_response item.
  7. 工具运行后,你会看到 response.mcp_call.in_progress来应答。如果成功,您随后将收到一个 response.output_item.done 事件,其 item.type is mcp_call;如果失败,您将收到 response.mcp_call.failed。助手消息项和 response.done 完成该轮次。

此事件处理器涵盖了主要的检查点:

在 Realtime 会话期间监听 MCP 事件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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;
  }
});

常见故障

  • mcp_list_tools.failed:Realtime API 无法从远程服务器或连接器导入工具。请检查 server_url or connector_id、身份验证、服务器连接状况以及任何 allowed_tools 你指定的名称。
  • response.mcp_call.failed:模型已选择一个工具,但工具调用未能完成。请检查事件负载及随后的 mcp_call MCP 协议、执行或传输错误的相关项。
  • mcp_approval_request with no matching mcp_approval_response:工具调用将暂停,直到您的客户端明确批准或拒绝该调用。
  • A turn starts while mcp_list_tools.in_progress 仍处于活跃状态:只有已完成加载的工具才有资格参与该轮次。
  • A response uses tool_choice: "required" 但当前没有可用的工具:模型没有可供调用的合格工具。请等待 mcp_list_tools.completed,请确认至少导入了一个工具,或使用不同的 tool_choice 用于不需要工具的轮次。
  • MCP 工具定义在导入开始前验证失败:常见原因是重复的 server_label in the same tools 数组,同时设置了 server_url and connector_id,在初始创建会话的请求中同时省略这两者、使用无效的 connector_id,或者同时发送这两者 authorization and headers.Authorization。对于连接器,请勿发送 headers.Authorization 完全不。

批准或拒绝 MCP 工具调用

如果工具需要批准,Realtime API 会向对话中插入一个 mcp_approval_request 项。 To continue,请发送一个新的 conversation.item.create 事件,其 item.type is mcp_approval_response.

批准 MCP 请求
1
2
3
4
5
6
7
8
9
10
11
12
13
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));
}

如果您拒绝该请求,请设置 approve to false and optionally include a reason.

仅在单次响应中使用 MCP

如果 MCP 应该 仅在单轮次中可用,将相同的 MCP 工具对象附加到 response.tools 而不是 session.tools:

在单次响应中添加 MCP 工具
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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));

这适用于仅单次响应需要外部上下文,或不同轮次需要使用不同 MCP 服务器的情况。

复用先前定义的服务器标签

server_label 是当前 Realtime 会话中工具定义的稳定句柄。在您使用以下命令定义服务器或连接器一次后 server_label 以及 server_url or connector_id,随后 session.update or response.create 事件只能引用该相同的 server_label,而 Realtime API 将复用先前的定义,无需您再次发送完整的工具对象。

复用先前定义的连接器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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));

这种复用仅限于会话范围。如果您启动一个新的 Realtime 会话,请再次发送完整的 MCP 定义,以便服务器导入其工具列表。