SpyBara
Go Premium

Documentation 2026-09-20 23:58 UTC to 2026-09-21 23:00 UTC

7 files changed +338 −11. View all changes and history on the product overview
2026
Tue 29 22:57 Mon 28 22:57 Sat 26 23:59 Fri 25 23:58 Thu 24 23:58 Wed 23 23:58 Tue 22 23:57 Mon 21 23:00 Sat 19 23:00 Fri 18 22:59 Thu 17 10:04 Wed 16 20:58 Tue 15 22:59 Mon 14 22:58 Sun 13 15:02 Fri 11 20:00 Thu 10 18:01 Wed 9 23:59 Sat 5 17:01 Fri 4 23:59 Thu 3 23:00 Wed 2 22:59
Details

517 {517 {

518 "type": "function",518 "type": "function",

519 "name": "wait_for_tasks",519 "name": "wait_for_tasks",

520 "description": "Wait for selected tasks whose results you need. Pass a nonempty list of distinct task_handles from your earlier lookup_price calls. Results arrive on their original calls; this tool returns status only. Do not wait again for results that have already arrived.",520 "description": "Wait for selected tasks whose results you need. Pass a nonempty list of distinct task_handles from your earlier async tool calls. Results arrive on their original calls; this tool returns status only. Do not wait again for results that have already arrived.",

521 "strict": true,521 "strict": true,

522 "parameters": {522 "parameters": {

523 "type": "object",523 "type": "object",


600 600 

601Set `previous_response_id` to the latest response ID, and include the tools and instructions in the continuation request. Your application can also deliver results as they become available, without a wait call. Only use the wait tool when the model's next step depends on results that haven't arrived.601Set `previous_response_id` to the latest response ID, and include the tools and instructions in the continuation request. Your application can also deliver results as they become available, without a wait call. Only use the wait tool when the model's next step depends on results that haven't arrived.

602 602 

603## Add a tool to ask the user for input

604 

605An async tool can ask the user a question while the model continues independent work. For example, the model can ask who a report is for, gather facts while the user answers, and use the answer to tailor the report.

606 

607Define a function with `async: true` to request missing information or a preference. Your application displays the question, collects the reply, and returns it as the tool result. Its schema and behavior belong to your application. `request_user_input_async` isn't a built-in Responses tool.

608 

609Add this definition to the request's `tools` array alongside `wait_for_tasks`:

610 

611```json

612{

613 "type": "function",

614 "name": "request_user_input_async",

615 "async": true,

616 "description": "Ask the user for missing information or a preference. Choose a fresh task_handle unique within this conversation, including completed tasks. Continue independent work while the answer is pending. Use wait_for_tasks when your next step depends on the answer.",

617 "strict": true,

618 "parameters": {

619 "type": "object",

620 "properties": {

621 "question": { "type": "string" },

622 "task_handle": { "type": "string" }

623 },

624 "required": ["question", "task_handle"],

625 "additionalProperties": false

626 }

627}

628```

629 

630### Display the question

631 

632When the complete call item arrives, register the question's `task_handle` and original `call_id`, then display the question to the user. The following illustrative output item asks about the report's audience:

633 

634```json

635{

636 "type": "function_call",

637 "name": "request_user_input_async",

638 "async": true,

639 "call_id": "call_audience",

640 "arguments": "{\"question\":\"Who is the report for: executives or engineers?\",\"task_handle\":\"report_audience_1\"}"

641}

642```

643 

644Keep the question pending in the same registry used by the wait tool. While the user answers, continue consuming the model's response. Don't complete the tool call with an acknowledgment that you displayed the question; its result is the user's answer.

645 

646### Return the user's answer

647 

648When the user replies, send the answer on the question's original `call_id`. For example, include this output item in the next request's `input` array:

649 

650```json

651[

652 {

653 "type": "function_call_output",

654 "call_id": "call_audience",

655 "output": "{\"task_handle\":\"report_audience_1\",\"answer\":\"Executives\"}"

656 }

657]

658```

659 

660Set `previous_response_id` to the latest response ID, and include the tools and instructions in the continuation request. If the model called `wait_for_tasks` for `report_audience_1`, return the answer before the wait status, as in the [wait tool example](#deliver-results-before-wait-status).

661 

662Async execution doesn't keep a response open until the user replies. Instruct the model to continue independent work and wait before taking a step that requires the answer. If your application supports dismissing or timing out a question, return an explicit no-answer result so the model can decide how to proceed.

663 

603## Compatibility664## Compatibility

604 665 

605Async tool calling is supported by GPT-6 Astra and later models.666Async tool calling is supported by GPT-6 Astra and later models.

Details

399 399 

400 400 

401 401 

402 

403 

404<a id="prewarm-the-cache"></a>

405 

406 

407 

408### Prewarm the cache

409 

410 

411 

412For GPT-5.6 and later, prepare known context ahead of time to reduce time to first token on a subsequent request. For example, an interactive application can prewarm shared instructions, tool definitions, or reference material during startup, before the user asks their first question.

413 

414Set [`prompt_cache_options.prewarm`](https://developers.openai.com/api/reference/resources/responses/methods/create#%28resource%29%20responses%20%3E%20%28method%29%20create%20%3E%20%28params%29%200.non_streaming%20%3E%20%28param%29%20prompt_cache_options%20%3E%20%28schema%29%20%3E%20%28property%29%20prewarm) to `true` in a Responses API request to prepare the prompt cache without generating output. Once it completes, send your actual request with the same prompt prefix and `prewarm` omitted or set to `false`.

415 

416Prewarm the cache

417 

418```json

419{

420 "model": "gpt-5.6",

421 "input": [

422 {

423 "role": "developer",

424 "content": "Your app's shared instructions and reference material..."

425 }

426 ],

427 "prompt_cache_options": {

428 "prewarm": true

429 }

430}

431```

432 

433 

434Send a follow-up request

435 

436```json

437{

438 "model": "gpt-5.6",

439 "input": [

440 {

441 "role": "developer",

442 "content": "Your app's shared instructions and reference material..."

443 },

444 {

445 "role": "user",

446 "content": "The user's question..."

447 }

448 ]

449}

450```

451 

452 

453Note: Tokens written to the cache during a prewarm request are billed at the standard cache-write rate.

454 

455 

456 

457 

458 

402<a id="prompt-cache-key-best-practices"></a>459<a id="prompt-cache-key-best-practices"></a>

403 460 

404<a id="tune-prompt-cache-keys"></a>461<a id="tune-prompt-cache-keys"></a>

guides/realtime-webrtc-warp.md +203 −0 created

Details

1# WebRTC with WARP

2 

3> For the complete documentation index, see [llms.txt](/llms.txt). Markdown versions of documentation pages are available by appending `.md` to the page URL.

4 

5Use [WebRTC Abridged Roundtrip Protocol (WARP)](https://datatracker.ietf.org/doc/draft-uberti-tsvwg-warp/) to reduce the time it takes to start a Realtime API voice session. WARP combines [DTLS 1.3](https://datatracker.ietf.org/doc/html/rfc9147), [SPED](https://datatracker.ietf.org/doc/draft-hancke-webrtc-sped/), [SNAP](https://datatracker.ietf.org/doc/draft-hancke-tsvwg-snap/), and a pre-negotiated data channel to establish the connection with fewer network round trips.

6 

7WARP, SPED, and SNAP are IETF Internet-Drafts, so their specifications and client support may change.

8 

9You can also use these optimizations individually. Enable the features your client supports to reduce connection latency, even when full WARP isn't available. Using all the features together provides the full WARP handshake.

10 

11## Enable WARP in a native client

12 

13Current versions of [`libwebrtc`](https://webrtc.googlesource.com/src/) include the WARP optimizations. If your native client uses a compatible `libwebrtc` build, enable the following field trials:

14 

15```text

16WebRTC-ForceDtls13/Enabled/

17WebRTC-Sctp-Snap/Enabled/

18WebRTC-IceHandshakeDtls/Enabled/

19```

20 

21Some integrations require one combined field-trial string:

22 

23```text

24WebRTC-ForceDtls13/Enabled/WebRTC-Sctp-Snap/Enabled/WebRTC-IceHandshakeDtls/Enabled/

25```

26 

27Initialize the field trials before creating the peer connection factory. For example, a Rust integration can enable all three trials together:

28 

29```rust

30const WARP_FIELD_TRIALS: &str = concat!(

31 "WebRTC-ForceDtls13/Enabled/",

32 "WebRTC-Sctp-Snap/Enabled/",

33 "WebRTC-IceHandshakeDtls/Enabled/",

34);

35 

36webrtc_sys::peer_connection_factory::ffi::initialize_field_trials(

37 WARP_FIELD_TRIALS.to_string(),

38);

39```

40 

41If you use an SDK that wraps `libwebrtc`, such as a native LiveKit SDK, pass the same field-trial string through its WebRTC configuration or initialization options. If the SDK doesn't expose field trials, initialize the underlying `libwebrtc` instance before the SDK creates its peer connection factory, or update to a wrapper that provides this configuration.

42 

43After enabling the trials, create a negotiated data channel with any available ID. When you send the SDP offer to `/v1/realtime/calls`, include the same ID in the `dcid` query parameter.

44 

45## Enable WARP in a browser

46 

47Chrome, Edge, and other Chromium-based browsers bundle `libwebrtc`, but a web page can't configure its field trials. An [origin trial](https://developer.chrome.com/docs/web-platform/origin-trials/) enables an experimental browser feature for a registered website. Check the availability of each WARP feature:

48 

49- **DTLS 1.3:** Chrome supports DTLS 1.3 without an origin trial.

50- **SNAP:** Chrome 151–156 supports SNAP through an origin trial. For Edge, check whether a SNAP origin trial is available for your version and register for an Edge-issued token.

51- **SPED:** No browser origin trial is available. Check back later for SPED support. To use full WARP, the browser must enable SPED by default, or you must control its startup flags and enable the necessary field trials yourself.

52 

53Enabling the SNAP origin trial doesn't enable SPED or full WARP. If your browser doesn't expose SPED, you can still use DTLS 1.3 and the SNAP origin trial to gain the benefits of those individual optimizations.

54 

55Check the origin trials for your browser:

56 

57- [Google Chrome origin trials](https://developer.chrome.com/origintrials/#/trials/active)

58- [Microsoft Edge origin trials](https://developer.microsoft.com/en-us/microsoft-edge/origin-trials/trials)

59 

60To enable the SNAP origin trial:

61 

621. Open your browser's origin trials page and find **WebRTC Data Channel: SCTP Negotiation Acceleration Protocol (SNAP)**.

632. Select **Register** and enter your application's origin, such as `https://example.com`.

643. Add the issued token to your page's `<head>` before the script that creates `RTCPeerConnection`:

65 

66```html

67 <meta http-equiv="origin-trial" content="YOUR_ORIGIN_TRIAL_TOKEN" />

68```

69 

704. Reload the page. In Chrome, open DevTools, select **Application**, and confirm `WebRtcSctpSnap` appears under **Origin Trials**.

71 

72You can also provide the token as an HTTP response header:

73 

74```http

75Origin-Trial: YOUR_ORIGIN_TRIAL_TOKEN

76```

77 

78An origin-trial token applies only to its named feature, issuing browser, and

79 registered origin. A SNAP token doesn't enable SPED, and a Chrome token

80 doesn't enable the trial in Edge. Firefox, Safari, browsers on iOS, and older

81 Chromium builds can support standard WebRTC without supporting full WARP.

82 

83## Connect with the unified interface

84 

85Use the [unified WebRTC connection flow](https://developers.openai.com/api/docs/guides/voice-webrtc?api=realtime#connecting-using-the-unified-interface) for faster Realtime API connections. The browser sends its SDP offer and negotiated data-channel ID to your application server. Your server forwards the same ID in the `dcid` query parameter when it calls `/v1/realtime/calls`.

86 

87### Configure your application server

88 

89This application server supports standard WebRTC and WARP. The comment marked `WARP only` identifies the `dcid` forwarding needed for WARP:

90 

91```javascript

92import express from "express";

93 

94const app = express();

95 

96// Parse raw SDP payloads posted from the browser

97app.use(express.text({ type: ["application/sdp", "text/plain"] }));

98 

99const sessionConfig = JSON.stringify({

100 type: "realtime",

101 model: "gpt-realtime-2.1",

102 audio: { output: { voice: "marin" } },

103});

104 

105// An endpoint which creates a Realtime API session.

106app.post("/session", async (req, res) => {

107 const fd = new FormData();

108 fd.set("sdp", req.body);

109 fd.set("session", sessionConfig);

110 

111 const endpoint = new URL("https://api.openai.com/v1/realtime/calls");

112 

113 // WARP only: forward the negotiated data-channel ID to the Realtime API.

114 if (typeof req.query.dcid === "string") {

115 endpoint.searchParams.set("dcid", req.query.dcid);

116 }

117 

118 try {

119 const r = await fetch(endpoint, {

120 method: "POST",

121 headers: {

122 Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,

123 "OpenAI-Safety-Identifier": "hashed-user-id",

124 },

125 body: fd,

126 });

127 // Send back the SDP we received from the OpenAI REST API

128 const sdp = await r.text();

129 res.send(sdp);

130 } catch (error) {

131 console.error("Token generation error:", error);

132 res.status(500).json({ error: "Failed to generate token" });

133 }

134});

135 

136app.listen(3000);

137```

138 

139 

140### Connect from your browser

141 

142After enabling the optimizations available in your browser, set `useWarp` to `true`. Choose any available data-channel ID and pass the same ID to the server. Comments marked `WARP only` identify the configuration and signaling that aren't needed for standard WebRTC:

143 

144```javascript

145// WARP only: set to true after enabling the supported WARP optimizations.

146const useWarp = false;

147 

148// WARP only: choose any available data-channel ID.

149const dataChannelId = 4;

150 

151// Create a peer connection

152const pc = new RTCPeerConnection();

153 

154// Set up to play remote audio from the model

155audioElement.current = document.createElement("audio");

156audioElement.current.autoplay = true;

157pc.ontrack = (e) => (audioElement.current.srcObject = e.streams[0]);

158 

159// Add local audio track for microphone input in the browser

160const ms = await navigator.mediaDevices.getUserMedia({

161 audio: true,

162});

163pc.addTrack(ms.getTracks()[0]);

164 

165// Set up the event channel using any channel label.

166// WARP only: pre-negotiate the channel using the selected data-channel ID.

167const dc = pc.createDataChannel(

168 "events",

169 useWarp ? { negotiated: true, id: dataChannelId } : undefined,

170);

171 

172// Start the session using the Session Description Protocol (SDP)

173const offer = await pc.createOffer();

174await pc.setLocalDescription(offer);

175 

176const endpoint = new URL("/session", window.location.origin);

177 

178// WARP only: include the matching data-channel ID in the session request.

179if (useWarp) {

180 endpoint.searchParams.set("dcid", String(dataChannelId));

181}

182 

183const sdpResponse = await fetch(endpoint, {

184 method: "POST",

185 body: offer.sdp,

186 headers: {

187 "Content-Type": "application/sdp",

188 },

189});

190 

191const answer = {

192 type: "answer",

193 sdp: await sdpResponse.text(),

194};

195await pc.setRemoteDescription(answer);

196```

197 

198 

199## Use a client without WARP support

200 

201If your WebRTC client doesn't use `libwebrtc`, add the WARP-compatible transport optimizations to your WebRTC stack or use another approach supported by that stack. The relevant specifications are [WARP](https://datatracker.ietf.org/doc/draft-uberti-tsvwg-warp/), [SPED](https://datatracker.ietf.org/doc/draft-hancke-webrtc-sped/), [SNAP](https://datatracker.ietf.org/doc/draft-hancke-tsvwg-snap/), [DTLS 1.3](https://datatracker.ietf.org/doc/html/rfc9147), and [data channel establishment](https://datatracker.ietf.org/doc/html/rfc8832).

202 

203If those optimizations aren't available, use the [unified WebRTC interface](https://developers.openai.com/api/docs/guides/voice-webrtc?api=realtime#connecting-using-the-unified-interface).

Details

54}54}

55```55```

56 56 

57After verifying and acknowledging the webhook, retrieve the alert in your background processing. Replace the illustrative `salert_123` value with `data.id` from the webhook. The event's `id` identifies the webhook event rather than the alert. Use an API key authorized for the same project with the `api.safety.alerts.read` permission:57After verifying and acknowledging the webhook, retrieve the alert in your background processing. Replace the illustrative `alert_0123456789abcdef0123456789abcdef` value with `data.id` from the webhook. The event's `id` identifies the webhook event rather than the alert. Use an API key authorized for the same project with the `api.safety.alerts.read` permission:

58 58 

59```bash59```bash

60curl "https://api.openai.com/v1/safety/alerts/salert_123" \60curl "https://api.openai.com/v1/safety/alerts/alert_0123456789abcdef0123456789abcdef" \

61 -H "Authorization: Bearer ${OPENAI_API_KEY}"61 -H "Authorization: Bearer ${OPENAI_API_KEY}"

62```62```

63 63 


68import OpenAI from "openai";68import OpenAI from "openai";

69 69 

70const client = new OpenAI();70const client = new OpenAI();

71const alertId = "salert_123";71const alertId = "alert_0123456789abcdef0123456789abcdef";

72 72 

73const alert = await client.safety.alerts.retrieve(alertId);73const alert = await client.safety.alerts.retrieve(alertId);

74console.log(alert.error_type, alert.reason, alert.response_id);74console.log(alert.error_type, alert.reason, alert.response_id);


80from openai import OpenAI80from openai import OpenAI

81 81 

82client = OpenAI()82client = OpenAI()

83alert = client.safety.alerts.retrieve("salert_123")83alert = client.safety.alerts.retrieve("alert_0123456789abcdef0123456789abcdef")

84print(alert.error_type, alert.reason)84print(alert.error_type, alert.reason)

85```85```

86 86 


97 97 

98func main() {98func main() {

99 client := openai.NewClient()99 client := openai.NewClient()

100 alert, err := client.Safety.Alerts.Get(context.Background(), "salert_123")100 alert, err := client.Safety.Alerts.Get(context.Background(), "alert_0123456789abcdef0123456789abcdef")

101 if err != nil {101 if err != nil {

102 panic(err)102 panic(err)

103 }103 }


111// Replace the illustrative IDs and URLs below with your own resource values.111// Replace the illustrative IDs and URLs below with your own resource values.

112import com.openai.models.safety.alerts.SafetyAlert;112import com.openai.models.safety.alerts.SafetyAlert;

113 113 

114SafetyAlert alert = client.safety().alerts().retrieve("salert_123");114SafetyAlert alert = client.safety().alerts().retrieve("alert_0123456789abcdef0123456789abcdef");

115System.out.println(alert.errorType());115System.out.println(alert.errorType());

116alert.reason().ifPresent(System.out::println);116alert.reason().ifPresent(System.out::println);

117System.out.println(alert.requestPaused());117System.out.println(alert.requestPaused());


122require "openai"122require "openai"

123 123 

124client = OpenAI::Client.new124client = OpenAI::Client.new

125alert = client.safety.alerts.retrieve("salert_123")125alert = client.safety.alerts.retrieve("alert_0123456789abcdef0123456789abcdef")

126puts(alert.error_type)126puts(alert.error_type)

127puts(alert.reason)127puts(alert.reason)

128puts(alert.request_paused)128puts(alert.request_paused)

Details

392 392 

393## Overview393## Overview

394 394 

395The Realtime API supports two mechanisms for connecting to the Realtime API from the browser, either using ephemeral API keys ([generated via the OpenAI REST API](https://developers.openai.com/api/reference/resources/realtime/subresources/client_secrets)), or via the new unified interface. Generally, using the unified interface is simpler, but puts your application server in the critical path for session initialization.395The Realtime API supports two mechanisms for connecting from the browser: the unified interface and ephemeral API keys ([generated via the OpenAI REST API](https://developers.openai.com/api/reference/resources/realtime/subresources/client_secrets)). Use the unified interface for simpler setup and faster connections. This approach puts your application server in the critical path for session initialization.

396 396 

397### Connecting using the unified interface397### Connecting using the unified interface

398 398 


614```614```

615 615 

616 616 

617## Reduce connection latency with WARP

618 

619WebRTC Abridged Roundtrip Protocol (WARP) reduces the time it takes to start a Realtime API voice session. You can enable its optimizations individually or combine them for the full WARP handshake.

620 

621See [WebRTC with WARP](https://developers.openai.com/api/docs/guides/realtime-webrtc-warp) for native client setup, browser support, origin-trial instructions, and the unified connection flow.

622 

617## Sending and receiving events623## Sending and receiving events

618 624 

619Realtime API sessions are managed using a combination of [client-sent events](https://developers.openai.com/api/reference/resources/realtime/client-events#session.update) emitted by you as the developer, and [server-sent events](https://developers.openai.com/api/reference/resources/realtime/server-events#error) created by the Realtime API to indicate session lifecycle events.625Realtime API sessions are managed using a combination of [client-sent events](https://developers.openai.com/api/reference/resources/realtime/client-events#session.update) emitted by you as the developer, and [server-sent events](https://developers.openai.com/api/reference/resources/realtime/server-events#error) created by the Realtime API to indicate session lifecycle events.

libraries.md +1 −1

Details

173<dependency>173<dependency>

174 <groupId>com.openai</groupId>174 <groupId>com.openai</groupId>

175 <artifactId>openai-java</artifactId>175 <artifactId>openai-java</artifactId>

176 <version>4.65.0</version>176 <version>4.66.0</version>

177</dependency>177</dependency>

178```178```

179 179 

quickstart.md +1 −1

Details

190<dependency>190<dependency>

191 <groupId>com.openai</groupId>191 <groupId>com.openai</groupId>

192 <artifactId>openai-java</artifactId>192 <artifactId>openai-java</artifactId>

193 <version>4.65.0</version>193 <version>4.66.0</version>

194</dependency>194</dependency>

195```195```

196 196