SpyBara
Go Premium

Documentation 2026-10-09 22:57 UTC to 2026-10-10 23:58 UTC

11 files changed +626 −71. View all changes and history on the product overview
2026
Sat 10 23:58 Fri 9 22:57 Thu 8 23:01 Wed 7 23:57 Tue 6 22:58 Mon 5 22:59 Sun 4 22:58 Fri 2 23:58 Thu 1 22:59
Details

220 NotificationChannel: openai.AdminOrganizationProjectSpendAlertNewParamsNotificationChannel{220 NotificationChannel: openai.AdminOrganizationProjectSpendAlertNewParamsNotificationChannel{

221 Recipients: []string{"billing@example.com"},221 Recipients: []string{"billing@example.com"},

222 Type: "email",222 Type: "email",

223 SubjectPrefix: openai.String("[OpenAI spend]"),223 SubjectPrefix: openai.String("OpenAI spend"),

224 },224 },

225 ThresholdAmount: 50000,225 ThresholdAmount: 50000,

226 },226 },

Details

10For tasks that interact with websites through a browser, see10For tasks that interact with websites through a browser, see

11[Computer use](https://developers.openai.com/api/docs/guides/agents-api/tools/computer-use).11[Computer use](https://developers.openai.com/api/docs/guides/agents-api/tools/computer-use).

12 12 

13To prepare the workspace before creating a session, see

14[Pre-warm sandboxes](https://developers.openai.com/api/docs/guides/agents-api/environments/prewarmed).

15 

13## Configure the sandbox16## Configure the sandbox

14 17 

15Set `environment.type` to `openai_hosted` in your create-session request. Add18Set `environment.type` to `openai_hosted` in your create-session request. Add

Details

1# Pre-warm sandboxes

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 

5Pre-warmed environments let you create an OpenAI-hosted sandbox, install packages, load files, and run setup commands before creating an agent session. When a task arrives, attach the prepared environment to a session and start the agent.

6 

7Use pre-warming when low latency is a core requirement. For example, a reporting app can prepare its Python dependencies while a user chooses a dataset, or a coding workflow can prepare its workspace while a user writes a request. Starting setup earlier can reduce how much of that work the user waits for.

8 

9## How it works

10 

11An environment is the workspace where the agent runs tools. A session holds the agent configuration and conversation. Pre-warming lets you prepare the workspace independently, then attach it when you need a session.

12 

13The workflow has three steps:

14 

151. **Create an environment.** Supply the packages, files, and setup commands your task needs.

162. **Wait for readiness.** Retrieve the environment until its status is `ready`, or use a webhook.

173. **Start a session.** Pass the environment ID when creating the session.

18 

19You can also attach an environment while setup is still running. The agent's access to the workspace waits for setup to finish.

20 

21## Pricing

22 

23Pre-warming a sandbox is free, including container usage before attachment. Unattached pre-warmed sandboxes expire after five minutes.

24 

25After you attach a pre-warmed sandbox to a session, standard [container pricing](https://developers.openai.com/api/docs/pricing#container-usage-pricing) applies.

26 

27## Prepare a reporting workspace

28 

29This example installs pandas and loads a small CSV before starting an agent. The agent then uses the prepared workspace to calculate the total.

30 

31The create and attach examples require Python SDK 3.27.0, Node.js SDK 7.31.0, Java SDK 4.79.0, or Ruby SDK 0.102.0 or later. Upgrade your SDK if these methods are unavailable.

32 

33### 1. Create the environment

34 

35Send the workspace configuration to `POST /v1/agents/environments`:

36 

37```javascript

38import OpenAI from "openai";

39 

40const client = new OpenAI();

41const environment = await client.beta.agents.environments.create({

42 environment: {

43 type: "openai_hosted",

44 packages: { python: ["pandas==2.2.3"] },

45 files: [

46 {

47 type: "inline",

48 path: "/workspace/amounts.csv",

49 data: "YW1vdW50CjEwCjIwCjMwCg==",

50 },

51 ],

52 setup_commands: [

53 {

54 command: 'python -c "import pandas; print(pandas.__version__)"',

55 cwd: "/workspace",

56 },

57 ],

58 },

59});

60const environmentId = environment.id;

61console.log(environmentId);

62```

63 

64```python

65from openai import OpenAI

66 

67client = OpenAI()

68environment = client.beta.agents.environments.create(

69 environment={

70 "type": "openai_hosted",

71 "packages": {"python": ["pandas==2.2.3"]},

72 "files": [

73 {

74 "type": "inline",

75 "path": "/workspace/amounts.csv",

76 "data": "YW1vdW50CjEwCjIwCjMwCg==",

77 }

78 ],

79 "setup_commands": [

80 {

81 "command": 'python -c "import pandas; print(pandas.__version__)"',

82 "cwd": "/workspace",

83 }

84 ],

85 }

86)

87environment_id = environment.id

88print(environment_id)

89```

90 

91```java

92import com.openai.client.okhttp.OpenAIOkHttpClient;

93 

94import com.openai.models.beta.agents.HostedEnvironmentFileParam;

95import com.openai.models.beta.agents.SetupCommandParam;

96import com.openai.models.beta.agents.environments.EnvironmentCreateParams;

97 

98var client = OpenAIOkHttpClient.fromEnv();

99var environment =

100 client

101 .beta()

102 .agents()

103 .environments()

104 .create(

105 EnvironmentCreateParams.builder()

106 .environment(

107 EnvironmentCreateParams.Environment.builder()

108 .packages(

109 EnvironmentCreateParams.Environment.Packages.builder()

110 .addPython("pandas==2.2.3")

111 .build())

112 .addFile(

113 HostedEnvironmentFileParam.Inline.builder()

114 .path("/workspace/amounts.csv")

115 .data("YW1vdW50CjEwCjIwCjMwCg==")

116 .build())

117 .addSetupCommand(

118 SetupCommandParam.builder()

119 .command(

120 "python -c \"import pandas; print(pandas.__version__)\"")

121 .cwd("/workspace")

122 .build())

123 .build())

124 .build());

125String environmentId = environment.id();

126System.out.println(environmentId);

127```

128 

129```ruby

130require "openai"

131 

132client = OpenAI::Client.new

133environment = client.beta.agents.environments.create(

134 environment: {

135 type: :openai_hosted,

136 packages: { python: ["pandas==2.2.3"] },

137 files: [

138 {

139 type: :inline,

140 path: "/workspace/amounts.csv",

141 data: "YW1vdW50CjEwCjIwCjMwCg=="

142 }

143 ],

144 setup_commands: [

145 {

146 command: 'python -c "import pandas; print(pandas.__version__)"',

147 cwd: "/workspace"

148 }

149 ]

150 }

151)

152environment_id = environment.id

153puts environment_id

154```

155 

156```bash

157curl https://api.openai.com/v1/agents/environments \\\n -H "OpenAI-Beta: agents=v1" \\\n -H "Authorization: Bearer $OPENAI_API_KEY" \\\n -H "Content-Type: application/json" \\\n -d \'{\n "environment": {\n "type": "openai_hosted",\n "packages": {\n "python": ["pandas==2.2.3"]\n },\n "files": [\n {\n "type": "inline",\n "path": "/workspace/amounts.csv",\n "data": "YW1vdW50CjEwCjIwCjMwCg=="\n }\n ],\n "setup_commands": [\n {\n "command": "python -c \\"import pandas; print(pandas.__version__)\\"",\n "cwd": "/workspace"\n }\n ]\n }\n }\'

158```

159 

160 

161The SDK examples save the returned `id` for the next steps. If you use cURL, save it in a shell variable:

162 

163```bash

164ENVIRONMENT_ID="ccarenv_REPLACE_WITH_RETURNED_ID"

165```

166 

167Set `environment.type` to `openai_hosted` when creating a standalone environment.

168 

169### 2. Check readiness

170 

171Retrieve the environment using the ID saved in step 1:

172 

173```javascript

174const current = await client.beta.agents.environments.retrieve(environmentId);

175console.log(current.status);

176```

177 

178```python

179current = client.beta.agents.environments.retrieve(environment_id)

180print(current.status)

181```

182 

183```go

184current, err := client.Beta.Agents.Environments.Get(context.Background(), environmentID)

185if err != nil {

186 panic(err)

187}

188fmt.Println(current.Status)

189```

190 

191```java

192var current = client.beta().agents().environments().retrieve(environmentId);

193System.out.println(current.status());

194```

195 

196```ruby

197current = client.beta.agents.environments.retrieve(environment_id)

198puts current.status

199```

200 

201```bash

202curl \\\n "https://api.openai.com/v1/agents/environments/$ENVIRONMENT_ID" \\\n -H "OpenAI-Beta: agents=v1" \\\n -H "Authorization: Bearer $OPENAI_API_KEY"

203```

204 

205 

206While setup is running, the status is `pending`. When it becomes `ready`, the workspace is prepared and can be attached to a session.

207 

208Readiness does not mean an agent is connected. The environment can be `ready` before a session exists.

209 

210To avoid polling, subscribe a project webhook endpoint to:

211 

212- `agent.environment.ready`

213- `agent.environment.failed`

214 

215If you attach the environment before setup finishes, follow the session's `agent.session.environment.ready` or `agent.session.environment.failed` events for setup status. Use the response stream from creating the session with `"stream": true`, or open `GET /v1/agents/sessions/{session_id}/events`. See [Session events](https://developers.openai.com/api/docs/guides/agents-api/sessions/events) for streaming details.

216 

217### 3. Attach the environment and run a task

218 

219Create a session with the saved environment ID, an agent, and its first input:

220 

221```javascript

222const stream = await client.beta.agents.sessions.create({

223 agent: { model: "gpt-6-astra" },

224 environment: { type: "openai_hosted", environment_id: environmentId },

225 input:

226 "Use pandas to read /workspace/amounts.csv, calculate the sum of the amount column, and report the total.",

227 stream: true,

228});

229try {

230 for await (const event of stream) {

231 console.log(event);

232 }

233} finally {

234 stream.controller.abort();

235}

236```

237 

238```python

239stream = client.beta.agents.sessions.create(

240 agent={"model": "gpt-6-astra"},

241 environment={"type": "openai_hosted", "environment_id": environment_id},

242 input="Use pandas to read /workspace/amounts.csv, calculate the sum of the amount column, and report the total.",

243 stream=True,

244)

245with stream:

246 for event in stream:

247 print(event.model_dump_json())

248```

249 

250```java

251import com.openai.models.beta.agents.EnvironmentParam;

252 

253import com.openai.models.beta.agents.sessions.SessionCreateParams;

254 

255var params =

256 SessionCreateParams.builder()

257 .agent(SessionCreateParams.Agent.builder().model("gpt-6-astra").build())

258 .environment(

259 EnvironmentParam.OpenAIHosted.builder().environmentId(environmentId).build())

260 .input(

261 "Use pandas to read /workspace/amounts.csv, calculate the sum of the amount column, and report the total.")

262 .build();

263try (var stream = client.beta().agents().sessions().createStreaming(params)) {

264 stream.stream().forEach(System.out::println);

265}

266```

267 

268```ruby

269stream = client.beta.agents.sessions.create_streaming(

270 agent: { model: "gpt-6-astra" },

271 environment: {

272 type: :openai_hosted,

273 environment_id: environment_id

274 },

275 input: "Use pandas to read /workspace/amounts.csv, calculate the sum of the amount column, and report the total."

276)

277begin

278 stream.each { |event| puts event.to_json }

279ensure

280 stream.close

281end

282```

283 

284```bash

285curl --no-buffer https://api.openai.com/v1/agents/sessions \\\n -H "OpenAI-Beta: agents=v1" \\\n -H "Authorization: Bearer $OPENAI_API_KEY" \\\n -H "Content-Type: application/json" \\\n --data-binary @- <<EOF\n{\n "agent": {\n "model": "gpt-6-astra"\n },\n "environment": {\n "type": "openai_hosted",\n "environment_id": "$ENVIRONMENT_ID"\n },\n "input": "Use pandas to read /workspace/amounts.csv, calculate the sum of the amount column, and report the total.",\n "stream": true\n}\nEOF

286```

287 

288 

289## Common errors

290 

291Use the error message and the environment's current status to choose a recovery step.

292 

293A newly created shared environment supports up to 128 attached sessions. Reusing it across sessions is supported; those sessions share the workspace. Older environments can still have a single-session lifecycle.

294 

295| Error or symptom | How to resolve |

296| -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

297| Attaching an expired environment. | Create a new environment and use its new ID. Unused environments expire after approximately five minutes. Retrying an expired ID will not restore its workspace. |

298| `404`: environment not found. | Check the environment ID and use the same organization, project, and creating identity as the creation request. If the environment has expired or is no longer available, create a new one. |

299| `409`: shared environment has reached its session limit. | A shared environment supports up to 128 attached sessions. Reuse an existing session or create another environment for additional sessions. |

300 

301## Use a saved environment template

302 

303If multiple tasks need the same packages and setup, [save an environment configuration as a template](https://developers.openai.com/api/reference/resources/beta/subresources/agents/subresources/environments/subresources/templates/methods/create), then supply its ID when creating each pre-warmed environment:

304 

305```javascript

306import OpenAI from "openai";

307 

308const client = new OpenAI();

309const environment = await client.beta.agents.environments.create({

310 environment: {

311 type: "openai_hosted",

312 environment_template_id: "envtmpl_REPLACE_WITH_TEMPLATE_ID",

313 },

314});

315console.log(environment.id);

316```

317 

318```python

319from openai import OpenAI

320 

321client = OpenAI()

322environment = client.beta.agents.environments.create(

323 environment={

324 "type": "openai_hosted",

325 "environment_template_id": "envtmpl_REPLACE_WITH_TEMPLATE_ID",

326 }

327)

328print(environment.id)

329```

330 

331```java

332import com.openai.client.okhttp.OpenAIOkHttpClient;

333import com.openai.models.beta.agents.environments.EnvironmentCreateParams;

334 

335var client = OpenAIOkHttpClient.fromEnv();

336var environment =

337 client

338 .beta()

339 .agents()

340 .environments()

341 .create(

342 EnvironmentCreateParams.builder()

343 .environment(

344 EnvironmentCreateParams.Environment.builder()

345 .environmentTemplateId("envtmpl_REPLACE_WITH_TEMPLATE_ID")

346 .build())

347 .build());

348System.out.println(environment.id());

349```

350 

351```ruby

352require "openai"

353 

354client = OpenAI::Client.new

355environment = client.beta.agents.environments.create(

356 environment: {

357 type: :openai_hosted,

358 environment_template_id: "envtmpl_REPLACE_WITH_TEMPLATE_ID"

359 }

360)

361puts environment.id

362```

363 

364```bash

365curl https://api.openai.com/v1/agents/environments \\\n -H "OpenAI-Beta: agents=v1" \\\n -H "Authorization: Bearer $OPENAI_API_KEY" \\\n -H "Content-Type: application/json" \\\n -d \'{\n "environment": {\n "type": "openai_hosted",\n "environment_template_id": "envtmpl_REPLACE_WITH_TEMPLATE_ID"\n }\n}\'

366```

367 

368 

369## Prewarm a sandbox for computer use

370 

371For browser tasks, prepare the managed browser and virtual display before the session starts. Include `desktop.enabled` when creating the environment:

372 

373```javascript

374import OpenAI from "openai";

375 

376const client = new OpenAI();

377const environment = await client.beta.agents.environments.create({

378 environment: {

379 type: "openai_hosted",

380 desktop: { enabled: true },

381 },

382});

383console.log(environment.id);

384```

385 

386```python

387from openai import OpenAI

388 

389client = OpenAI()

390environment = client.beta.agents.environments.create(

391 environment={

392 "type": "openai_hosted",

393 "desktop": {"enabled": True},

394 }

395)

396print(environment.id)

397```

398 

399```java

400import com.openai.client.okhttp.OpenAIOkHttpClient;

401import com.openai.models.beta.agents.environments.EnvironmentCreateParams;

402 

403var client = OpenAIOkHttpClient.fromEnv();

404var environment =

405 client

406 .beta()

407 .agents()

408 .environments()

409 .create(

410 EnvironmentCreateParams.builder()

411 .environment(

412 EnvironmentCreateParams.Environment.builder()

413 .desktop(

414 EnvironmentCreateParams.Environment.Desktop.builder()

415 .enabled(true)

416 .build())

417 .build())

418 .build());

419System.out.println(environment.id());

420```

421 

422```ruby

423require "openai"

424 

425client = OpenAI::Client.new

426environment = client.beta.agents.environments.create(

427 environment: {

428 type: :openai_hosted,

429 desktop: { enabled: true }

430 }

431)

432puts environment.id

433```

434 

435```bash

436curl https://api.openai.com/v1/agents/environments \\\n -H "OpenAI-Beta: agents=v1" \\\n -H "Authorization: Bearer $OPENAI_API_KEY" \\\n -H "Content-Type: application/json" \\\n -d \'{\n "environment": {\n "type": "openai_hosted",\n "desktop": {\n "enabled": true\n }\n }\n}\'

437```

438 

439 

440When creating a session, attach the saved environment ID and give the agent the `computer_use` tool. The session uses the environment's saved desktop configuration. See [Computer use](https://developers.openai.com/api/docs/guides/agents-api/tools/computer-use) for tool configuration and browser-origin approvals.

441 

442## List your environments

443 

444Use `GET /v1/agents/environments` to find active environments created by your identity in the current organization and project:

445 

446```javascript

447const environments = await client.beta.agents.environments.list({

448 limit: 20,

449 order: "desc",

450});

451console.log(environments.data);

452```

453 

454```python

455environments = client.beta.agents.environments.list(limit=20, order="desc")

456for item in environments.data:

457 print(item.model_dump_json())

458```

459 

460```java

461import com.openai.models.beta.agents.environments.EnvironmentListParams;

462 

463var environments =

464 client

465 .beta()

466 .agents()

467 .environments()

468 .list(

469 EnvironmentListParams.builder()

470 .limit(20L)

471 .order(EnvironmentListParams.Order.DESC)

472 .build());

473System.out.println(environments);

474```

475 

476```ruby

477environments = client.beta.agents.environments.list(

478 limit: 20,

479 order: :desc

480)

481(environments.data || []).each { |item| puts item.to_json }

482```

483 

484```bash

485curl \\\n "https://api.openai.com/v1/agents/environments?limit=20&order=desc" \\\n -H "OpenAI-Beta: agents=v1" \\\n -H "Authorization: Bearer $OPENAI_API_KEY"

486```

487 

488 

489The list includes environments before and after session attachment, with statuses `pending`, `ready`, `connected`, or `disconnected`. It excludes failed, expired, deleted, and terminated environments. An environment appearing in the list may already be attached to one or more sessions.

490 

491Results are newest first by default. If `has_more` is true, set `after` to the previous response's `last_id` to fetch the next page. `limit` accepts 1–100 and defaults to 20; `order` accepts `asc` or `desc`.

492 

493## Lifetime and reuse

494 

495- **Multiple sessions can share one environment.** Pass the same `environment_id` when creating each session. They share the running workspace, including files, processes, installed packages, and environment configuration. Each session keeps its own conversation history. Changes to the workspace are visible to other attached sessions, so create separate environments when tasks need separate workspaces. A shared environment supports up to 128 attached sessions. This behavior applies to newly created standalone environments; older environments retain their original lifecycle.

496- **Unused environments expire.** An environment that remains unattached expires after approximately 5 minutes. Prewarm close to when you expect a task to start.

497- **Keep the creating identity consistent.** Retrieval, listing, and attachment require the same organization, project, and authenticated identity that created the environment. Different API keys for that identity can access the same environments, including after key rotation.

498- **Shared environments expire after inactivity.** The first attachment starts a 20-minute idle lifetime. Activity in any attached session or through the environment file API extends it; pending work and active turns prevent idle expiry. Deleting a session removes that session from the environment without deleting the shared workspace. Even after the last session is deleted, the environment remains available for attachment until its idle deadline. The API has no standalone environment deletion endpoint.

499 

500## Retry creation safely

501 

502When creating an environment, you can send an `Idempotency-Key` header. If the request times out or its response is lost, retry with the **same key and the same request body** to avoid creating an additional environment.

503 

504While the original environment remains available, a completed retry returns its ID with its current state. A retained key can return `409` if creation is still in progress, its outcome is uncertain, the environment is no longer available, or the parameters differ. These conflicts do not create a replacement environment. Keys are retained for 24 hours; after that window, the same key may create a new environment. Use a new key when you intentionally want a new environment.

Details

20 20 

21 21 

22 22 

23This example asks two subagents to review separate release notes, then combines their findings. It needs no environment or configured tools:23This example explicitly requests two subagents in the user input. Each reviews one set of release notes, and the main agent combines their findings. It needs no environment or configured tools:

24 24 

25Compare release notes25Compare release notes

26 26 


38 },38 },

39 environment: { type: "none" },39 environment: { type: "none" },

40 input:40 input:

41 "Release A: Search now supports filtering by date. Existing queries continue to work. Release B: The export endpoint now returns a download URL instead of file bytes. Update clients to fetch that URL.",41 "Use two subagents, one for each release, and combine their findings into a labeled summary. Release A: Search now supports filtering by date. Existing queries continue to work. Release B: The export endpoint now returns a download URL instead of file bytes. Update clients to fetch that URL.",

42 stream: true,42 stream: true,

43});43});

44events.withResultCollection();44events.withResultCollection();


64 "multi_agent": {"enabled": True, "max_concurrent_subagents": 2},64 "multi_agent": {"enabled": True, "max_concurrent_subagents": 2},

65 },65 },

66 environment={"type": "none"},66 environment={"type": "none"},

67 input="Release A: Search now supports filtering by date. Existing queries continue to work. Release B: The export endpoint now returns a download URL instead of file bytes. Update clients to fetch that URL.",67 input="Use two subagents, one for each release, and combine their findings into a labeled summary. Release A: Search now supports filtering by date. Existing queries continue to work. Release B: The export endpoint now returns a download URL instead of file bytes. Update clients to fetch that URL.",

68 stream=True,68 stream=True,

69).with_result_collection() as stream:69).with_result_collection() as stream:

70 for event in stream:70 for event in stream:


87 MultiAgent: openai.MultiAgentConfigParam{Enabled: true,87 MultiAgent: openai.MultiAgentConfigParam{Enabled: true,

88 MaxConcurrentSubagents: openai.Int(2)}},88 MaxConcurrentSubagents: openai.Int(2)}},

89 Environment: openai.EnvironmentParamUnion{OfParamNone: &openai.EnvironmentParamNone{}},89 Environment: openai.EnvironmentParamUnion{OfParamNone: &openai.EnvironmentParamNone{}},

90 Input: openai.BetaAgentSessionNewParamsInputUnion{OfString: openai.String("Release A: Search now supports filtering by date. Existing queries continue to work. Release B: The export endpoint now returns a download URL instead of file bytes. Update clients to fetch that URL.")}})90 Input: openai.BetaAgentSessionNewParamsInputUnion{OfString: openai.String("Use two subagents, one for each release, and combine their findings into a labeled summary. Release A: Search now supports filtering by date. Existing queries continue to work. Release B: The export endpoint now returns a download URL instead of file bytes. Update clients to fetch that URL.")}})

91defer events.Close()91defer events.Close()

92openai.BetaAgentSessionWithResultCollection(events)92openai.BetaAgentSessionWithResultCollection(events)

93for events.Next() {93for events.Next() {


132 .build())132 .build())

133 .environmentNone()133 .environmentNone()

134 .input(134 .input(

135 "Release A: Search now supports filtering by date. Existing queries"135 "Use two subagents, one for each release, and combine their findings into"

136 + " a labeled summary. Release A: Search now supports filtering by date."

137 + " Existing queries"

136 + " continue to work. Release B: The export endpoint now returns a"138 + " continue to work. Release B: The export endpoint now returns a"

137 + " download URL instead of file bytes. Update clients to fetch that"139 + " download URL instead of file bytes. Update clients to fetch that"

138 + " URL.")140 + " URL.")


159 }161 }

160 },162 },

161 environment: { type: "none" },163 environment: { type: "none" },

162 input: "Release A: Search now supports filtering by date. Existing queries continue to work. Release B: The export endpoint now returns a download URL instead of file bytes. Update clients to fetch that URL."164 input: "Use two subagents, one for each release, and combine their findings into a labeled summary. Release A: Search now supports filtering by date. Existing queries continue to work. Release B: The export endpoint now returns a download URL instead of file bytes. Update clients to fetch that URL."

163)165)

164begin166begin

165 events.with_result_collection167 events.with_result_collection


183 "multi_agent": { "enabled": true, "max_concurrent_subagents": 2 }185 "multi_agent": { "enabled": true, "max_concurrent_subagents": 2 }

184 },186 },

185 "environment": { "type": "none" },187 "environment": { "type": "none" },

186 "input": "Release A: Search now supports filtering by date. Existing queries continue to work. Release B: The export endpoint now returns a download URL instead of file bytes. Update clients to fetch that URL.",188 "input": "Use two subagents, one for each release, and combine their findings into a labeled summary. Release A: Search now supports filtering by date. Existing queries continue to work. Release B: The export endpoint now returns a download URL instead of file bytes. Update clients to fetch that URL.",

187 "stream": true189 "stream": true

188 }'190 }'

189```191```

Details

263 263 

264## Inspect turns and identify delegated commands264## Inspect turns and identify delegated commands

265 265 

266Session turns are available through the public API. Use the `turn_id` from a command item with your saved session ID. The cURL example requires `jq`:266Session turns are available through the public API. Use the `turn_id` from a command item with your saved session ID. The Go example searches root-agent and subagent turns with native SDK pagination, then retrieves the matching turn from its owning agent. Replace the illustrative IDs with IDs from your session. The cURL example requires `jq`:

267 267 

268Identify delegated command execution268Identify delegated command execution

269 269 


300```300```

301 301 

302```go302```go

303// Replace the illustrative IDs and URLs below with your own resource values.303// Replace the illustrative session and turn IDs with values from your command item.

304import (304import (

305 "context"305 "context"

306 "fmt"306 "fmt"


310 310 

311ctx := context.Background()311ctx := context.Background()

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

313result, err := client.Beta.Agents.Sessions.Turns.List(ctx,313turn, err := findTurn(ctx, &client, "sess_123", "turn_123")

314 "sess_123",

315 openai.BetaAgentSessionTurnListParams{

316 Limit: openai.Int(20),

317 Order: "desc",

318 })

319if err != nil {314if err != nil {

320 panic(err)315 panic(err)

321}316}

322fmt.Println(result.Data)317if turn.SubagentID == "" {

323turn, err := client.Beta.Agents.Sessions.Turns.Get(ctx,318 fmt.Println("main agent")

324 "sess_123",319} else {

325 "turn_123")320 fmt.Println(turn.SubagentID)

326if err != nil {321}

327 panic(err)322 

323// findTurn discovers the owning agent using native SDK pagination.

324func findTurn(ctx context.Context, client *openai.Client, sessionID, turnID string) (*openai.Turn, error) {

325 turns := client.Beta.Agents.Sessions.Turns.ListAutoPaging(ctx, sessionID,

326 openai.BetaAgentSessionTurnListParams{Limit: openai.Int(100)})

327 for turns.Next() {

328 if turns.Current().ID == turnID {

329 return client.Beta.Agents.Sessions.Turns.Get(ctx, sessionID, turnID)

330 }

331 }

332 if err := turns.Err(); err != nil {

333 return nil, err

334 }

335 subagents := client.Beta.Agents.Sessions.Subagents.ListAutoPaging(ctx, sessionID,

336 openai.BetaAgentSessionSubagentListParams{Limit: openai.Int(100)})

337 for subagents.Next() {

338 subagent := subagents.Current()

339 childTurns := client.Beta.Agents.Sessions.Subagents.Turns.ListAutoPaging(ctx, sessionID, subagent.ID,

340 openai.BetaAgentSessionSubagentTurnListParams{Limit: openai.Int(100)})

341 for childTurns.Next() {

342 if childTurns.Current().ID == turnID {

343 return client.Beta.Agents.Sessions.Subagents.Turns.Get(ctx, sessionID, subagent.ID, turnID)

344 }

345 }

346 if err := childTurns.Err(); err != nil {

347 return nil, err

348 }

349 }

350 if err := subagents.Err(); err != nil {

351 return nil, err

352 }

353 return nil, fmt.Errorf("turn %s not found in session %s", turnID, sessionID)

328}354}

329fmt.Println(turn.SubagentID)

330```355```

331 356 

332```java357```java


390```415```

391 416 

392 417 

393Use the returned `last_id` as the next page's `after` value when `has_more` is `true`.418For manual pagination, use the returned `last_id` as the next page's `after` value when `has_more` is `true`. The Go example follows these pages automatically.

394 419 

395Command items contain `turn_id`. Retrieve that turn and read `subagent_id` to identify the delegated agent that ran the command. A `null` subagent ID identifies root-agent work. Command-output truncation is not reported.420Command items contain `turn_id`. Retrieve that turn and read `subagent_id` to identify the delegated agent that ran the command. A `null` subagent ID identifies root-agent work. Command-output truncation is not reported.

396 421 

Details

1801The Ruby sample uses `gem install openai async-websocket`.1801The Ruby sample uses `gem install openai async-websocket`.

1802 1802 

1803For Go, run `go get github.com/openai/openai-go/v3@v3.73.0`.1803For Go, run `go get github.com/openai/openai-go/v3@v3.73.0`.

1804For Java, add the Maven dependency `com.openai:openai-java:4.78.0`.1804For Java, add the Maven dependency `com.openai:openai-java:4.79.0`.

1805These Go and Java SDK versions provide native Responses WebSocket support.1805These Go and Java SDK versions provide native Responses WebSocket support.

1806 1806 

1807Start a Responses API WebSocket session1807Start a Responses API WebSocket session

Details

102```102```

103 103 

104```go104```go

105response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{105response, err := client.Responses.New(ctx, responses.ResponseNewParams{

106 Model: "gpt-6-astra",106 Model: "gpt-6-astra",

107 Input: responses.ResponseNewParamsInputUnion{OfString: openai.String(responseInput)},107 Input: responses.ResponseNewParamsInputUnion{OfString: openai.String(responseInput)},

108 Tools: []responses.ToolUnionParam{{OfApplyPatch: &responses.ApplyPatchToolParam{}}},108 Tools: []responses.ToolUnionParam{{OfApplyPatch: &responses.ApplyPatchToolParam{}}},

109})109})

110if err != nil {110if err != nil {

111 panic(err)111 return err

112}

113patchCalls := make([]responses.ResponseOutputItemUnion, 0)

114for _, item := range response.Output {

115 if item.Type == "apply_patch_call" {

116 patchCalls = append(patchCalls, item)

117 }

118}112}

119```113```

120 114 


230```224```

231 225 

232```go226```go

233results := make(responses.ResponseInputParam, 0, len(patchCalls))227for turn := 0; ; turn++ {

234for _, call := range patchCalls {228 if response.Status != responses.ResponseStatusCompleted {

235 success, logOutput := applyOperation(call.Operation)229 return fmt.Errorf("response ended with status %s", response.Status)

230 }

231 patchCalls := make([]responses.ResponseOutputItemUnion, 0)

232 for _, item := range response.Output {

233 if item.Type == "apply_patch_call" {

234 patchCalls = append(patchCalls, item)

235 }

236 }

237 if len(patchCalls) == 0 {

238 fmt.Println(response.OutputText())

239 return nil

240 }

241 if turn == 8 {

242 return fmt.Errorf("patch workflow exceeded eight tool turns")

243 }

244 results := make(responses.ResponseInputParam, 0, len(patchCalls))

245 for _, call := range patchCalls {

246 success, logOutput := applyOperation(files, call.Operation)

236 status := "completed"247 status := "completed"

237 if !success {248 if !success {

238 status = "failed"249 status = "failed"


240 result := responses.ResponseInputItemParamOfApplyPatchCallOutput(call.CallID, status)251 result := responses.ResponseInputItemParamOfApplyPatchCallOutput(call.CallID, status)

241 result.OfApplyPatchCallOutput.Output = openai.String(logOutput)252 result.OfApplyPatchCallOutput.Output = openai.String(logOutput)

242 results = append(results, result)253 results = append(results, result)

243}254 }

244_, err = client.Responses.New(context.Background(), responses.ResponseNewParams{255 response, err = client.Responses.New(ctx, responses.ResponseNewParams{

245 Model: "gpt-6-astra",256 Model: "gpt-6-astra",

246 PreviousResponseID: openai.String(response.ID),257 PreviousResponseID: openai.String(response.ID),

247 Input: responses.ResponseNewParamsInputUnion{OfInputItemList: results},258 Input: responses.ResponseNewParamsInputUnion{OfInputItemList: results},

248 Tools: []responses.ToolUnionParam{{OfApplyPatch: &responses.ApplyPatchToolParam{}}},259 Tools: []responses.ToolUnionParam{{OfApplyPatch: &responses.ApplyPatchToolParam{}}},

249})260 })

250if err != nil {261 if err != nil {

251 panic(err)262 return err

263 }

252}264}

253```265```

254 266 

Details

356```356```

357 357 

358```go358```go

359package main359// The surrounding program prepares an isolated sandbox with the skill files.

360 360client := openai.NewClient()

361import (361tool := responses.ToolUnionParam{OfShell: &responses.FunctionShellToolParam{Environment: responses.FunctionShellToolEnvironmentUnionParam{OfLocal: &responses.LocalEnvironmentParam{Skills: []responses.LocalSkillParam{{Name: "csv-insights", Description: "Summarize CSV files and produce a markdown report.", Path: "/workspace/skills/csv-insights"}}}}}}

362 "context"362params := responses.ResponseNewParams{Model: "gpt-6-astra", Tools: []responses.ToolUnionParam{tool}, Input: responses.ResponseNewParamsInputUnion{OfString: openai.String("Use the csv-insights skill and run locally to summarize /workspace/reports.csv. Read the skill instructions, write /workspace/report.md, and include the total in your final answer.")}}

363 "fmt"363for turn := 0; turn <= 8; turn++ {

364 364 response, err := client.Responses.New(ctx, params)

365 "github.com/openai/openai-go/v3"

366 "github.com/openai/openai-go/v3/responses"

367)

368 

369func main() {

370 client := openai.NewClient()

371 tool := responses.ToolUnionParam{OfShell: &responses.FunctionShellToolParam{

372 Environment: responses.FunctionShellToolEnvironmentUnionParam{OfLocal: &responses.LocalEnvironmentParam{

373 Skills: []responses.LocalSkillParam{{

374 Name: "csv-insights",

375 Description: "Summarize CSV files and produce a markdown report.",

376 Path: "<path-to-skill-folder>",

377 }},

378 }},

379 }}

380 response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{

381 Model: "gpt-6-astra",

382 Tools: []responses.ToolUnionParam{tool},

383 Input: responses.ResponseNewParamsInputUnion{OfString: openai.String("Use the csv-insights skill and run locally to summarize today's CSV reports in this repo.")},

384 })

385 if err != nil {365 if err != nil {

386 panic(err)366 return err

367 }

368 if response.Status != responses.ResponseStatusCompleted {

369 return fmt.Errorf("response ended with status %s", response.Status)

370 }

371 results := responses.ResponseInputParam{}

372 for _, item := range response.Output {

373 if item.Type != "shell_call" {

374 continue

387 }375 }

376 if turn == 8 {

377 return fmt.Errorf("shell workflow exceeded eight tool turns")

378 }

379 result, err := executeShellCall(ctx, name, item.AsShellCall())

380 if err != nil {

381 return err

382 }

383 results = append(results, result)

384 }

385 if len(results) == 0 {

388 fmt.Println(response.OutputText())386 fmt.Println(response.OutputText())

387 // Read the artifact without executing generated code outside the container.

388 report, err := readReport(ctx, name)

389 if err != nil {

390 return fmt.Errorf("read generated report: %w", err)

391 }

392 fmt.Printf("Report:\n%s\n", report)

393 return nil

394 }

395 params.PreviousResponseID = openai.String(response.ID)

396 params.Input = responses.ResponseNewParamsInputUnion{OfInputItemList: results}

389}397}

398return fmt.Errorf("shell workflow exceeded eight turns")

390```399```

391 400 

392```java401```java

Details

17Install the WebSocket dependencies with `pip install "openai[realtime]>=3.8.0"` for Python, `npm install openai@^7.10.0 ws` for JavaScript, or `gem install openai async-websocket` for Ruby.17Install the WebSocket dependencies with `pip install "openai[realtime]>=3.8.0"` for Python, `npm install openai@^7.10.0 ws` for JavaScript, or `gem install openai async-websocket` for Ruby.

18 18 

19For Go, run `go get github.com/openai/openai-go/v3@v3.73.0`.19For Go, run `go get github.com/openai/openai-go/v3@v3.73.0`.

20For Java, add the Maven dependency `com.openai:openai-java:4.78.0`.20For Java, add the Maven dependency `com.openai:openai-java:4.79.0`.

21These Go and Java SDK versions provide native Responses WebSocket support.21These Go and Java SDK versions provide native Responses WebSocket support.

22 22 

23In WebSocket mode, start each turn by sending a `response.create` event from the client. The payload mirrors the normal [Responses create body](https://developers.openai.com/api/reference/resources/responses/methods/create), except that transport-specific fields like `stream` and `background` are not used.23In WebSocket mode, start each turn by sending a `response.create` event from the client. The payload mirrors the normal [Responses create body](https://developers.openai.com/api/reference/resources/responses/methods/create), except that transport-specific fields like `stream` and `background` are not used.

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.79.0</version>176 <version>4.80.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.79.0</version>193 <version>4.80.0</version>

194</dependency>194</dependency>

195```195```

196 196