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.