These examples are for manual verification of the cloud sandbox backends that
live under agents.extensions.sandbox.
They intentionally keep the flow simple:
- Build a tiny manifest in memory.
- Create a
SandboxAgentthat inspects that workspace through one shell tool. - Run the agent against E2B, Modal, Daytona, Cloudflare, Runloop, Blaxel, or Vercel.
All of these examples require OPENAI_API_KEY, because they call the model through the normal
Runner path. Each cloud backend also needs its own provider credentials.
Install the repo extra:
uv sync --extra e2bCreate an E2B account, create an API key, and export it as E2B_API_KEY.
The official setup docs are:
Export the required environment variables:
export OPENAI_API_KEY=...
export E2B_API_KEY=...uv run python examples/sandbox/extensions/e2b_runner.py --streamUseful flags:
--sandbox-type e2b_code_interpreter--template <template-name>--timeout 300--pause-on-exit
The example defaults to e2b, which provides a bash-style interface.
Use e2b_code_interpreter for a Jupyter-style interface.
If you want the same explicit session lifecycle shown in
examples/sandbox/basic.py, that example now accepts
--backend modal and reuses the same streamed tool-output flow:
uv run python examples/sandbox/basic.py \
--backend modalThe dedicated script below stays as the smaller extension-specific example.
Install the repo extra:
uv sync --extra modalAuthenticate Modal with either CLI token setup or environment variables. The official references are:
- https://modal.com/docs/reference/cli/token
- https://modal.com/docs/reference/modal.config
- https://modal.com/docs/guide/sandbox
If you want to configure credentials directly from the CLI:
uv run modal token set --token-id <token-id> --token-secret <token-secret>Or export environment variables for the current shell:
export OPENAI_API_KEY=...
export MODAL_TOKEN_ID=...
export MODAL_TOKEN_SECRET=...uv run python examples/sandbox/extensions/modal_runner.py \
--app-name openai-agents-python-sandbox-example \
--streamUseful flags:
--workspace-persistence tar--workspace-persistence snapshot_filesystem--workspace-persistence snapshot_directory--sandbox-create-timeout-s 60--native-cloud-bucket-secret-name my-modal-secret
app_name is required by ModalSandboxClientOptions, so the example makes it
an explicit CLI flag instead of hiding it.
Modal sandboxes also support native cloud bucket mounts through
ModalCloudBucketMountStrategy on S3Mount, R2Mount, and HMAC-authenticated
GCSMount.
For native cloud bucket testing, you can either export raw credential
environment variables or pass --native-cloud-bucket-secret-name to reuse an
existing named Modal Secret instead.
Install the repo extra:
uv sync --extra cloudflareExport the required environment variables:
export OPENAI_API_KEY=...
export CLOUDFLARE_SANDBOX_WORKER_URL=...If your Cloudflare Sandbox Service worker requires bearer auth, also export:
export CLOUDFLARE_SANDBOX_API_KEY=...uv run python examples/sandbox/extensions/cloudflare_runner.py --streamUseful flags:
--stream-- stream model output to the terminal.--demo pty-- run a PTY demo (interactive Python session withtty=true).--skip-snapshot-check-- skip the stop/resume snapshot round-trip verification.--native-cloud-bucket-name <bucket>-- mount an R2/S3 bucket viaCloudflareBucketMountStrategy.--native-cloud-bucket-endpoint-url <url>-- optional S3 endpoint URL.--api-key <key>-- bearer token for the worker (or setCLOUDFLARE_SANDBOX_API_KEY).
Cloudflare sandboxes support native cloud bucket mounts through
CloudflareBucketMountStrategy on S3Mount, R2Mount, and HMAC-authenticated
GCSMount.
Each script asks the model to inspect a small workspace and summarize it. A successful run should:
- Start the chosen cloud sandbox backend.
- Materialize the manifest into the sandbox workspace.
- Call the shell tool at least once.
- Print either streamed text or a final short answer about the workspace.
These examples are not live-validated in CI because they depend on external cloud credentials, but they are shaped so contributors can verify backend behavior locally with one command per provider.
Install the repo extra:
uv sync --extra vercelExport the required environment variables:
export OPENAI_API_KEY=...
export VERCEL_OIDC_TOKEN=...Or use explicit token and scope variables:
export OPENAI_API_KEY=...
export VERCEL_TOKEN=...
export VERCEL_PROJECT_ID=...
export VERCEL_TEAM_ID=...uv run python examples/sandbox/extensions/vercel_runner.py --streamUseful flags:
--demo pty--demo port--demo backend-checks--workspace-persistence tar--workspace-persistence snapshot--runtime node22--timeout-ms 120000
The default Vercel run mirrors the other cloud runners and stays focused on the
standard agent flow. Use --demo for backend-specific checks such as PTY,
resume verification, and exposed-port validation.
Install the repo extra:
uv sync --extra daytonaExport the required environment variables:
export OPENAI_API_KEY=...
export DAYTONA_API_KEY=...uv run python examples/sandbox/extensions/daytona/daytona_runner.py --streamInstall the repo extra:
uv sync --extra runloopSign up for Runloop, no credit card required and $50 in credits @ platform.runloop.ai. Export the required environment variables:
export OPENAI_API_KEY=...
export RUNLOOP_API_KEY=...uv run python examples/sandbox/extensions/runloop/runner.py --streamUseful flags:
--blueprint-name <name>--pause-on-exit--root
Runloop-specific SDK features are also available directly on
RunloopSandboxClientOptions and RunloopSandboxClient.platform. Example:
from agents.extensions.sandbox.runloop import (
RunloopAfterIdle,
RunloopGatewaySpec,
RunloopLaunchParameters,
RunloopMcpSpec,
RunloopSandboxClient,
RunloopSandboxClientOptions,
RunloopTunnelConfig,
)
client = RunloopSandboxClient()
sandbox = await client.create(
options=RunloopSandboxClientOptions(
blueprint_name="python-3-12",
launch_parameters=RunloopLaunchParameters(
network_policy_id="np_123",
resource_size_request="MEDIUM",
after_idle=RunloopAfterIdle(idle_time_seconds=300, on_idle="suspend"),
),
tunnel=RunloopTunnelConfig(auth_mode="authenticated"),
gateways={
"OPENAI_GATEWAY": RunloopGatewaySpec(
gateway="openai",
secret="OPENAI_GATEWAY_SECRET",
)
},
mcp={
"GITHUB_MCP": RunloopMcpSpec(
mcp_config="github-readonly",
secret="GITHUB_MCP_SECRET",
)
},
managed_secrets={"OPENAI_API_KEY": "..."},
metadata={"team": "agents"},
)
)
public_blueprints = await client.platform.blueprints.list_public()
public_benchmarks = await client.platform.benchmarks.list_public()managed_secrets are stored as Runloop account secrets and only secret references
are persisted in session state. The platform facade also exposes Runloop-native
helpers for blueprints, benchmarks, secrets, network policies, and axons.
If you enable --root, Runloop launches the devbox with
launch_parameters.user_parameters={"username":"root","uid":0}. In that mode,
the default home and working directory become /root, so the example also uses
/root as its manifest workspace root. If you configure root launch in your
own code, either rely on that root-mode default or explicitly choose a
manifest.root under /root.
Install the repo extra:
uv sync --extra blaxelCreate a Blaxel account and get an API key. The official docs are:
Export the required environment variables:
export OPENAI_API_KEY=...
export BL_API_KEY=...
export BL_WORKSPACE=...uv run python examples/sandbox/extensions/blaxel_runner.py --streamUseful flags:
--image blaxel/py-app--region us-pdx-1--memory 4096--ttl 1h--pause-on-exit--skip-snapshot-check
The runner also includes standalone demos for individual features. Pass
--demo <name> to run one:
pty-- agent-driven interactive Python session via PTYdrive-- Blaxel Drive mount (persistent storage, requires--drive-name)
Blaxel sandboxes support cloud bucket mounts (S3, R2, GCS) through
BlaxelCloudBucketMountStrategy and persistent drive mounts through
BlaxelDriveMountStrategy. See the
Blaxel Drive docs for details.