For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
メインナビゲーション
Theme

Realtime でのツールの利用

リアルタイム音声エージェントから関数ツールやリモート MCP サーバーを呼び出せるようにします。

Realtime セッションにツールを追加すると、モデルは会話中にデータを検索したり、操作を実行したり、サービスを呼び出したりできます。クライアントが WebRTC データチャネルと WebSocket のどちらを使う場合も、ツールの設定には同じイベントを使います。

アプリケーションがツールを実行して結果を返す場合は、関数ツールを使います。Realtime API にリモートのツールサーバーへの接続を任せる場合は、MCP ツールを使います。

ツールの種類の選び方

ツールの種類 用途 実行主体と動作
function アプリケーション側でビジネスロジック、承認の確認、非公開システムへのアクセスのいずれかを管理する場合 クライアントまたはサーバーが関数呼び出しを受け取り、function_call_output を返します。
mcp と server_url モデルからリモート MCP サーバーが公開するツールを呼び出す場合 Realtime API がリモート MCP サーバーを呼び出します。
mcp と connector_id 既存のモデルで従来の組み込みコネクタを使う場合 Realtime API が指定された認可情報を使ってコネクタを呼び出します。

ツールは次の 2 か所のいずれかに追加します。

  • セッション単位で追加するには、session.tools を session.update に含めます。ツールをセッション全体で利用できます。
  • レスポンス単位で追加するには、response.tools を response.create に含めます。ツールが 1 ターンだけ必要な場合に使います。

関数ツールの設定

アプリケーション側でツールを実行する場合は、基本的に関数ツールを使います。モデルが関数呼び出しの引数を出力したら、アプリケーションのコードで操作を実行し、function_call_output アイテムで結果を返します。

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

モデルが関数を呼び出したら、関数呼び出しのアイテムを受け取り、アプリケーションのロジックを実行してから結果を返します。

関数呼び出しの結果の送信
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" },
  })
);

Function Calling の手順をイベントごとに確認するには、「会話の管理」を参照してください。

MCP ツールの設定

MCP ツールは、リモート MCP サーバーがすでに提供しているツールを使う場合や、既存のモデルで従来の組み込みコネクタを使う場合に適しています。関数ツールと異なり、MCP ツールは Realtime API 自体が実行します。

Realtime では、MCP ツールを次の項目で定義します。

  • type: "mcp"
  • server_label
  • server_url または connector_id のいずれか
  • 任意項目の authorization と headers
  • 任意項目の allowed_tools
  • 任意項目の require_approval
  • 任意項目の server_description

次の例では、ドキュメント用の MCP サーバーをセッション全体で利用できるようにします。

session.update を使った MCP ツールの設定
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));

従来のコネクタ

connector_id は、2026 年 9 月 1 日より後にリリースされたモデルでは非推奨です。リモート MCP サーバーに接続するには server_url を使います。ローカル MCP サーバーに接続するには tunnel_id を指定し、 セキュア MCP トンネルを経由します。既存のモデルは引き続きコネクタをサポートします。次の例で使用する gpt-realtime-1.5 は、2026 年 9 月 1 日より前にリリースされたモデルです。

組み込みコネクタも MCP ツールと同じ形式で定義しますが、指定するのは connector_id で、server_url は使いません。たとえば、Google カレンダーでは connector_googlecalendar を使います。Realtime では、予定やメールの検索、内容の取得などの読み取り操作に組み込みコネクタを使います。ユーザーの OAuth アクセストークンを authorization に指定し、可能な限り allowed_tools で利用できるツールを絞り込んでください。

Google カレンダーのコネクタの設定
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));

リモート MCP サーバーが 会話のコンテキスト全体を自動的に受け取ることはありません。ただし、モデルがツール呼び出しで送信したデータはすべてサーバーから参照できます。 利用できるツールを必要最小限に絞るには allowed_tools を使います。自動実行を許可しない操作には必ず承認を求めてください。

Realtime での MCP ツール実行の流れ

Realtime の function ツールと異なり、リモート MCP ツールは Realtime API 自体が実行します。クライアントはリモートツールを実行せず、function_call_output も返しません。クライアントはツールへのアクセスを設定し、MCP のライフサイクルイベントを受け取ります。サーバーが承認を求めた場合は、必要に応じて承認リクエストへの応答を送信します。

一般的な流れは次のとおりです。

  1. session.update または response.create を送信します。tools には、type が mcp のエントリを含めます。
  2. サーバーがツールのインポートを開始し、mcp_list_tools.in_progress を送信します。
  3. ツール一覧の取得中、モデルはまだ読み込まれていないツールを呼び出せません。そのツールが必要なターンを開始する前に読み込みを待つ場合は、mcp_list_tools.completed を待ち受けます。conversation.item.done イベントのうち、item.type が mcp_list_tools のイベントで、実際にインポートされたツールの名前を確認できます。インポートに失敗すると、mcp_list_tools.failed が届きます。
  4. ユーザーが発話するかテキストを送信すると、クライアントがレスポンスを作成するか、セッションの設定に従ってレスポンスが自動的に作成されます。
  5. モデルが MCP ツールを選ぶと、response.mcp_call_arguments.delta と response.mcp_call_arguments.done が届きます。
  6. 承認が必要な場合、サーバーは item.type が mcp_approval_request のアイテムを会話に追加します。クライアントは mcp_approval_response アイテムで応答する必要があります。
  7. ツールの実行が始まると、response.mcp_call.in_progress が届きます。成功すると、その後に response.output_item.done イベントが届きます。このイベントの item.type は mcp_call です。失敗すると、response.mcp_call.failed が届きます。
  8. response.done は、そのレスポンスに含まれる MCP 呼び出しが完了する前に届くことがあります。レスポンスとその MCP 呼び出しがすべて完了したら、もう一度 response.create イベントを送信し、モデルが結果を使って会話を続けられるようにします。モデルがさらに MCP 呼び出しを行った場合は、この手順を繰り返します。Realtime API は、こうした後続のレスポンスを自動では作成しません。

次のイベントハンドラーは、MCP の主要なライフサイクルイベントをログに記録します。後続のレスポンスは管理しません。

Realtime セッションでの MCP イベントの受信
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 または connector_id の値、認証情報、サーバーへの接続、allowed_tools に指定したツール名を確認してください。
  • response.mcp_call.failed が届いた場合、モデルはツールを選択しましたが、呼び出しが完了しませんでした。イベントのペイロードと後続の mcp_call アイテムを調べ、MCP プロトコル、ツールの実行、通信のいずれかでエラーが発生していないか確認してください。
  • mcp_approval_request に対応する mcp_approval_response がない場合、クライアントが明示的に承認または拒否するまでツール呼び出しは先に進みません。
  • mcp_list_tools.in_progress の状態が続いている間にターンが始まった場合、そのターンで利用できるのは、すでに読み込みが完了したツールだけです。
  • レスポンスに tool_choice: "required" を指定していても、その時点で利用できるツールがなければ、モデルが呼び出せるツールはありません。mcp_list_tools.completed を待つか、少なくとも 1 つのツールがインポートされたことを確認してください。ツールが不要なターンでは別の tool_choice を指定することもできます。
  • インポート開始前に MCP ツール定義の検証に失敗する場合は、次の点を確認してください。server_label が同じ tools 配列内で重複していると検証に失敗します。ほかにも、server_url と connector_id の両方を指定している、最初のセッション作成リクエストでどちらも指定していない、無効な connector_id を使っている、authorization と headers.Authorization の両方を送信している、といった原因があります。コネクタを使う場合は、headers.Authorization を送信しないでください。

MCP ツール呼び出しの承認と拒否

ツールの実行に承認が必要な場合、Realtime API は mcp_approval_request アイテムを会話に追加します。処理を続けるには、新しい conversation.item.create イベントの item.type に mcp_approval_response を指定して送信します。

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

リクエストを拒否するには、approve を false に設定します。必要に応じて reason に理由を指定できます。

1 回のレスポンスに限定した MCP の利用

MCP を 1 ターンだけ利用できるようにするには、同じ MCP ツールオブジェクトを response.tools に追加します。この場合、session.tools は使いません。

1 回のレスポンスへの MCP ツールの追加
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));

この方法は、外部のコンテキストが必要なレスポンスが 1 つだけの場合や、ターンごとに異なる MCP サーバーを使いたい場合に便利です。

定義済みのサーバーラベルの再利用

server_label は、現在の Realtime セッション内でツール定義を識別するための固定のラベルです。サーバーまたはコネクタを初めて定義するときに、server_label とともに server_url または connector_id を指定します。以降の session.update または response.create イベントでは、同じ server_label を指定するだけで Realtime API が以前の定義を再利用します。ツールオブジェクト全体を再送する必要はありません。

定義済みのコネクタの再利用
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 定義全体を再送してください。