Wähle die API, die deine Anwendung verwendet. Jede API hat eigene Vorgaben für die Authentifizierung, die Sitzungserstellung und den Austausch von Ereignissen.
Eine GPT-Live-Sitzung von deinem Server aus steuern
Verbinde deinen Anwendungsserver mit einer bestehenden GPT-Live-Sitzung über WebRTC oder SIP, wenn der Server Gesprächsereignisse empfangen, private Werkzeuge ausführen oder das Gespräch aktualisieren muss. Diese zweite Verbindung wird als Sideband-WebSocket bezeichnet. Beide Verbindungen nutzen dieselbe Sitzung, während WebRTC oder SIP die primäre Audioübertragung übernimmt.
Die Sideband-Verbindung überträgt Ereignisse und Befehle. Deine Anwendung übernimmt die Ausführung der Werkzeuge, die Autorisierungsprüfungen und die Geschäftsregeln. Bewahre API-Schlüssel und Zugangsdaten für Werkzeuge auf deinem Server auf.
Entscheiden, ob du eine Sideband-Verbindung brauchst
Verwende in Browseranwendungen den WebRTC-Datenkanal für Untertitel und lokale Aktualisierungen der Benutzeroberfläche. Nutze eine Sideband-Verbindung, wenn Transkripte auf deinem Server verarbeitet werden, etwa für Prüfungen durch Schutzmechanismen, Stimmungsanalysen oder spekulative Werkzeugaufrufe. Dein Server kann Ereignisse empfangen und dieselbe Sitzung direkt steuern, während die Audioübertragung im Browser weiterhin über WebRTC läuft. Beispiele findest du unter Auf Transkriptfragmente reagieren.
Wenn dein Backend bereits die primäre WebSocket-Verbindung verwaltet, empfängt es bereits die Ereignisse der Sitzung und kann Befehle senden.
Die Delegation an Responses funktioniert auch ohne Sideband-Verbindung. Der Browser kann Ereignisse für Funktionsaufrufe aus seinem Datenkanal zur Ausführung an ein authentifiziertes Backend weiterleiten. Von OpenAI gehostete Werkzeuge werden über das Backend ausgeführt, an das delegiert wurde. Dafür benötigt die Anwendung keine eigene Komponente zur Werkzeugausführung.
Mit der bestehenden Sitzung verbinden
-
Speichere die ID der Sitzung, die dein Backend steuern soll. Verwende bei WebRTC
session.idaus der JSON-Antwort aufPOST /v1/live/sessions. Bei SIP musst du zuerst den eingehenden Anruf annehmen. Verwende anschließenddata.session_idaus dem zugehörigen Webhook. Speichere die ID zusammen mit den zugehörigen Datensätzen zur nutzenden Person und zum Gespräch in der Anwendung. -
Öffne von deinem Server aus eine WebSocket-Verbindung zur folgenden URL und setze dabei die gespeicherte ID unverändert ein. Authentifiziere dich mit
Authorization: Bearer $OPENAI_API_KEYund verwende dabei dieselbe Projektauthentifizierung, mit der die Sitzung erstellt oder angenommen wurde. Sende dieselben Verbindungsheader mit, die beim Erstellen der Sitzung erforderlich sind.wss://api.openai.com/v1/live/sessions/{session_id}/attach -
Empfange Ereignisse und sende Befehle über den verbundenen Socket. Die Sitzung läuft bereits. Sende
session.startnicht erneut.
Behandle die Sitzungs-ID als undurchsichtigen Wert. Behalte ihr Präfix bei und verwende sie nur für die Sitzung, für die deine Anwendung eine Zugriffsberechtigung hat. Lies die ID aus der Live-JSON-Antwort aus, nicht aus einem Realtime-Header Location oder dem URL-Parameter call_id.
Ereignisse beobachten und Befehle senden
| Aufgabe | Ereignisse oder Befehle |
|---|---|
| Das Gespräch verfolgen | Empfange Transkriptdeltas der nutzenden Person und des Assistenten, Delegationsereignisse und verschachtelte Responses-Ereignisse. |
| Backend-Konfiguration aktualisieren | Verwende session.update, um unterstützte Einstellungen innerhalb des bestehenden Delegationsmodus zu ändern. Starteinstellungen wie das Frontend-Modell und die Audiokonfiguration bleiben unverändert. |
| Kontext bereitstellen | Verwende session.instructions.append für Anweisungen, session.thinking.append für Kontext, der nicht ausgesprochen wird, und session.commentary.append für Aktualisierungen, die ausgesprochen werden können. |
| Werkzeugergebnisse zurückgeben | Sende bei der Delegation an Responses zuerst response.item.create und dann response.create, um die Arbeit im Backend fortzusetzen. |
| Mikrofoneingabe steuern | Verwende session.input_audio.mute und session.input_audio.unmute. Das Stummschalten der Eingabe stoppt die Ausgabe des Assistenten nicht. |
| Die Sitzung beenden | Sende session.close und warte auf den Empfang von session.closed, bevor du die Verbindung trennst. |
Für Befehle gelten dieselben Validierungs- und Delegationsregeln wie auf der primären Verbindung. Verwende beim Anhängen von Kontext delegation_id: null für allgemeinen Sitzungskontext. Eine ID ungleich null muss eine bestehende Client-Delegation identifizieren. Informationen zur Konfiguration und Funktionsausführung sowie Beispiele zum Anhängen von Kontext findest du unter Delegation und Werkzeuge.
Übertrage bei Browsersitzungen die Mikrofoneingabe und die Lautsprecherausgabe weiterhin über die ausgehandelte WebRTC-Medienspur. Verwende die Sideband-Verbindung für Gesprächsereignisse und die Steuerung. Ein Transkriptereignis oder eine Befehlsbestätigung belegt nicht, dass Audio abgespielt wurde oder die nutzende Person es gehört hat.
Gespiegelte Audiodaten empfangen
Eine Sideband-Verbindung empfängt auch Kopien der nachfolgenden Audioeingabe und -ausgabe, während die primäre Verbindung die Live-Medien überträgt:
| Ereignis | Audiofeld | Zeitangaben |
|---|---|---|
session.input_audio.append | audio | Keine Zeitstempel. |
session.output_audio.delta | delta | start_ms und end_ms beschreiben den Zeitraum der Ausgabe auf der Zeitachse der Sitzung. |
Beide Nutzdaten enthalten Base64-kodierte Mono-Rohdaten im Format PCM16LE mit 24 kHz, unabhängig vom Audioformat des primären Transportwegs. Keines der beiden Ereignisse hat eine event_id. Die gespiegelte Eingabe enthält die empfangenen Audiodaten vor der Stummschaltung der Eingabe. Sie bestätigt nicht, dass das Modell diese Samples verarbeitet hat. Die Zeiträume der gespiegelten Ausgabe können Lücken durch verworfene Frames aufweisen und geben nicht an, wann die anrufende Person das Audio gehört hat.
Dies sind Serverereignisse und keine Berechtigung, Audio über die Sideband-Verbindung zu senden. Sende Mikrofon-Audiodaten über den primären Transportweg. Sende session.input_audio.append nicht über den verbundenen Socket.
Für jede Aktion genau eine Zuständigkeit festlegen
Lege für jede Aktion fest, ob der Browser oder das Backend sie übernimmt. Wenn beide Verbindungen ein Ereignis für einen Funktionsaufruf empfangen, führe die Funktion nur einmal aus. Wende dieselbe Zuständigkeitsregel auf Kontextaktualisierungen und Anfragen zur Fortsetzung der Arbeit im Backend an.
Speichere Transkripte und den Zustand der Werkzeuge in deiner Anwendung. Stelle die Verbindung frühzeitig her, wenn das Backend das Gespräch von Anfang an beobachten muss, und bewahre den zuvor erfassten Verlauf auf. Verlasse dich nicht darauf, dass sich durch das Herstellen der Verbindung frühere Transkripte oder Werkzeugergebnisse rekonstruieren lassen.
Eine Sideband-Verbindung allein verbirgt Sitzungsereignisse nicht vor dem Browser. Bewahre vertrauliche Zugangsdaten für Werkzeuge in deinem Backend auf und triff dort die Autorisierungsentscheidungen. Gib nur den Kontext zurück, der für das Gespräch benötigt wird.
Schutzmechanismen für Gespräche anwenden
Verwende die Verbindung deines Servers, um das Gespräch zu überwachen, Anfragen anhand der Richtlinien deiner Anwendung zu prüfen und einzugreifen, wenn eine Prüfung anschlägt. Eine Sideband-Verbindung gibt deinem Server Zugriff auf Sitzungsereignisse und Befehle. Deine Anwendung führt die Prüfungen aus und setzt deren Ergebnisse durch. Derselbe Ablauf gilt, wenn dein Server bereits die primäre WebSocket-Verbindung verwaltet.
Prüfungen parallel zum Gespräch ausführen
Schutzmechanismen sind ein Anwendungsfall für die Verarbeitung von Transkriptfragmenten direkt beim Eintreffen. Derselbe Datenstrom kann parallel zu diesen Prüfungen eine spekulative Abfrage starten oder die Benutzeroberfläche aktualisieren.
- Transkripte überwachen. Sammle Fragmente aus
session.input_transcript.delta, um Anfragen der nutzenden Person auf Jailbreak-Versuche, vertrauliche Informationen oder Richtlinienverstöße zu prüfen. Verwendesession.output_transcript.delta, um die Sprachausgabe des Assistenten auf unbelegte Behauptungen oder Antworten außerhalb des vorgesehenen Einsatzbereichs deiner Anwendung zu prüfen. Behalte bei jeder Prüfung die Zuordnung zum ausgewerteten Transkript und zur ausgewerteten Anwendungsanfrage bei. - Prüfungen parallel ausführen. Ein schnelles, ressourcenschonendes Modell kann Anfragen auswerten, während das Gespräch weiterläuft. Gib ein kleines strukturiertes Ergebnis wie
{"triggered": true}zurück, auf das deine Anwendung reagieren kann. Halte genehmigungspflichtige Aktionen blockiert, bis ihre Prüfungen bestanden sind. Eine Zeitüberschreitung oder eine fehlgeschlagene Prüfung gilt nicht als Genehmigung. - Betroffene Aktionen blockieren. Wenn eine Prüfung anschlägt, markiere die Anfrage im Anwendungszustand als blockiert. Prüfe diesen Zustand, bevor du ein Werkzeug ausführst oder eine Änderung verbindlich übernimmst. Das gilt auch für bereits eingereihte Arbeit. Eine mündliche Ablehnung verhindert nicht, dass ein Werkzeug ausgeführt wird.
- Zugehörige Arbeit stoppen. Brich von der Anwendung verwaltete Aufträge ab, sofern dein Backend den Abbruch unterstützt, und verwirf verspätete Ergebnisse blockierter oder überholter Anfragen. Stelle bei der Delegation an Responses die Ausführung betroffener benutzerdefinierter Funktionen ein und sende kein
response.create, um blockierte Arbeit fortzusetzen. Dadurch wird weder eine bereits laufende gehostete Antwort abgebrochen noch die Sprachausgabe im Frontend gestoppt. - Protokollieren und umsteuern. Protokolliere die Entscheidung zusammen mit den betroffenen Anfrage- und Delegations-IDs und sende anschließend eine korrigierende Anweisung. Ein Ereignisname wie
guardrail.triggeredgehört zur Telemetrie deiner Anwendung. Er ist kein Ereignis der GPT-Live API.
Unter Transkriptdeltas erfährst du, wie du Fragmente sammelst. Unter Delegation und Werkzeuge erfährst du, wie du sicherstellst, dass Backend-Ergebnisse zur aktuellen Aufgabe passen.
Das Gespräch umlenken
Verwende session.instructions.append, um das Gespräch anhand der Schutzmechanismen zu steuern. Damit kannst du die laufende Sprachausgabe unterbrechen und eine neue Anweisung anwenden. Sende beispielsweise Folgendes, nachdem deine Anwendung eine Anfrage blockiert hat:
export function sendUpdate(connection) {
connection.send({
type: "session.instructions.append",
event_id: "guardrail_block_17",
delegation_id: null,
content:
"Stop speaking immediately. Do not continue or act on the last request. Refuse briefly, then wait.",
});
}Die Anweisung muss von der Anwendung verfasst werden. Übernimm keinen nicht vertrauenswürdigen Text von Nutzenden als Anweisung. Verwende delegation_id: null für diese sitzungsweite Korrektur und beschränke content auf höchstens 500 Token.
Ordne session.instructions.appended über client_event_id deinem Befehl zu. Die Bestätigung trifft nach dem geschätzten Zeitpunkt der Einfügung in den Kontext ein. Sie belegt nicht, dass der Assistent aufgehört hat zu sprechen oder dass die Wiedergabe wartender Audiodaten gestoppt wurde. Korrigierende Anweisungen können Audio, das die nutzende Person bereits gehört hat, nicht zurücknehmen.
Verwende auch für Hinweise, die in einem bestimmten Wortlaut gesprochen werden sollen, Anweisungen. Unter Einen Hinweis ausgeben findest du ein Beispiel und Hinweise zur Wiedergabe.
Wiedergabe bei Bedarf steuern
Teste zunächst korrigierende Anweisungen und das Blockieren von Aktionen. Wenn deine Anwendung auch die Audioausgabe des Modells blockieren muss, steuere die Ausgabe im Client oder im Medienrelay: Schalte die Ausgabe vorübergehend stumm oder verwirf sie, verwirf lokal wartende Audiodaten, sende die korrigierende Anweisung und setze die Wiedergabe gemäß den Wiederaufnahmeregeln deiner Anwendung fort. Entferne veraltete Audiodaten vor der Wiederaufnahme. Ein Sideband allein steuert den Medienpfad nicht, und die Bestätigung einer Anweisung ist kein Signal, die Wiedergabe fortzusetzen.
session.input_audio.mute steuert die Mikrofoneingabe der anrufenden Person. Es schaltet weder die Modellausgabe stumm noch bricht es delegierte Aufgaben ab.
GPT-Live streamt während des Sprechens Transkriptfragmente. Wenn eine Prüfung abgeschlossen sein muss, bevor die nutzende Person das Audio hört, muss deine Anwendung die Audiodaten vor der Wiedergabe puffern und freigeben. Das erhöht die Latenz. Unterdrücktes Audio kann außerdem dazu führen, dass der Gesprächskontext des Modells bereits Inhalte enthält, die die nutzende Person noch nicht gehört hat. Teste deshalb, wie das Gespräch fortgesetzt wird.
Das Eingreifen testen
Teste zulässige und blockierte Anfragen, Fehlalarme, langsame oder fehlgeschlagene Prüfungen, das Auslösen einer Schutzmaßnahme während des Sprechens oder der Ausführung eines Werkzeugs sowie verspätete Ergebnisse abgebrochener Aufgaben. Überprüfe das Blockieren von Aktionen, den Anwendungszustand, korrigierende Sprachausgaben und die tatsächliche Wiedergabe jeweils separat. Wenn du die Ausgabe steuerst, beziehe wartende Audiodaten und die Wiederaufnahme in den Test ein. Verwende das Cookbook zur Evaluierung von Sprachagenten, um Aufgabenerfolg und Antwortzeit bei Sprachausgaben zu vergleichen.
Sauber beenden
Empfange weiterhin Ereignisse, solange das Backend für die Ausführung von Werkzeugen oder die Erfassung der abschließenden Nutzungsdaten zuständig ist. Registriere den Handler für session.closed, bevor du session.close sendest, und halte die WebRTC-Verbindung, den Datenkanal und das Sideband offen, bis ausstehende Aufgaben abgeschlossen sind. Speichere vor dem Aufräumen die abschließenden Nutzungsdaten der Sitzung sowie alle Backend-Nutzungsdaten, die du in Responses-Ereignissen erhältst. Wenn die Verbindung abbricht, bevor das letzte Ereignis eintrifft, vermerke den Abschluss als unvollständig. Den Ablauf zum Beenden findest du unter Sitzungen verwalten.
Die Realtime API ermöglicht es Clients, sich über WebRTC oder SIP direkt mit dem API-Server zu verbinden. Wahrscheinlich möchtest du jedoch die Verwendung von Werkzeugen und andere Geschäftslogik auf deinem Anwendungsserver ausführen, damit diese Logik vertraulich und vom Client unabhängig bleibt.
Halte die Verwendung von Werkzeugen, die Geschäftslogik und andere Details sicher auf der Serverseite, indem du eine Verbindung über einen „Sideband“-Steuerkanal herstellst. Sideband-Optionen sind jetzt sowohl für SIP- als auch für WebRTC-Verbindungen verfügbar.
Bei einer Sideband-Verbindung bestehen zwei aktive Verbindungen zur selben Realtime-Sitzung: eine vom Client der nutzenden Person und eine von deinem Anwendungsserver. Über die Serververbindung kannst du die Sitzung überwachen, Anweisungen aktualisieren und auf Werkzeugaufrufe reagieren.
Mit WebRTC
- Beim Herstellen einer Peer-Verbindung rufst du eine SDP-Antwort von der Realtime API ab, um die Verbindung zu konfigurieren. Wenn du den Beispielcode aus dem WebRTC-Leitfaden verwendet hast, sieht das etwa so aus:
const baseUrl = "https://api.openai.com/v1/realtime/calls";
const sdpResponse = await fetch(baseUrl, {
method: "POST",
body: offer.sdp,
headers: {
Authorization: `Bearer ${EPHEMERAL_KEY}`,
"Content-Type": "application/sdp",
},
});- Die Antwort auf die Fetch-Anfrage enthält einen
Location-Header mit einer eindeutigen Anruf-ID. Mit dieser ID kannst du auf dem Server eine WebSocket-Verbindung zu derselben Realtime-Sitzung herstellen.
// Location: /v1/realtime/calls/rtc_123456
const location = sdpResponse.headers.get("Location");
const callId = location?.split("/").pop();
console.log(callId);- Auf einem Server kannst du dann wie bei einer üblichen WebSocket-Verbindung zur Realtime API auf Ereignisse lauschen und die Sitzung konfigurieren. Verwende dazu diese Anruf-ID mit der URL
wss://api.openai.com/v1/realtime?call_id=rtc_xxxxx, wie unten gezeigt:
import WebSocket from "ws";
const callId = "rtc_u1_9c6574da8b8a41a18da9308f4ad974ce";
// Connect to a WebSocket for the in-progress call
const url = "wss://api.openai.com/v1/realtime?call_id=" + callId;
const ws = new WebSocket(url, {
headers: {
Authorization: "Bearer " + process.env.OPENAI_API_KEY,
},
});
ws.on("open", function open() {
console.log("Connected to server.");
// Send client events over the WebSocket once connected
ws.send(
JSON.stringify({
type: "session.update",
session: {
type: "realtime",
instructions: "Be extra nice today!",
},
})
);
});
// Listen for and parse server events
ws.on("message", function incoming(message) {
console.log(JSON.parse(message.toString()));
});So kannst du Werkzeuge hinzufügen, Sitzungen überwachen und Geschäftslogik auf dem Server ausführen, ohne diese Aktionen auf dem Client konfigurieren zu müssen.
Mit SIP
- Eine Person verbindet sich per Telefon über SIP mit OpenAI.
- OpenAI sendet einen Webhook an die Webhook-URL auf dem Server deiner Anwendung, um deine App über den Zustand der Sitzung zu informieren. Der Webhook sieht etwa so aus:
POST https://my_website.com/webhook_endpoint
user-agent: OpenAI/1.0 (+https://platform.openai.com/docs/webhooks)
content-type: application/json
webhook-id: wh_685342e6c53c8190a1be43f081506c52 # unique id for idempotency
webhook-timestamp: 1750287078 # timestamp of delivery attempt
webhook-signature: v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4= # signature to verify authenticity from OpenAI
{
"object": "event",
"id": "evt_685343a1381c819085d44c354e1b330e",
"type": "realtime.call.incoming",
"created_at": 1750287018, // Unix timestamp
"data": {
"call_id": "some_unique_id",
"sip_headers": [
{ "name": "From", "value": "sip:+142555512112@sip.example.com" },
{ "name": "To", "value": "sip:+18005551212@sip.example.com" },
{ "name": "Call-ID", "value": "03782086-4ce9-44bf-8b0d-4e303d2cc590"}
]
}
}
- Der Anwendungsserver öffnet mit dem im Webhook übermittelten Wert für
call_ideine WebSocket-Verbindung zur Realtime API. Dafür verwendet er eine URL wie diese:wss://api.openai.com/v1/realtime?call_id={callId}. Die WebSocket-Verbindung bleibt für die Dauer des SIP-Anrufs bestehen.
Über die WebSocket-Verbindung kannst du dann Ereignisse senden und empfangen, um den Anruf zu steuern, genau wie bei einer Sitzung, die über eine WebSocket-Verbindung gestartet wurde. Dazu gehören das Überwachen des Anrufs, das dynamische Aktualisieren von Anweisungen und das Reagieren auf Werkzeugaufrufe.