> ## Documentation Index
> Fetch the complete documentation index at: https://docs.celesto.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Sandbox an OpenAI agent with Celesto or SmolVM

> Give an OpenAI agent its own sandboxed computer. Use a hosted Celesto computer or a local SmolVM as the workspace for a SandboxAgent.

The Celesto SDK ships with two ready-made sandbox providers for the [OpenAI Agents SDK](https://openai.github.io/openai-agents-python/). With one of them plugged in, an OpenAI `SandboxAgent` can read files, run shell commands, and create artifacts in an isolated computer instead of on your laptop or server.

You get to pick where that computer lives:

* **Hosted Celesto computer** for cloud runs you can share, persist, and resume from any machine.
* **Local SmolVM sandbox** for fast, private runs that stay on your own hardware.

Both options expose the exact same OpenAI primitives (`SandboxAgent`, `SandboxRunConfig`, `Runner`), so you can swap providers without changing the rest of your agent code.

## When to use this

Reach for these integrations when you want an OpenAI agent to:

* Run untrusted or model-generated commands without touching your machine.
* Inspect, edit, or build files in a clean, throwaway workspace.
* Pause a session, save it, and resume it later from a different process.

If you only need to call a single shell command from an OpenAI tool, the simpler [function tool example](/smolvm/guides/ai-agent-integration#openai-agents-sdk) on the SmolVM page may be enough.

## Installation

Install the Celesto SDK with the `openai-agents` extra. This pulls in the OpenAI Agents SDK and SmolVM alongside Celesto:

```bash theme={null}
pip install "celesto[openai-agents]"
```

<Note>
  The hosted provider needs a Celesto API key. Set `CELESTO_API_KEY` or pass `api_key=` when you create the client. The SmolVM provider runs locally and does not need an API key.
</Note>

## Hosted Celesto sandboxes

Use `CelestoSandboxClient` when you want OpenAI to spin up a fresh Celesto computer for the agent's session. The client creates the computer on `create()`, runs every shell command and file operation against it, and tears it down on `delete()`.

<Steps>
  <Step title="Import the provider and OpenAI primitives">
    ```python theme={null}
    from agents import Runner
    from agents.run import RunConfig
    from agents.sandbox import SandboxAgent, SandboxRunConfig
    from celesto.integrations.openai_agents import (
        CelestoSandboxClient,
        CelestoSandboxClientOptions,
    )
    ```
  </Step>

  <Step title="Define your SandboxAgent">
    A `SandboxAgent` is an OpenAI agent that always works inside a sandbox you provide.

    ```python theme={null}
    agent = SandboxAgent(
        name="Workspace analyst",
        instructions="Inspect the sandbox workspace before answering.",
    )
    ```
  </Step>

  <Step title="Create a session and run the agent">
    ```python theme={null}
    import asyncio

    async def main():
        client = CelestoSandboxClient()
        session = await client.create(
            options=CelestoSandboxClientOptions(cpus=2, memory=4096),
        )
        try:
            async with session:
                result = await Runner.run(
                    agent,
                    "Run `uname -a` in the sandbox and summarize the result.",
                    run_config=RunConfig(sandbox=SandboxRunConfig(session=session)),
                )
                print(result.final_output)
        finally:
            await client.delete(session)

    asyncio.run(main())
    ```

    <Check>
      The agent prints a one-line summary of `uname -a` output from a fresh Celesto computer.
    </Check>
  </Step>
</Steps>

### Client options

Pass a `CelestoSandboxClientOptions` to control how the computer is created. Every field is optional. Omit a field to inherit the template's default.

<Note>
  CPU and memory must match a named Celesto size. Free and Nano plans use Nano (1 vCPU, 512 MB). Builder and Growth can also use Small (1 vCPU, 1 GB), Standard (2 vCPU, 4 GB), and Large (4 vCPU, 12 GB). See [Choose computer size](/celesto-sdk/features/resources).
</Note>

<ParamField body="template_id" type="string" default="scratch">
  Sandbox template to create the computer from. Defaults to `scratch` (a minimal Ubuntu computer). Pass `coding-agent` when your agent needs common coding tools preinstalled. See [Use a template](/celesto-sdk/computers#use-a-template).
</ParamField>

<ParamField body="template_version" type="string">
  Pin an immutable template version for reproducible runs.
</ParamField>

<ParamField body="cpus" type="integer">
  CPU value from a named size. Use together with the matching `memory` value. Defaults to the template's value.
</ParamField>

<ParamField body="memory" type="integer">
  Memory in MB from a named size. Use together with the matching `cpus` value. Defaults to the template's value.
</ParamField>

<ParamField body="disk_size_mb" type="integer">
  Disk size in MB. Range: 512-20480. Defaults to the template's value.
</ParamField>

<ParamField body="image" type="string">
  Legacy OS image selector. Prefer `template_id` for new code.
</ParamField>

<ParamField body="computer_id" type="string">
  Reuse an existing Celesto computer instead of creating a new one. When set, the session attaches to that computer and starts it if needed.
</ParamField>

<ParamField body="delete_on_close" type="boolean">
  Whether to delete the computer when the session closes. Defaults to `true` if the client created the computer, and `false` if you passed in an existing `computer_id`.
</ParamField>

<Tip>
  Need preinstalled coding tools? Create the session with `options=CelestoSandboxClientOptions(template_id="coding-agent")`.
</Tip>

### Authenticate the client

By default `CelestoSandboxClient` uses your `CELESTO_API_KEY` environment variable. You can also pass credentials directly:

```python theme={null}
from celesto.integrations.openai_agents import CelestoSandboxClient

client = CelestoSandboxClient(api_key="your-api-key")
```

### Resume a session later

Save the session state when your process exits and resume it on the next run. This keeps the same computer attached to the same agent identity:

```python theme={null}
state = session.state.model_dump()
# ... persist `state` to disk or a database

resumed = await client.resume(
    CelestoSandboxClient().deserialize_session_state(state)
)
```

<Tip>
  Use `delete_on_close=False` when you plan to resume. Otherwise the computer is deleted when the original session ends.
</Tip>

## Local SmolVM sandboxes

`SmolVMSandboxClient` runs the agent in a [SmolVM](/smolvm/introduction) on your own machine. It is a drop-in replacement for `CelestoSandboxClient` and uses the same `SandboxAgent`, `SandboxRunConfig`, and `Runner` flow.

```python theme={null}
from agents import Runner
from agents.run import RunConfig
from agents.sandbox import SandboxAgent, SandboxRunConfig
from celesto.integrations.openai_agents import (
    SmolVMSandboxClient,
    SmolVMSandboxClientOptions,
)

agent = SandboxAgent(
    name="Local workspace analyst",
    instructions="Inspect the sandbox workspace before answering.",
)

async def main():
    client = SmolVMSandboxClient()
    session = await client.create(
        options=SmolVMSandboxClientOptions(memory=2048),
    )
    try:
        async with session:
            result = await Runner.run(
                agent,
                "List the files in the workspace and describe them.",
                run_config=RunConfig(sandbox=SandboxRunConfig(session=session)),
            )
            print(result.final_output)
    finally:
        await client.delete(session)
```

### Client options

<ParamField body="os" type="string">
  OS image to boot inside SmolVM (for example, `ubuntu-24.04`). Defaults to SmolVM's default image.
</ParamField>

<ParamField body="backend" type="string">
  Which SmolVM backend to use (such as `firecracker` or `qemu`). Defaults to SmolVM's auto-selected backend for your platform.
</ParamField>

<ParamField body="memory" type="integer">
  Memory in MB for the local sandbox.
</ParamField>

<ParamField body="disk_size" type="integer">
  Disk size in MB for the local sandbox.
</ParamField>

<ParamField body="exposed_ports" type="tuple[int, ...]" default="()">
  Guest ports to expose to your host. Use this when the agent runs a server (for example, a dev server or web app) you want to reach from your machine.
</ParamField>

<ParamField body="vm_id" type="string">
  Reuse an existing SmolVM instead of creating a new one. The session attaches to that VM and starts it if needed.
</ParamField>

<ParamField body="delete_on_close" type="boolean">
  Whether to delete the VM when the session closes. Defaults to `true` if the client created the VM, and `false` if you passed in an existing `vm_id`.
</ParamField>

## Choosing between hosted and local

<CardGroup cols={2}>
  <Card title="Hosted Celesto" icon="cloud">
    Use when you want managed infrastructure, shared computers, longer-lived sessions, or runs that originate from servers without local virtualization.
  </Card>

  <Card title="Local SmolVM" icon="laptop">
    Use when you want fast iteration, private runs, no API key, or development on a single workstation.
  </Card>
</CardGroup>

Both providers implement OpenAI's sandbox session interface, so the rest of your agent code (instructions, tools, runners) stays the same when you switch.

## Common patterns

### Read and write files in the sandbox

`SandboxAgent` operations call `read()` and `write()` on the session. The Celesto and SmolVM providers map those calls to the underlying computer or VM:

```python theme={null}
from pathlib import Path

async with session:
    await session.write(Path("notes/plan.md"), io.BytesIO(b"# Plan\n"))
    handle = await session.read(Path("notes/plan.md"))
    print(handle.read().decode())
```

### Save and restore the workspace

Both providers can snapshot the sandbox workspace as a tarball and rehydrate it later:

```python theme={null}
async with session:
    archive = await session.persist_workspace()
    # store `archive.read()` somewhere durable

# later, in a new session:
async with new_session:
    await new_session.hydrate_workspace(archive)
```

This is useful when you want to keep the agent's working files across runs without keeping the computer alive.

## Troubleshooting

<AccordionGroup>
  <Accordion title="ImportError: OpenAI Agents support is not installed">
    The integration is an optional extra. Install it with `pip install "celesto[openai-agents]"`. This adds the `openai-agents` and `smolvm` packages alongside Celesto.
  </Accordion>

  <Accordion title="The agent can't find files I expected">
    Files written through `session.write()` land inside the sandbox workspace, not on your host. Use `session.read()` or `session.persist_workspace()` to pull them out.
  </Accordion>

  <Accordion title="Commands time out">
    Long-running commands need a longer timeout. Pass `timeout=` when calling sandbox operations, or split the work into shorter steps in the agent's instructions.
  </Accordion>
</AccordionGroup>
