SPB Git

Repository Public

sandboxes.md 38.3 KB 757 lines markdown

1# Sandbox Agents23> For the complete documentation index, see [llms.txt](/llms.txt). Markdown versions of documentation pages are available by appending `.md` to the page URL.45A sandbox gives an agent an isolated, Unix-like execution environment with a6filesystem, shell, installed packages, mounted data, exposed ports, snapshots,7and controlled access to external systems.89Agent workflows get brittle when the model needs that kind of workspace but10only receives prompt context. Large document sets, generated artifacts,11commands, previews, and resumable work all need an environment the agent can12inspect and change.1314Sandbox agents are available in the TypeScript and Python Agents SDKs. They15  are in beta, so API details, defaults, and supported capabilities may change.1617This guide covers sandboxes in the Agents SDK, where your application runs the harness. For an OpenAI-managed harness, use [Agents API: Connect a sandbox](https://developers.openai.com/api/docs/guides/agents-api/environments/self-hosted).1819Use sandboxes when the agent needs to manipulate files, run commands, mount a20data room, produce artifacts, expose a service, or continue stateful work21later.2223The key split is the boundary between the harness and compute. The harness is24the control plane around the model: it owns the agent loop, model calls, tool25routing, handoffs, approvals, tracing, recovery, and run state. Compute is the26sandbox execution plane where model-directed work reads and writes files, runs27commands, installs dependencies, uses mounted storage, exposes ports, and28snapshots state.2930Keeping those boundaries separate lets your application keep sensitive control31plane work in trusted infrastructure while the sandbox stays focused on32provider-specific execution. The sandbox can run code against files with narrow33credentials and mounts; the harness can keep auth, billing, audit logs, human34review, and recovery state outside any one container.35363738  <figure>39    4041![Diagram showing an agent harness running inside sandbox compute with filesystem access and gateway-mediated access to data, APIs, and the web.](<https://developers.openai.com/images/api/agents/harness_with_compute.png>)424344    <figcaption className="mt-3 text-sm text-gray-600 dark:text-gray-400">45      Running the harness inside the sandbox can be convenient for prototypes,46      but it puts orchestration and model-directed execution in the same compute47      boundary.48    </figcaption>49  </figure>5051  <figure>52    5354![Diagram showing an agent harness separate from sandbox compute, where the harness accesses trusted services and the sandbox executes commands against a filesystem.](<https://developers.openai.com/images/api/agents/harness_separate_from_compute.png>)555657    <figcaption className="mt-3 text-sm text-gray-600 dark:text-gray-400">58      The harness can run in your infrastructure while the sandbox handles59      provider-specific, stateful execution.60    </figcaption>61  </figure>62636465## When to use a sandbox6667Use a sandbox when the agent's answer depends on work done in a sandbox68workspace, not just reasoning over prompt context.6970Common pain points include:7172- The task needs a directory of documents, not a single prompt.73- The agent should write files that your application can inspect later.74- The agent needs commands, packages, or scripts to complete the work.75- The workflow produces artifacts such as Markdown, CSV, JSONL, screenshots, or generated websites.76- A service, notebook, or report preview needs to run on an exposed port.77- Work pauses for human review and then resumes in the same workspace.7879If your workflow only needs a short model response and no persistent workspace,80call the [Responses API](https://developers.openai.com/api/reference/responses/overview) directly or use the81basic Agents SDK runtime without a sandbox.8283If shell access is only one occasional tool, start with the hosted shell tool in84[Using tools](https://developers.openai.com/api/docs/guides/tools#usage-in-the-agents-sdk). Use sandbox85agents when workspace isolation, sandbox provider choice, or resumable86filesystem state is part of the product design.8788## What sandboxes add8990`SandboxAgent` is still an `Agent`. It keeps the usual agent surface, including91`instructions`, `prompt`, `tools`, `handoffs`, MCP servers, model settings,92structured output, guardrails, and hooks. What changes is the execution boundary:93the runner prepares the agent against a live sandbox session that owns files,94commands, ports, and provider-specific isolation.9596| Piece              | What it owns                                                     | Design question                                                                                   |97| ------------------ | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |98| `SandboxAgent`     | The agent definition plus sandbox defaults                       | What should this agent do, and which sandbox defaults travel with it?                             |99| `Manifest`         | The fresh-session workspace contract                             | What files, directories, repos, mounts, environment, users, or groups start out in the workspace? |100| Capabilities       | Sandbox-native behavior attached to the agent                    | Which sandbox tools, instructions, or runtime behavior does this agent need?                      |101| Sandbox client     | The provider integration                                         | Where should the live workspace run: Unix-local, Docker, or a hosted provider?                    |102| Sandbox session    | The live execution environment                                   | Where do commands run, files change, ports open, and provider state live?                         |103| Sandbox run config | Per-run sandbox session source, client options, and fresh inputs | Should this run inject, resume, or create the sandbox session?                                    |104| Saved state        | `RunState`, serialized session state, and snapshots              | How should later runs reconnect to work or seed a new workspace?                                  |105106Sandbox-specific defaults belong on `SandboxAgent`. Per-run sandbox-session107choices belong in the run's sandbox configuration.108109Sandbox agents also don't change what a turn means. A turn is still a model110step, not a single shell command or sandbox action. Some work may stay inside111the sandbox execution layer. The agent runtime consumes another turn only when112it needs another model response after sandbox work has happened.113114## Create the workspace115116`Manifest` describes the desired starting contents and layout for a fresh117sandbox workspace. Use it for the files, repos, input artifacts, helper files,118mounts, output directories, and environment setup the agent should see.119120Treat the manifest as a fresh-session contract, not the full source of truth for121every live sandbox. The effective workspace for a run can instead come from a122reused live sandbox session, serialized sandbox session state, or a snapshot123chosen at run time.124125Manifest entry paths are workspace-relative. They can't be absolute paths or126escape the workspace with `..`, which keeps the workspace contract portable127across local, Docker, and hosted clients.128129| Manifest input                                                                 | Use it for                                                                            |130| ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------- |131| `File`, `Dir`                                                                  | Small synthetic inputs, helper files, or output directories.                          |132| Local file or directory                                                        | Host files or directories to materialize into the sandbox.                            |133| Git repo                                                                       | A repository to fetch into the workspace.                                             |134| `S3Mount`, `GCSMount`, `R2Mount`, `AzureBlobMount`, `BoxMount`, `S3FilesMount` | External storage to make available inside the sandbox.                                |135| `environment`                                                                  | Environment variables the sandbox needs when it starts.                               |136| `users` and `groups`                                                           | Sandbox-local OS accounts and groups for providers that support account provisioning. |137138Good manifest design means:139140- Put repos, input artifacts, and output directories in the manifest.141- Put longer task specs and repo-local instructions in workspace files such as `repo/task.md` or `AGENTS.md`.142- Use relative workspace paths in instructions, for example `repo/task.md` or `output/report.md`.143- Keep mounted storage scoped to the inputs the agent should read or write.144- Treat mount entries as ephemeral workspace entries: snapshot and persistence flows skip mounted remote storage instead of copying it into saved workspace contents.145146### Mount files and storage147148Useful data often already lives somewhere else. Instead of pasting large149documents into context, mount them into the sandbox and let the agent work with150files.151152Examples:153154- Mount a due-diligence data room and ask the agent to produce a cited summary.155- Mount a support export and ask the agent to cluster issues into a report.156- Mount generated artifacts so another system can review them.157158Provider integrations expose their own mount helpers, credential handling, and159persistence behavior. Keep the application contract the same: mount only the160inputs the agent should use, tell the agent where to read and write, and check161generated artifacts before using them.162163### Handle secrets and credentials164165Treat sandbox credentials as runtime configuration, not prompt content. The166agent may need access to credentials for package managers, storage mounts, or167provider APIs, but those credentials shouldn't appear in user prompts,168agent instructions, task files, committed manifests, or generated artifacts.169170Use these rules:171172- Prefer provider-native secret systems for hosted sandbox providers.173- Keep cloud storage credentials scoped to the mount or provider option that needs them.174- Use `Manifest.environment` for values the sandbox process needs at startup, and mark sensitive or generated entries as ephemeral when you want to rebuild them instead of persisting them.175- Avoid saving secrets, generated mount config, local tokens, or files that shouldn't survive the run.176- Review artifacts before moving them out of the sandbox, especially when the agent can read private documents or mounted storage.177178The SDK supports manifest environment values and provider-specific mount179credentials. General secret-store integration is provider-specific, so keep this180page focused on the contract: your runtime or sandbox provider should inject181credentials instead of teaching them to the model as instructions.182183## Give the agent capabilities184185Capabilities attach sandbox-native behavior to a `SandboxAgent`. They can shape186the workspace before a run starts, append sandbox-specific instructions, expose187tools that bind to the live sandbox session, and adjust model behavior or input188handling for that agent.189190| Capability                              | Add it when                                                  | Notes                                                                                |191| --------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------ |192| `Shell`                                 | The agent needs shell access.                                | Adds command execution and, when supported by the sandbox client, interactive input. |193| `Filesystem`                            | The agent needs to edit files or inspect local images.       | Adds `apply_patch` and `view_image`; patch paths are workspace-root-relative.        |194| `Skills`                                | You want skill discovery and materialization in the sandbox. | Prefer this over manually mounting `.agents` or `.agents/skills`.                    |195| [`Memory`](#persist-memory-across-runs) | Follow-on runs should read or generate memory artifacts.     | Requires `Shell`; live memory updates also require `Filesystem`.                     |196| `Compaction`                            | Long-running flows need context trimming.                    | Adjusts model behavior and input handling after compaction items.                    |197198By default, a `SandboxAgent` includes filesystem, shell, and compaction199capabilities. If you pass a `capabilities` list, it replaces the default list,200so include any default capabilities the agent still needs.201202Prefer built-in capabilities when they fit. Write a custom capability only when203you need a sandbox-specific tool or instruction surface that the built-ins don't204cover.205206### Load skills207208Some tasks need repeatable instructions, scripts, references, or assets before209the agent starts. Use the `Skills` capability so the agent can discover that210working context during the run.211212Load skills213214```javascript215import {216  Capabilities,217  SandboxAgent,218  gitRepo,219  skills,220} from "@openai/agents/sandbox";221222const agent = new SandboxAgent({223  name: "Tax prep assistant",224  instructions: "Use the mounted skill before preparing the return.",225  capabilities: [226    ...Capabilities.default(),227    skills({228      from: gitRepo({229        repo: "owner/tax-prep-skills",230        ref: "main",231      }),232    }),233  ],234});235```236237```python238from agents.sandbox import SandboxAgent239from agents.sandbox.capabilities import Capabilities, Skills240from agents.sandbox.entries import GitRepo241242agent = SandboxAgent(243    name="Tax prep assistant",244    instructions="Use the mounted skill before preparing the return.",245    capabilities=Capabilities.default()246    + [247        Skills(from_=GitRepo(repo="owner/tax-prep-skills", ref="main")),248    ],249)250```251252253Choose the skill source based on how you want it materialized:254255- Use a lazy local directory source for larger local skill directories when you want the model to discover the index first and load only what it needs.256- Use a local directory source for a small local bundle to stage up front.257- Use a Git repo source when the skills bundle has its own release cadence or many sandboxes use it.258259### Expose previews and ports260261Sometimes the artifact isn't a file; it's a running process. Use an exposed262port when the agent creates a local app, notebook, report server, browser263preview, or other service that you need to inspect outside the sandbox.264265Port setup is provider-specific, but the product contract is the same: the266agent starts the service inside the sandbox, the sandbox client exposes the267port, and your application shares or inspects the resulting preview URL.268269## Run a sandbox agent270271The shortest useful sandbox loop is:2722731. Build a `Manifest` that describes the workspace.2742. Create a `SandboxAgent` with the capabilities the model needs.2753. Choose a sandbox client for the environment where work should run.2764. Run the agent with the per-run sandbox configuration.2775. Inspect, copy, resume, or snapshot the artifacts that matter to your application.278279Start with Unix-local for local development on macOS or Linux. It gives you the280smallest local loop because the runner can create a temporary workspace from the281agent's default manifest and clean it up after the run.282283Run a Unix-local sandbox agent284285```javascript286import { run } from "@openai/agents";287import { Manifest, SandboxAgent, file, shell } from "@openai/agents/sandbox";288import { UnixLocalSandboxClient } from "@openai/agents/sandbox/local";289290const manifest = new Manifest({291  entries: {292    "account_brief.md": file({293      content:294        "# Northwind Health\n\n" +295        "- Segment: Mid-market healthcare analytics provider.\n" +296        "- Renewal date: 2026-04-15.\n",297    }),298    "implementation_risks.md": file({299      content:300        "# Delivery risks\n\n" +301        "- Security questionnaire is not complete.\n" +302        "- Procurement requires final legal language by April 1.\n",303    }),304  },305});306307const agent = new SandboxAgent({308  name: "Renewal Packet Analyst",309  model: "gpt-6-astra",310  instructions:311    "Review the workspace before answering. Keep the response concise, " +312    "business-focused, and cite the file names that support each conclusion.",313  defaultManifest: manifest,314  capabilities: [shell()],315});316317const result = await run(318  agent,319  "Summarize the renewal blockers and recommend the next two actions.",320  {321    sandbox: {322      client: new UnixLocalSandboxClient(),323    },324  }325);326327console.log(result.finalOutput);328```329330```python331import asyncio332333from agents import Runner334from agents.run import RunConfig335from agents.sandbox import Manifest, SandboxAgent, SandboxRunConfig336from agents.sandbox.capabilities import Shell337from agents.sandbox.entries import File338from agents.sandbox.sandboxes.unix_local import UnixLocalSandboxClient339340manifest = Manifest(341    entries={342        "account_brief.md": File(343            content=(344                b"# Northwind Health\n\n"345                b"- Segment: Mid-market healthcare analytics provider.\n"346                b"- Renewal date: 2026-04-15.\n"347            )348        ),349        "implementation_risks.md": File(350            content=(351                b"# Delivery risks\n\n"352                b"- Security questionnaire is not complete.\n"353                b"- Procurement requires final legal language by April 1.\n"354            )355        ),356    }357)358359agent = SandboxAgent(360    name="Renewal Packet Analyst",361    model="gpt-6-astra",362    instructions=(363        "Review the workspace before answering. Keep the response concise, "364        "business-focused, and cite the file names that support each conclusion."365    ),366    default_manifest=manifest,367    capabilities=[Shell()],368)369370371async def main():372    result = await Runner.run(373        agent,374        "Summarize the renewal blockers and recommend the next two actions.",375        run_config=RunConfig(376            sandbox=SandboxRunConfig(client=UnixLocalSandboxClient()),377            workflow_name="Unix-local sandbox review",378        ),379    )380    print(result.final_output)381382383asyncio.run(main())384```385386387For complete local examples, see the TypeScript [sandbox agent quickstart][sdk-js-example-basic] and Python [`unix_local_runner.py`][sdk-example-unix-local-runner].388389### Switch providers390391The provider is part of the run configuration, not the agent definition. Keep392the `SandboxAgent`, manifest, and capabilities stable, then swap the sandbox393client and provider options for the environment you want.394395This example uses Docker for local container isolation. Hosted providers follow396the same pattern with their own client classes and options.397398Switch to Docker399400```javascript401import { run } from "@openai/agents";402import { SandboxAgent } from "@openai/agents/sandbox";403import { DockerSandboxClient } from "@openai/agents/sandbox/local";404405const agent = new SandboxAgent({406  name: "Workspace reviewer",407  model: "gpt-6-astra",408  instructions: "Inspect the sandbox workspace before answering.",409});410411const result = await run(agent, "Inspect the workspace.", {412  sandbox: {413    client: new DockerSandboxClient({414      image: "node:22-bookworm-slim",415    }),416  },417});418419console.log(result.finalOutput);420```421422```python423from docker import from_env as docker_from_env424425from agents import Runner426from agents.run import RunConfig427from agents.sandbox import SandboxRunConfig428from agents.sandbox.config import DEFAULT_PYTHON_SANDBOX_IMAGE429from agents.sandbox.sandboxes.docker import (430    DockerSandboxClient,431    DockerSandboxClientOptions,432)433434docker_run_config = RunConfig(435    sandbox=SandboxRunConfig(436        client=DockerSandboxClient(docker_from_env()),437        options=DockerSandboxClientOptions(image=DEFAULT_PYTHON_SANDBOX_IMAGE),438    ),439    workflow_name="Docker sandbox review",440)441442result = await Runner.run(443    agent,444    "Summarize the renewal blockers and recommend the next two actions.",445    run_config=docker_run_config,446)447```448449450For runnable examples, see the TypeScript [sandbox clients guide][sdk-js-sandbox-clients] and [basic example][sdk-js-example-basic], plus Python [`basic.py`][sdk-example-basic] for provider selection, [`docker_runner.py`][sdk-example-docker-runner] for Docker, and [`main.py`][sdk-example-dataroom-qa] for a data-room flow in the SDK repository.451452### Advanced patterns453454Once the basic loop works, sandboxes become useful for workflows where the455agent needs a sandbox workspace instead of more prompt context. These456examples are workflow patterns, not separate APIs: the same harness can route, pause,457resume, and trace the workflow while each sandbox keeps execution close to the458files, tools, and ports it needs.459460| Example                                                | Description                                                   |461| ------------------------------------------------------ | ------------------------------------------------------------- |462| [Data room Q&A][sdk-example-dataroom-qa]               | Answer questions over a mounted data room.                    |463| [Data room table extraction][sdk-example-dataroom]     | Extract a table from a mounted data room.                     |464| [Repository code review][sdk-example-repo-code-review] | Clone a repo, inspect it, and produce code review artifacts.  |465| [Vision website clone][sdk-example-vision-clone]       | Clone a website using the Vision API and screenshot feedback. |466| [Sandbox resume][sdk-example-sandbox-resume]           | Resume work in a pre-existing sandbox.                        |467468## Resume or seed future work469470Useful agent work often outlives one request. A user reviews an artifact, a471step needs approval, or the next step depends on a later event.472473Keep three state concepts separate:474475| State surface | Restores                                                                                  | Use when                                                                       |476| ------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |477| `RunState`    | Harness-side state such as model items, tool state, approvals, and active agent position. | The runner should carry the workflow forward across pauses.                    |478| Session state | A serialized sandbox session that a client can reconnect to.                              | Your app or job system stores provider session state directly.                 |479| `snapshot`    | Saved workspace contents used to seed a fresh sandbox session.                            | A new run should start from saved files and artifacts, not an empty workspace. |480481In practice, the runner resolves the sandbox session in this order:4824831. If you pass a live sandbox session, the runner reuses that session directly.4842. Otherwise, if the run is resuming from `RunState`, the runner resumes from the stored sandbox session state.4853. Otherwise, if you pass explicit serialized sandbox state, the runner resumes from that state.4864. Otherwise, the runner creates a fresh sandbox session. For that fresh session, it uses the per-run manifest when provided, or the agent's default manifest if not.487488The sandbox resume example serializes the stopped session state, resumes it489through the same client, and then passes the resumed session back into the next490run:491492Serialize and resume sandbox state493494```javascript495import { run } from "@openai/agents";496import { Manifest, SandboxAgent } from "@openai/agents/sandbox";497import { UnixLocalSandboxClient } from "@openai/agents/sandbox/local";498499const manifest = new Manifest();500const client = new UnixLocalSandboxClient({501  snapshot: { type: "local", baseDir: "/tmp/my-sandbox-snapshots" },502});503const agent = new SandboxAgent({504  name: "Workspace builder",505  model: "gpt-6-astra",506  instructions: "Inspect the sandbox workspace before answering.",507});508509const session = await client.create({ manifest });510let conversation = [];511let frozenSessionState;512513try {514  const firstResult = await run(agent, "Build the first version of the app.", {515    maxTurns: 20,516    sandbox: { session },517  });518519  conversation = firstResult.history;520  frozenSessionState = await client.serializeSessionState?.(session.state);521} finally {522  await session.close?.();523}524525if (!frozenSessionState || !client.deserializeSessionState || !client.resume) {526  throw new Error("Sandbox client does not support session resume.");527}528529const resumedSession = await client.resume(530  await client.deserializeSessionState(frozenSessionState)531);532533try {534  conversation.push({535    role: "user",536    content: "Continue from the existing workspace and add tests.",537  });538539  await run(agent, conversation, {540    maxTurns: 20,541    sandbox: { session: resumedSession },542  });543} finally {544  await resumedSession.close?.();545}546```547548```python549async with session:550    first_result = await Runner.run(551        agent,552        "Build the first version of the app.",553        max_turns=20,554        run_config=RunConfig(555            sandbox=SandboxRunConfig(session=session),556            workflow_name="Sandbox resume example",557        ),558    )559560conversation = first_result.to_input_list()561frozen_session_state = client.deserialize_session_state(562    client.serialize_session_state(session.state)563)564565conversation.append(566    {567        "role": "user",568        "content": "Continue from the existing workspace and add tests.",569    }570)571572resumed_session = await client.resume(frozen_session_state)573try:574    async with resumed_session:575        second_result = await Runner.run(576            agent,577            conversation,578            max_turns=20,579            run_config=RunConfig(580                sandbox=SandboxRunConfig(session=resumed_session),581                workflow_name="Sandbox resume example",582            ),583        )584finally:585    await client.delete(resumed_session)586```587588589Fresh-session inputs such as `manifest` and `snapshot` only apply when the590runner creates a new sandbox session. If you inject a live `session`, capability591processing can add compatible non-mount entries, but it can't change root,592environment, users, or groups; remove existing entries; replace entry types; or593add or change mount entries on the already-running sandbox.594595This split lets the harness resume the agent loop while the sandbox provider596restores or recreates the workspace. Current sample code for these paths lives597in the TypeScript [resume session state example][sdk-js-example-resume] and598Python [`main.py`][sdk-example-sandbox-resume] and599[`sandbox_agent_with_remote_snapshot.py`][sdk-example-remote-snapshot].600601## Persist memory across runs602603Sandbox memory lets future sandbox-agent runs learn from prior runs. It's604separate from SDK-managed conversational `Session` memory: sessions preserve605message history, while sandbox memory distills useful lessons from prior606workspace runs into files the agent can read later.607608Use memory when the agent should carry forward user preferences, corrections,609project-specific lessons, or task summaries without replaying every previous610turn. Resume and snapshots preserve workspace state; memory preserves reusable611guidance about work that happened in the workspace.612613Enable sandbox memory614615```javascript616import {617  Manifest,618  SandboxAgent,619  filesystem,620  memory,621  shell,622} from "@openai/agents/sandbox";623624const manifest = new Manifest();625626const agent = new SandboxAgent({627  name: "Memory-enabled reviewer",628  instructions:629    "Inspect the workspace and retain useful lessons for follow-up runs.",630  defaultManifest: manifest,631  capabilities: [memory(), filesystem(), shell()],632});633```634635```python636from agents.sandbox.capabilities import Filesystem, Memory, Shell637638agent = SandboxAgent(639    name="Memory-enabled reviewer",640    instructions="Inspect the workspace and retain useful lessons for follow-up runs.",641    default_manifest=manifest,642    capabilities=[Memory(), Filesystem(), Shell()],643)644```645646647Memory enables both reads and generation by default. Memory reads require shell648access so the agent can search and open memory files. By default, live memory649updates also require filesystem access, so the agent can repair stale memory or650update memory when the user asks.651652Memory reads use progressive disclosure. The SDK injects `memory_summary.md` at653the start of a run, the agent searches `MEMORY.md` when prior work looks654relevant, and it opens rollout summaries only when it needs more detail.655656| Memory mode          | Use it when                                                             |657| -------------------- | ----------------------------------------------------------------------- |658| Default read/write   | The agent should read existing memory and generate new memory.          |659| Read-only memory     | The agent should read memory but not generate new memory after the run. |660| Generate-only memory | The run should generate memory without using existing memory.           |661| Read config          | You need to disable live updates.                                       |662| Generate config      | You need to tune generation, such as the extra prompt.                  |663| Layout config        | Agents need isolated memory layouts in the same sandbox workspace.      |664665By default, memory artifacts live in the sandbox workspace:666667```text668workspace/669  sessions/670    <rollout-id>.jsonl671  memories/672    memory_summary.md673    MEMORY.md674    raw_memories.md675    phase_two_selection.json676    raw_memories/677      <rollout-id>.md678    rollout_summaries/679      <rollout-id>_<slug>.md680    skills/681```682683The runtime appends run segments during the sandbox session. When the session684closes, memory generation first extracts conversation summaries and raw685memories, then consolidates those raw memories into `MEMORY.md` and686`memory_summary.md`. To reuse memory in a later run, preserve the configured687memory directories by keeping the same live sandbox session, resuming from688session state, starting from a snapshot, or mounting persistent storage such as689S3.690691For multi-turn sandbox chats, use a stable SDK session together with the same692live sandbox session. Memory groups runs by the explicit conversation ID, then693the SDK session ID, then the run group ID, and finally a generated per-run ID.694The sandbox session ID identifies the live workspace; it's not the memory695conversation ID.696697For runnable examples, see the TypeScript [memory guide][sdk-js-sandbox-memory],698plus Python [`memory.py`][sdk-example-memory] for a local snapshot flow,699[`memory_s3.py`][sdk-example-memory-s3] for S3-backed memory storage, and700[`memory_multi_agent_multiturn.py`][sdk-example-memory-multi-agent] for separate701memory layouts across agents.702703## Compose sandbox agents704705Sandbox agents compose with the rest of the SDK.706707Use a handoff when a non-sandbox intake agent should delegate only the708workspace-heavy part of a workflow to a sandbox agent. The top-level run709continues, but the sandbox agent becomes the active agent for the next turn.710711Use agents as tools when an outer orchestrator should call one or more sandbox712agents as nested tools. Each sandbox tool-agent can have its own sandbox run713configuration, sandbox client, manifest, and provider options.714715For examples, see [`handoffs.py`][sdk-example-handoffs] and716[`sandbox_agents_as_tools.py`][sdk-example-agents-as-tools].717718## Sandbox providers719720Start with Unix-local for fast local iteration or Docker when you want local721container isolation. Move to a hosted provider when the task needs managed722execution, provider-specific isolation, scaling, previews, storage mounts,723snapshots, or credentials that should live outside your application server.724725Use provider docs for provider-specific setup, credentials, isolation, storage,726previews, and persistence behavior.727728| Provider   | SDK client                | Documentation and examples                                                                                                                                                                                                                                                                                                                                                                                                 |729| ---------- | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |730| Blaxel     | `BlaxelSandboxClient`     | [Sandbox overview](https://docs.blaxel.ai/Sandboxes/Overview)                                                                                                                                                                                                                                                                                                                                                   |731| Cloudflare | `CloudflareSandboxClient` | [Sandbox documentation](https://developers.cloudflare.com/sandbox/)<br />[OpenAI Agents tutorial](https://docs.cloudflare.com/sandbox/tutorials/openai-agents/)<br />[Sandbox Bridge examples](https://github.com/cloudflare/sandbox-sdk/tree/main/bridge/examples)                                                                                                                       |732| Daytona    | `DaytonaSandboxClient`    | [Sandbox documentation](https://www.daytona.io/docs/en/sandboxes/)<br />[OpenAI Agents SDK guide](https://www.daytona.io/docs/en/guides/openai-agents/openai-agents-sdk-with-sandboxes)                                                                                                                                                                                                              |733| Docker     | `DockerSandboxClient`     | [Docker documentation](https://docs.docker.com/)<br />[TypeScript Docker SDK example](https://github.com/openai/openai-agents-js/blob/main/examples/docs/sandbox-agents/docker-client.ts)<br />[Python Docker SDK example](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/docker/docker_runner.py)                                                             |734| E2B        | `E2BSandboxClient`        | [Sandbox documentation](https://e2b.dev/docs)<br />[OpenAI Agents SDK guide](https://e2b.dev/docs/agents/openai-agents-sdk)<br />[Launch blog](https://e2b.dev/blog/e2b-is-now-in-agents-sdk)                                                                                                                                                                                             |735| Modal      | `ModalSandboxClient`      | [Sandbox guide](https://modal.com/docs/guide/sandboxes)<br />[Integration blog](https://modal.com/blog/building-with-modal-and-the-openai-agent-sdk)<br />[Example repo](https://github.com/modal-labs/openai-agents-python-example)<br />[Modal extension reference](https://github.com/modal-labs/openai-agents-python-example?tab=readme-ov-file#modal-extension-reference) |736| Runloop    | `RunloopSandboxClient`    | [Devbox overview](https://docs.runloop.ai/docs/devboxes/overview)<br />[Tunnels](https://docs.runloop.ai/docs/devboxes/tunnels)                                                                                                                                                                                                                                                                      |737| Unix-local | `UnixLocalSandboxClient`  | [TypeScript local SDK example](https://github.com/openai/openai-agents-js/blob/main/examples/docs/sandbox-agents/basic.ts)<br />[Python local SDK example](https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/unix_local_runner.py)                                                                                                                                           |738| Vercel     | `VercelSandboxClient`     | [Sandbox documentation](https://vercel.com/docs/vercel-sandbox)<br />[OpenAI Agents SDK guide](https://vercel.com/kb/guide/building-an-agent-with-openai-agents-sdk-and-vercel-sandbox)<br />[FastAPI template](https://vercel.com/templates/template/openai-agents-sdk-with-fastapi)<br />[Sample app](https://github.com/vercel-labs/openai-agents-fastapi-starter)          |739740[sdk-example-agents-as-tools]: https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/sandbox_agents_as_tools.py741[sdk-example-basic]: https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/basic.py742[sdk-example-dataroom]: https://github.com/openai/openai-agents-python/tree/main/examples/sandbox/tutorials/dataroom_metric_extract743[sdk-example-dataroom-qa]: https://github.com/openai/openai-agents-python/tree/main/examples/sandbox/tutorials/dataroom_qa744[sdk-example-docker-runner]: https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/docker/docker_runner.py745[sdk-example-handoffs]: https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/handoffs.py746[sdk-example-memory]: https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/memory.py747[sdk-example-memory-multi-agent]: https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/memory_multi_agent_multiturn.py748[sdk-example-memory-s3]: https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/memory_s3.py749[sdk-example-remote-snapshot]: https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/sandbox_agent_with_remote_snapshot.py750[sdk-example-repo-code-review]: https://github.com/openai/openai-agents-python/tree/main/examples/sandbox/tutorials/repo_code_review751[sdk-example-sandbox-resume]: https://github.com/openai/openai-agents-python/tree/main/examples/sandbox/tutorials/sandbox_resume752[sdk-example-unix-local-runner]: https://github.com/openai/openai-agents-python/blob/main/examples/sandbox/unix_local_runner.py753[sdk-example-vision-clone]: https://github.com/openai/openai-agents-python/tree/main/examples/sandbox/tutorials/vision_website_clone754[sdk-js-example-basic]: https://github.com/openai/openai-agents-js/blob/main/examples/docs/sandbox-agents/basic.ts755[sdk-js-example-resume]: https://github.com/openai/openai-agents-js/blob/main/examples/docs/sandbox-agents/resume-session-state.ts756[sdk-js-sandbox-clients]: https://openai.github.io/openai-agents-js/guides/sandbox-agents/clients757[sdk-js-sandbox-memory]: https://openai.github.io/openai-agents-js/guides/sandbox-agents/memory
Files main
Menu

Theme