# OpenAI Agents

Use Sandbox0 as the backend for OpenAI Agents SDK `SandboxAgent` runs through
the Sandbox0 Python SDK adapter. The adapter maps the OpenAI workspace to
`/workspace` on the sandbox writable rootfs.

<Callout variant="info">
This guide targets the adapter's supported `openai-agents>=0.17.6,<0.18`
range. The Sandbox0 adapter uses RootFS snapshots for durable workspace
references. See OpenAI's [Sandbox Agents guide](https://developers.openai.com/api/docs/guides/agents/sandboxes)
for the SDK's agent, manifest, and run-configuration concepts.
</Callout>

## Requirements

- Python 3.10 or later
- `sandbox0[openai-agents]`
- `SANDBOX0_TOKEN`
- model-provider authentication, normally `OPENAI_API_KEY` when using OpenAI;
  the Sandbox0 token authenticates sandbox operations only
- optional `SANDBOX0_BASE_URL` to override the API endpoint; Sandbox0 Cloud is the default

```bash
pip install "sandbox0[openai-agents]"
```

## Basic Usage

```python
import asyncio

from agents import Runner
from agents.run import RunConfig
from agents.sandbox import SandboxAgent, SandboxRunConfig

from sandbox0_openai_agents import Sandbox0SandboxClient, Sandbox0SandboxClientOptions


async def main() -> None:
    client = Sandbox0SandboxClient()
    agent = SandboxAgent(
        name="sandbox0-demo",
        instructions="Use the sandbox for filesystem and command execution tasks.",
    )

    result = await Runner.run(
        agent,
        "Create hello.txt in the workspace, print it, and summarize what you did.",
        run_config=RunConfig(
            sandbox=SandboxRunConfig(
                client=client,
                options=Sandbox0SandboxClientOptions(template="default"),
            ),
            workflow_name="Sandbox0 OpenAI Agents demo",
        ),
    )
    print(result.final_output)


asyncio.run(main())
```

## Lifecycle And Persistence

For a fresh session, the adapter claims a sandbox and uses its `/workspace`
directory directly. `start()` reconnects to a running sandbox or resumes a
paused one. The adapter's explicit resume call uses filesystem-only resume;
this integration does not implement retained-process memory restoration.
`stop()` attempts a named RootFS snapshot by default and stores its ID in
`Sandbox0SandboxSessionState`. It is a persistence operation and does not pause
or delete the sandbox's compute.

If the original sandbox is unavailable, the adapter can claim a replacement
from `rootfs_snapshot_id`. This creates a new isolated writable rootfs from the
saved workspace state.
Snapshots capture the writable RootFS, not only `/workspace`, and do not
retain processes, memory, or runtime-only mounts. They remain subject to
expiry and retention limits. Snapshot API errors during `stop()` can leave
the state with an older snapshot ID or no snapshot. Verify the saved ID before
depending on it for recovery. If there is no snapshot and the original sandbox
is unavailable, a replacement starts from the template without the old files.

Runner-owned cleanup deletes the sandbox and, by default, the current saved
RootFS snapshot, including one supplied by the caller. Preserve
that snapshot when serialized run state must resume
after cleanup:

```python
options = Sandbox0SandboxClientOptions(
    template="default",
    delete_sandbox_on_delete=True,
    delete_rootfs_snapshot_on_delete=False,
)
```

On a successful new snapshot, `stop()` replaces the state's snapshot ID and
attempts to delete the previous one even when `delete_rootfs_snapshot_on_delete`
is false. That option controls client cleanup, not historical snapshot
retention. Use explicit snapshot management when older restore points must live.

Start directly from a known workspace snapshot:

```python
options = Sandbox0SandboxClientOptions(
    template="default",
    rootfs_snapshot_id="snap_abc123",
    create_rootfs_snapshot_on_stop=False,
    delete_rootfs_snapshot_on_delete=False,
)
```

This borrowed-snapshot example keeps the source snapshot. With snapshot-on-stop
disabled, it does not automatically create a restore point for later changes.

## Options

| Option | Default | Description |
|--------|---------|-------------|
| `template` | `default` | Template used for a fresh or replacement sandbox. |
| `workspace_mount_path` | `/workspace` | Workspace root; must match `Manifest.root`. |
| `rootfs_snapshot_id` | `None` | Named Sandbox0 rootfs snapshot used to initialize a replacement workspace. |
| `sandbox_ttl_sec` | `None` | Optional sandbox TTL. |
| `delete_sandbox_on_delete` | `True` | Delete the sandbox when `client.delete(session)` runs. |
| `delete_rootfs_snapshot_on_delete` | `True` | Delete the current saved snapshot during client cleanup, including a caller-supplied ID. |
| `create_rootfs_snapshot_on_stop` | `True` | Create a best-effort rootfs snapshot during `stop()`. |
| `exposed_ports` | `()` | Port metadata recorded in session state; does not create Sandbox0 public services or previews. |
| `poll_interval_sec` | `0.1` | Poll interval for status and command completion. |
| `start_timeout_sec` | `60.0` | Timeout for sandbox startup and reconnect. |

Adapter file operations use the live sandbox file API, and shell commands run
through a Sandbox0 CMD context with `/workspace` as the working directory.
Generic OpenAI SDK snapshot specs are not accepted; use
`rootfs_snapshot_id` for Sandbox0 workspace persistence.
To publish a listener, configure a [Sandbox Service](/docs/sandbox/services) or
[Private Preview](/docs/sandbox/previews) explicitly. `exposed_ports` alone
does not configure network ingress or return a public URL.

## Next Steps

<CardGroup>
  <Card title="Files" href="/docs/sandbox/files" cta="Continue">
    Use the live sandbox file API while a session is running.
  </Card>

  <Card title="Snapshot And Restore" href="/docs/sandbox/snapshot-restore" cta="Continue">
    Understand rootfs snapshot, restore, claim, and fork semantics.
  </Card>
</CardGroup>
