OpenAI-hosted sandboxes
For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending
.mdto the page URL.
An OpenAI-hosted sandbox gives your agent a Linux workspace with Python, Node.js, and command-line tools. OpenAI provisions and connects it; your application supplies the task and retrieves the results. Choose a self-hosted sandbox when you need your own image, compute, or private network.
For tasks that interact with websites through a browser, see Computer use.
Configure the sandbox
Set environment.type to openai_hosted in your create-session request. Add
only the settings your workload needs. The sandbox's working directory is
/workspace.
Choose the resources and network access your task needs with container_size
and network. If you use an environment template, omitted settings inherit the
template.
Prepare packages and files
Use these settings to make dependencies and inputs available in the sandbox:
packages: Install Python, system, or globalnpmpackages withpython,system, ornpmlists. Pin versions when needed, such aspandas==2.2.3.files: Supply input files by Files API ID or inline base64 content.
Run setup commands
Use setup_commands to run shell commands in order before the agent starts. For
example, [{ "command": "mkdir -p reports" }] creates a directory. Each command
can set its own cwd; the default is /workspace.
Packages and input files are prepared before setup commands run. Use a setup command to check required dependencies or files. A nonzero setup exit status prevents the agent from starting.
Set environment variables
Use env to set string-valued environment variables. Agent-generated code can
read these values.
For secrets, use vault credentials
to keep the real values outside the sandbox. Runtime-reserved names, including
PATH, CODEX_*, and OPENAI_API_KEY, are rejected.
Choose a container size
Set environment.container_size when creating a session to choose the CPU and
memory available to your sandbox. Defaults to medium.
| Size | vCPU | Memory |
|---|---|---|
small |
1 | 1 GB |
medium |
2 | 4 GB |
large |
4 | 16 GB |
For example, include this environment in your
POST /v1/agents/sessions request to select small:
{
"environment": {
"type": "openai_hosted",
"container_size": "small"
}
}
The returned session reports the selected size in environment.container_size.
This setting applies only to OpenAI-hosted sandboxes.
Control network access
network.access |
Behavior |
|---|---|
enabled |
Allow outbound access. This is the default unless you inherit a template policy. |
disabled |
Block outbound access. |
restricted |
Allow only the hosts listed in allowed_domains. |
Restricted mode accepts 1–100 exact host names, such as api.example.com.
Do not include wildcards, protocols, paths, or ports. Subdomains and redirect
destinations need their own entries. Hosted stdio MCP servers currently require
enabled access; see stdio MCP requirements.
Add skills and plugins
Use skills, plugins, and capability_directories to add
skills and
plugins.
Reuse configuration across sessions
Set environment_template_id to reuse saved configuration.
Omitted settings inherit the template. Network overrides cannot broaden its policy.
Templates save configuration, not a running workspace.
Check that setup succeeded
The create-session response means setup has started. To check its status, retrieve
GET /v1/agents/environments/{environment_id} using the session's environment.id.
| Status | What to do |
|---|---|
provisioning |
Wait while setup runs. |
connected |
Setup succeeded. You can add or list live files. |
failed |
Read environment.error in the agent.session.environment.failed event. |
Wait for connected before adding or listing live files.
Files and lifetime
Each session has a separate workspace. Files persist across turns while its
sandbox exists. Files under /workspace/outputs are published as immutable
artifacts when a turn completes; those copies remain downloadable after the
sandbox expires.
Use Files and artifacts for uploads, path rules, live file operations, downloads, and limits. Save outputs you need before deleting the session.
Sandbox expiry
Connected sandboxes receive keep-alives, including between turns. If activity and keep-alives stop for an hour, the sandbox can be deleted. This timeout isn’t configurable.
Delete the session when you're done to request sandbox cleanup. If deletion
returns 409 while setup or execution finishes, wait and retry with a limit on
the number of attempts. Closing an event stream does not cancel the task.
Pricing
OpenAI-hosted sandboxes use standard container rates. Model usage is billed separately at the selected model's API rates.
Example: Create a report
Give the agent a CSV containing 10, 20, and 30. It runs Python to calculate
the sum and writes /workspace/outputs/summary.json.
Set OPENAI_API_KEY in your application terminal using the
quickstart prerequisites.
Keep this key outside the sandbox. Use a version of your
OpenAI SDK that includes the beta Agents API.
Create summary.json
import OpenAI from "openai";
import { agentFileDestination } from "openai/helpers/beta/agents/filesystem";
const client = new OpenAI();
const stream = await client.beta.agents.sessions.create({
agent: { model: "gpt-6-astra" },
environment: {
type: "openai_hosted",
network: { access: "disabled" },
files: [
{
type: "inline",
path: "/workspace/amounts.csv",
data: "YW1vdW50CjEwCjIwCjMwCg==",
},
],
},
input:
"Use Python to sum the amount column in /workspace/amounts.csv. Write a JSON object with the total to /workspace/outputs/summary.json, then read it back to verify it.",
stream: true,
});
stream.withResultCollection();
try {
for await (const event of stream) {
console.log(event);
}
const result = await stream.finalResult();
await client.beta.agents.sessions.artifacts.forResult(result).download({
path: "/workspace/outputs/summary.json",
to: agentFileDestination("summary.json"),
});
} finally {
stream.controller.abort();
}
from openai import OpenAI
client = OpenAI()
stream = client.beta.agents.sessions.create(
agent={"model": "gpt-6-astra"},
environment={
"type": "openai_hosted",
"network": {"access": "disabled"},
"files": [
{
"type": "inline",
"path": "/workspace/amounts.csv",
"data": "YW1vdW50CjEwCjIwCjMwCg==",
}
],
},
input="Use Python to sum the amount column in /workspace/amounts.csv. Write a JSON object with the total to /workspace/outputs/summary.json, then read it back to verify it.",
stream=True,
)
with stream.with_result_collection():
for event in stream:
print(event.model_dump_json())
result = stream.get_final_result()
client.beta.agents.sessions.artifacts.for_result(result).download(
"/workspace/outputs/summary.json", to="summary.json"
)
package main
import (
"context"
"fmt"
"os"
"github.com/openai/openai-go/v3"
)
func main() {
ctx := context.Background()
client := openai.NewClient()
stream := client.Beta.Agents.Sessions.NewStreaming(ctx, openai.BetaAgentSessionNewParams{
Agent: openai.BetaAgentSessionNewParamsAgent{Model: openai.String("gpt-6-astra")},
Environment: openai.EnvironmentParamUnion{OfParamOpenAIHosted: &openai.EnvironmentParamOpenAIHosted{
Network: openai.EnvironmentParamOpenAIHostedNetwork{Access: "disabled"},
Files: []openai.HostedEnvironmentFileParamUnion{{OfParamInline: &openai.HostedEnvironmentFileParamInline{
Path: "/workspace/amounts.csv",
Data: "YW1vdW50CjEwCjIwCjMwCg==",
}}},
}},
Input: openai.BetaAgentSessionNewParamsInputUnion{OfString: openai.String("Use Python to sum the amount column in /workspace/amounts.csv. Write a JSON object with the total to /workspace/outputs/summary.json, then read it back to verify it.")},
})
defer stream.Close()
openai.BetaAgentSessionWithResultCollection(stream)
for stream.Next() {
fmt.Println(stream.Current().RawJSON())
}
result, err := openai.BetaAgentSessionFinalResult(stream)
if err != nil {
panic(err)
}
destination, err := os.Create("summary.json")
if err != nil {
panic(err)
}
defer destination.Close()
_, err = client.Beta.Agents.Sessions.Artifacts.ForResult(result).Download(ctx, "/workspace/outputs/summary.json", destination)
if err != nil {
panic(err)
}
if err := destination.Close(); err != nil {
panic(err)
}
}
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.helpers.beta.agents.AgentArtifactDownloads;
import com.openai.models.beta.agents.EnvironmentParam;
import com.openai.models.beta.agents.HostedEnvironmentFileParam;
import com.openai.models.beta.agents.sessions.SessionCreateParams;
import com.openai.services.beta.agents.AgentTurnResults;
import java.nio.file.Path;
public class HostedReport {
public static void main(String[] args) throws Exception {
var client = OpenAIOkHttpClient.fromEnv();
var params =
SessionCreateParams.builder()
.agent(SessionCreateParams.Agent.builder().model("gpt-6-astra").build())
.environment(
EnvironmentParam.OpenAIHosted.builder()
.network(
EnvironmentParam.OpenAIHosted.Network.builder()
.access(EnvironmentParam.OpenAIHosted.Network.Access.DISABLED)
.build())
.addFile(
HostedEnvironmentFileParam.Inline.builder()
.path("/workspace/amounts.csv")
.data("YW1vdW50CjEwCjIwCjMwCg==")
.build())
.build())
.input(
"Use Python to sum the amount column in /workspace/amounts.csv. Write a JSON object"
+ " with the total to /workspace/outputs/summary.json, then read it back to"
+ " verify it.")
.build();
try (var stream = client.beta().agents().sessions().createStreaming(params)) {
AgentTurnResults.withResultCollection(stream);
stream.stream().forEach(System.out::println);
var result = AgentTurnResults.getFinalResult(stream);
AgentArtifactDownloads.forResult(client.beta().agents().sessions().artifacts(), result)
.download("/workspace/outputs/summary.json", Path.of("summary.json"));
}
}
}
require "openai"
require "json"
require "pathname"
client = OpenAI::Client.new
stream = client.beta.agents.sessions.create_streaming(
agent: { model: "gpt-6-astra" },
environment: {
type: :openai_hosted,
network: { access: :disabled },
files: [
{
type: :inline,
path: "/workspace/amounts.csv",
data: "YW1vdW50CjEwCjIwCjMwCg=="
}
]
},
input: "Use Python to sum the amount column in /workspace/amounts.csv. Write a JSON object with the total to /workspace/outputs/summary.json, then read it back to verify it."
)
begin
stream.with_result_collection
stream.each { |event| puts event.to_json }
result = stream.get_final_result
puts result.output_text
client.beta.agents.sessions.artifacts.for_result(result).download(
path: "/workspace/outputs/summary.json",
to: Pathname("summary.json")
)
ensure
stream.close
end
curl --no-buffer --fail-with-body 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 -d \'{\n "agent": {\n "model": "gpt-6-astra"\n },\n "environment": {\n "type": "openai_hosted",\n "network": {\n "access": "disabled"\n },\n "files": [\n {\n "type": "inline",\n "path": "/workspace/amounts.csv",\n "data": "YW1vdW50CjEwCjIwCjMwCg=="\n }\n ]\n },\n "input": "Use Python to sum the amount column in /workspace/amounts.csv. Write a JSON object with the total to /workspace/outputs/summary.json, then read it back to verify it.",\n "stream": true\n}\'
The base64 value in files contains the CSV input. The code prints session events.
Save session.id from agent.session.created. After agent.session.turn.completed,
list the artifacts, find summary.json,
and download it. Its contents should be:
{ "total": 60 }
A completed turn does not guarantee every tool succeeded. If the task fails or the stream ends before completion, inspect the saved session items. Delete the session when you're done.
Troubleshooting
| Problem | What to check |
|---|---|
| Setup fails | Inspect the environment-failure event and fix the package, input-file, or setup-command error before creating another session. |
| A sandbox request is blocked | Check network and any hosts reached through redirects. |
| A live file operation fails | Confirm the sandbox is connected. If it expired, create a new session and supply the inputs again. |
A status or file-list request returns 5xx |
Retry with increasing delays and a deadline. Keep the request ID if the error persists. |