Du kannst einer Realtime-Sitzung Werkzeuge hinzufügen, damit das Modell während eines laufenden Gesprächs Daten abfragen, Aktionen ausführen oder Dienste aufrufen kann. Die Konfiguration der Werkzeuge erfolgt über dieselbe Ereignisschnittstelle, unabhängig davon, ob dein Client einen WebRTC-Datenkanal oder einen WebSocket verwendet.
Verwende Funktionswerkzeuge, wenn deine Anwendung das Werkzeug ausführen und das Ergebnis zurückgeben soll. Verwende MCP-Werkzeuge, wenn die Realtime API für dich eine Verbindung zu einem Remote-Werkzeugserver herstellen soll.
Tool-Typ auswählen
| Tool-Typ | Einsatzbereich | Ausführung durch |
|---|---|---|
function | Deine Anwendung übernimmt die Geschäftslogik, Genehmigungsprüfungen oder den Zugriff auf private Systeme. | Dein Client oder Server empfängt einen Funktionsaufruf und gibt function_call_output zurück. |
mcp mit server_url | Du möchtest, dass das Modell Tools aufruft, die ein entfernter MCP-Server bereitstellt. | Die Realtime API ruft den entfernten MCP-Server auf. |
mcp mit connector_id | Du verwendest einen älteren integrierten Konnektor mit einem bestehenden Modell. | Die Realtime API ruft den Konnektor mit der von dir bereitgestellten Autorisierung auf. |
Füge Tools an einer von zwei Stellen hinzu:
- Auf Sitzungsebene mit
session.toolsinsession.update, wenn das Tool während der gesamten Sitzung verfügbar sein soll. - Auf Antwortebene mit
response.toolsinresponse.create, wenn du das Tool nur für einen Gesprächsschritt benötigst.
Ein Funktions-Tool konfigurieren
Funktions-Tools sind die passende Standardwahl, wenn das Tool in deiner Anwendung ausgeführt werden soll. Das Modell gibt die Argumente für den Funktionsaufruf aus. Dein Code führt die Aktion aus und sendet das Ergebnis mit einem function_call_output-Element zurück.
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));Wenn das Modell die Funktion aufruft, warte auf das Element mit dem Funktionsaufruf, führe deine Anwendungslogik aus und sende dann die Ausgabe zurück:
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" }));Eine vollständige Anleitung zum Funktionsaufruf, die jedes einzelne Ereignis erläutert, findest du unter Unterhaltungen verwalten.
Ein MCP-Tool konfigurieren
MCP-Werkzeuge eignen sich, wenn das Werkzeug bereits über einen Remote-MCP-Server verfügbar ist oder ein bestehendes Modell einen älteren integrierten Konnektor verwendet. Anders als Funktionswerkzeuge werden MCP-Werkzeuge von der Realtime API selbst ausgeführt.
In Realtime hat ein MCP-Tool folgende Struktur:
type: "mcp"server_label- Entweder
server_urloderconnector_id - Optional:
authorizationundheaders - Optional:
allowed_tools - Optional:
require_approval - Optional:
server_description
Dieses Beispiel stellt einen MCP-Server für Dokumentation während der gesamten Sitzung bereit:
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));Ältere Konnektoren
connector_id gilt für Modelle, die nach dem 1. September
2026 veröffentlicht wurden, als veraltet. Verwende server_url, um eine Verbindung zu einem Remote-MCP-Server herzustellen, oder
tunnel_id für eine Verbindung zu einem lokalen MCP-Server über den
Sicheren MCP-Tunnel. Bestehende
Modelle unterstützen weiterhin Konnektoren. Das folgende Beispiel verwendet
gpt-realtime-1.5, das vor diesem Stichtag veröffentlicht wurde.
Integrierte Konnektoren verwenden dieselbe Struktur wie MCP-Tools, übergeben aber connector_id
anstelle von server_url. Google Calendar verwendet beispielsweise
connector_googlecalendar. Verwende diese integrierten Konnektoren in Realtime für Lesezugriffe,
etwa zum Suchen oder Lesen von Terminen oder E-Mails. Übergib das OAuth-Zugriffstoken
der nutzenden Person in authorization und schränke die verfügbaren Tools nach Möglichkeit mit
allowed_tools ein:
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));Entfernte MCP-Server
erhalten nicht automatisch den vollständigen Unterhaltungskontext,
aber sie können alle Daten sehen, die das Modell in einem Tool-Aufruf sendet.
Beschränke die verfügbaren Tools mit allowed_tools
und verlange eine Genehmigung für jede Aktion, die du nicht automatisch ausführen würdest.
MCP-Ablauf in Realtime
Anders als Realtime-Tools vom Typ function werden entfernte MCP-Tools von der Realtime API selbst ausgeführt. Dein Client führt das entfernte Tool nicht aus und gibt auch kein function_call_output zurück. Stattdessen konfiguriert dein Client den Zugriff, wartet auf Ereignisse im MCP-Lebenszyklus und sendet gegebenenfalls eine Antwort auf eine Genehmigungsanfrage, wenn der Server sie anfordert.
Ein typischer Ablauf sieht so aus:
- Du sendest
session.updateoderresponse.createmit einem Eintrag intools, dessentypeden Wertmcphat. - Der Server beginnt mit dem Import der Tools und sendet
mcp_list_tools.in_progress. - Solange die Tool-Liste noch geladen wird, kann das Modell kein Tool aufrufen, das noch nicht geladen wurde. Wenn du mit einem Gesprächsschritt warten möchtest, der diese Tools benötigt, warte auf
mcp_list_tools.completed. Das Ereignisconversation.item.done, dessenitem.typeden Wertmcp_list_toolshat, zeigt, welche Tool-Namen tatsächlich importiert wurden. Wenn der Import fehlschlägt, erhältst dumcp_list_tools.failed. - Die nutzende Person spricht oder sendet Text. Daraufhin wird eine Antwort erstellt, entweder durch deinen Client oder automatisch gemäß der Sitzungskonfiguration.
- Wenn das Modell ein MCP-Tool auswählt, erhältst du
response.mcp_call_arguments.deltaundresponse.mcp_call_arguments.done. - Wenn eine Genehmigung erforderlich ist, fügt der Server der Unterhaltung ein Element hinzu, dessen
item.typeden Wertmcp_approval_requesthat. Dein Client muss darauf mit einemmcp_approval_response-Element antworten. - Sobald das Tool ausgeführt wird, erhältst du
response.mcp_call.in_progress. Bei Erfolg erhältst du später ein Ereignisresponse.output_item.done, dessenitem.typeden Wertmcp_callhat. Bei einem Fehler erhältst duresponse.mcp_call.failed. response.donefür eine Antwort kann eintreffen, bevor ihre MCP-Aufrufe abgeschlossen sind. Sobald die Antwort und alle zugehörigen MCP-Aufrufe abgeschlossen sind, sende ein weiteres Ereignisresponse.create, damit das Modell die Ergebnisse verwenden und die Unterhaltung fortsetzen kann. Wiederhole diesen Schritt, wenn das Modell weitere MCP-Aufrufe ausführt. Die Realtime API erstellt diese Folgeantworten nicht automatisch.
Dieser Ereignishandler protokolliert die wichtigsten Ereignisse im MCP-Lebenszyklus. Er verwaltet keine Folgeantworten:
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;
}
});Häufige Fehler
mcp_list_tools.failed: Die Realtime API konnte keine Tools vom entfernten Server oder Konnektor importieren. Prüfeserver_urloderconnector_id, die Authentifizierung, die Verbindung zum Server und alle Tool-Namen, die du inallowed_toolsangegeben hast.response.mcp_call.failed: Das Modell hat ein Tool ausgewählt, aber der Tool-Aufruf wurde nicht abgeschlossen. Prüfe die Ereignisdaten und das späteremcp_call-Element auf MCP-Protokoll-, Ausführungs- oder Übertragungsfehler.mcp_approval_requestohne passendemcp_approval_response: Der Tool-Aufruf kann erst fortgesetzt werden, wenn dein Client ihn ausdrücklich genehmigt oder ablehnt.- Ein Gesprächsschritt beginnt, während
mcp_list_tools.in_progressnoch aktiv ist: Für diesen Gesprächsschritt stehen nur Tools zur Verfügung, die bereits vollständig geladen wurden. - Eine Antwort verwendet
tool_choice: "required", aber derzeit sind keine Tools verfügbar: Das Modell kann kein geeignetes Tool aufrufen. Warte aufmcp_list_tools.completed, stelle sicher, dass mindestens ein Tool importiert wurde, oder verwende für Gesprächsschritte, die kein Tool benötigen, einen anderen Wert fürtool_choice. - Die Validierung der MCP-Tool-Definition schlägt fehl, bevor der Import beginnt. Häufige Ursachen sind ein doppelter
server_label-Wert im selbentools-Array, das gleichzeitige Setzen vonserver_urlundconnector_id, das Weglassen beider Angaben bei der ursprünglichen Anfrage zur Sitzungserstellung, ein ungültigerconnector_id-Wert oder das gleichzeitige Senden vonauthorizationundheaders.Authorization. Sende bei Konnektoren grundsätzlich keinheaders.Authorization.
MCP-Tool-Aufrufe genehmigen oder ablehnen
Wenn ein Tool eine Genehmigung erfordert, fügt die Realtime API ein mcp_approval_request-Element in die Unterhaltung ein. Um fortzufahren, sende ein neues conversation.item.create-Ereignis, bei dem item.type den Wert mcp_approval_response hat.
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));
}Wenn du die Anfrage ablehnst, setze approve auf false und gib optional eine Begründung in reason an.
MCP nur für eine Antwort verwenden
Wenn MCP nur für einen einzelnen Gesprächsschritt verfügbar sein soll, füge dasselbe MCP-Tool-Objekt zu response.tools statt zu session.tools hinzu:
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));Das ist nützlich, wenn nur eine Antwort externen Kontext benötigt oder wenn verschiedene Gesprächsschritte unterschiedliche MCP-Server verwenden sollen.
Eine zuvor definierte Serverkennung wiederverwenden
server_label ist die feste Kennung für eine Tool-Definition in der aktuellen
Realtime-Sitzung. Nachdem du einen Server oder Konnektor einmal mit
server_label sowie server_url oder connector_id definiert hast, genügt es, in späteren Ereignissen vom Typ session.update oder
response.create nur auf denselben server_label-Wert zu verweisen. Die
Realtime API verwendet dann die frühere Definition, ohne dass du
das vollständige Tool-Objekt erneut senden musst.
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));Diese Wiederverwendung ist auf die jeweilige Sitzung beschränkt. Wenn du eine neue Realtime-Sitzung startest, sende die vollständige MCP-Definition erneut, damit der Server seine Tool-Liste importieren kann.