> ## 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.

# Framework Integration

> Wire SmolVM into PydanticAI, the OpenAI Agents SDK, LangChain, and other agent frameworks so AI agents can run untrusted code inside isolated microVMs.

SmolVM gives your AI agents a safe place to run code. Instead of executing LLM-generated commands directly on your machine, SmolVM spins up an isolated microVM in milliseconds, runs the code inside it, and tears it down when finished.

<Info>
  Install the agent framework extras before following these examples:

  ```bash theme={null}
  pip install "smolvm[examples]"
  ```

  This adds PydanticAI, OpenAI Agents SDK, LangChain, and Playwright as dependencies. See [installation](/smolvm/installation) for details.
</Info>

## Agentor

[Agentor](/agentor/home) is Celesto's own agent framework. It has built-in SmolVM support through `SmolVMRuntime`, so your agent's shell commands run inside a sandbox automatically.

```python theme={null}
from agentor import Agentor
from agentor.runtime import SmolVMRuntime
from agentor.tools import ShellTool


def main() -> None:
    runtime = SmolVMRuntime(memory=1024, disk_size=2048)

    try:
        agent = Agentor(
            name="SmolVM Shell Agent",
            model="gpt-5",
            tools=[ShellTool(executor=runtime)],
            instructions="Use shell commands to inspect files inside the SmolVM sandbox.",
        )

        result = agent.run(
            "Install uv and use the Python interpreter to print 'Hello, World!'. Return both outputs."
        )
        print(result)
    finally:
        runtime.close()


if __name__ == "__main__":
    main()
```

<Tip>
  See the full working example in [`main.py`](https://github.com/celestoai/smolvm/blob/main/main.py).
</Tip>

## PydanticAI

Register SmolVM as a [PydanticAI](https://ai.pydantic.dev/) tool. Each call spins up a fresh VM, runs the command, and tears it down automatically.

```python theme={null}
from smolvm import SmolVM
from pydantic_ai import Agent

def run_in_smolvm(command: str, timeout: int = 30) -> str:
    """Run a shell command inside an ephemeral SmolVM sandbox.

    Args:
        command: Shell command to execute inside the sandbox guest.
        timeout: Maximum number of seconds to wait for the command.
    """
    with SmolVM() as vm:
        result = vm.run(command, timeout=timeout)
        return (
            f"exit_code: {result.exit_code}\n"
            f"stdout:\n{result.stdout.strip() or '<empty>'}\n"
            f"stderr:\n{result.stderr.strip() or '<empty>'}"
        )

agent = Agent(
    "openai:gpt-4.1",
    instructions=(
        "You are a coding assistant with access to a secure SmolVM sandbox. "
        "For shell or Python inspection requests, call run_in_smolvm exactly "
        "once and then summarize the result."
    ),
)
agent.tool_plain(docstring_format="google", require_parameter_descriptions=True)(
    run_in_smolvm
)

result = agent.run_sync("Run `uname -a && python3 --version` in the sandbox.")
print(result.output)
```

<Tip>
  See the full working example in [`examples/agent_tools/pydanticai_tool.py`](https://github.com/celestoai/smolvm/blob/main/examples/agent_tools/pydanticai_tool.py).
</Tip>

### Reusable sandbox across turns

If your agent needs to maintain state between tool calls, keep the VM alive across invocations:

```python theme={null}
from dataclasses import dataclass
from pydantic_ai import Agent, RunContext
from smolvm import SmolVM

@dataclass
class SandboxDeps:
    vm_id: str | None = None

def _connect_vm(deps: SandboxDeps) -> SmolVM:
    """Return the active sandbox, creating it on first use."""
    if deps.vm_id is None:
        vm = SmolVM()
        vm.start()
        deps.vm_id = vm.vm_id
        return vm
    return SmolVM.from_id(deps.vm_id)

def _cleanup_vm(vm_id: str | None) -> None:
    """Delete the reusable sandbox if one was created."""
    if vm_id is None:
        return
    vm = SmolVM.from_id(vm_id)
    try:
        vm.delete()
    finally:
        vm.close()

def run_in_reusable_smolvm(
    ctx: RunContext[SandboxDeps], command: str, timeout: int = 30
) -> str:
    """Run a shell command inside a reusable SmolVM sandbox.

    Args:
        command: Shell command to execute inside the sandbox guest.
        timeout: Maximum number of seconds to wait for the command.
    """
    vm = _connect_vm(ctx.deps)
    try:
        result = vm.run(command, timeout=timeout)
        return (
            f"exit_code: {result.exit_code}\n"
            f"stdout:\n{result.stdout.strip() or '<empty>'}\n"
            f"stderr:\n{result.stderr.strip() or '<empty>'}"
        )
    finally:
        vm.close()

agent = Agent(
    "openai:gpt-4.1",
    deps_type=SandboxDeps,
    instructions="You have access to a persistent SmolVM sandbox.",
)
agent.tool(docstring_format="google", require_parameter_descriptions=True)(
    run_in_reusable_smolvm
)

deps = SandboxDeps()
try:
    agent.run_sync("Write 'hello' to /tmp/note.txt", deps=deps)
    agent.run_sync("Read /tmp/note.txt and confirm the contents", deps=deps)
finally:
    _cleanup_vm(deps.vm_id)
```

<Tip>
  See the full working example in [`examples/agent_tools/pydanticai_reusable_tool.py`](https://github.com/celestoai/smolvm/blob/main/examples/agent_tools/pydanticai_reusable_tool.py).
</Tip>

## OpenAI Agents SDK

Use SmolVM as a [function tool](https://openai.github.io/openai-agents-python/) in the OpenAI Agents SDK:

```python theme={null}
import asyncio
from agents import Agent, Runner, function_tool
from smolvm import SmolVM

def run_in_smolvm(command: str, timeout: int = 30) -> str:
    """Run a shell command inside an ephemeral SmolVM sandbox.

    Args:
        command: Shell command to execute inside the sandbox guest.
        timeout: Maximum number of seconds to wait for the command.
    """
    with SmolVM() as vm:
        result = vm.run(command, timeout=timeout)
        return (
            f"exit_code: {result.exit_code}\n"
            f"stdout:\n{result.stdout.strip() or '<empty>'}\n"
            f"stderr:\n{result.stderr.strip() or '<empty>'}"
        )

agent = Agent(
    name="SmolVM Assistant",
    model="gpt-4.1",
    instructions=(
        "You are a coding assistant with access to a secure SmolVM sandbox. "
        "For shell or Python inspection requests, call run_in_smolvm exactly "
        "once and then summarize the result."
    ),
    tools=[function_tool(run_in_smolvm)],
)

async def main():
    result = await Runner.run(
        agent, "Run `uname -a && python3 --version` in the sandbox."
    )
    print(result.final_output)

asyncio.run(main())
```

<Tip>
  See the full working example in [`examples/agent_tools/openai_agents_tool.py`](https://github.com/celestoai/smolvm/blob/main/examples/agent_tools/openai_agents_tool.py).
</Tip>

### Use SmolVM as a SandboxAgent provider

If you want OpenAI's `SandboxAgent` to treat SmolVM as its full working computer (not just a one-shot tool), use the ready-made provider in the Celesto SDK. It plugs into `Runner` and `SandboxRunConfig` directly, and ships alongside a hosted Celesto option you can swap in without changing your agent code. See [OpenAI Agents SDK sandboxes](/celesto-sdk/openai-agents) for the full guide.

## LangChain

Wrap SmolVM as a [LangChain tool](https://python.langchain.com/docs/concepts/tools/):

```python theme={null}
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
from smolvm import SmolVM

@tool
def run_in_smolvm(command: str, timeout: int = 30) -> str:
    """Run a shell command inside an ephemeral SmolVM sandbox.

    Args:
        command: Shell command to execute inside the sandbox guest.
        timeout: Maximum number of seconds to wait for the command.
    """
    with SmolVM() as vm:
        result = vm.run(command, timeout=timeout)
        return (
            f"exit_code: {result.exit_code}\n"
            f"stdout:\n{result.stdout.strip() or '<empty>'}\n"
            f"stderr:\n{result.stderr.strip() or '<empty>'}"
        )

llm = ChatOpenAI(model="gpt-4.1")
agent = create_react_agent(llm, [run_in_smolvm])

result = agent.invoke({
    "messages": [{"role": "user", "content": "Run uname -a in the sandbox"}]
})
print(result["messages"][-1].content)
```

<Tip>
  See the full working example in [`examples/agent_tools/langchain_tool.py`](https://github.com/celestoai/smolvm/blob/main/examples/agent_tools/langchain_tool.py).
</Tip>

## Browser and desktop sandboxes

SmolVM can give your agent a browser or a full desktop inside a disposable sandbox. Use browser mode for websites and Playwright automation. Use desktop mode when the agent needs a visible screen that a computer-use driver can control. VNC means Virtual Network Computing, a standard way to view and control a remote screen.

```python browser_agent.py theme={null}
from smolvm import SmolVM

with SmolVM.browser(
    headless=False,
    record_video=True,
    viewport={"width": 1440, "height": 900},
) as browser_sandbox:
    print(f"Session: {browser_sandbox.session_id}")
    print(f"CDP URL: {browser_sandbox.cdp_url}")
    print(f"Viewer URL: {browser_sandbox.viewer_url}")
    print(f"Display URL: {browser_sandbox.display_url}")

    browser = browser_sandbox.connect_playwright()
    context = browser.contexts[0] if browser.contexts else browser.new_context()
    page = context.pages[0] if context.pages else context.new_page()
    page.goto("https://example.com", wait_until="networkidle")

    browser_sandbox.screenshot("screenshot.png")
    browser.close()
```

<Tip>
  See the full working example in [`examples/browser_sandbox.py`](https://github.com/celestoai/smolvm/blob/main/examples/browser_sandbox.py).
</Tip>

### Browser and desktop modes

| Mode                             | Description                                                      |
| -------------------------------- | ---------------------------------------------------------------- |
| `SmolVM.browser(headless=True)`  | Starts Chromium for automation and returns `cdp_url`.            |
| `SmolVM.browser(headless=False)` | Starts Chromium with `cdp_url`, `viewer_url`, and `display_url`. |
| `SmolVM.desktop()`               | Starts a full desktop with `viewer_url` and `display_url`.       |

`cdp_url` is the browser automation address used by Playwright and other Chrome DevTools Protocol clients. `viewer_url` opens in your browser so you can watch the screen. `display_url` is the VNC address for desktop viewers and computer-use agents.

### Computer-use with OpenAI

Combine a visible browser or desktop sandbox with OpenAI's [computer-use API](https://platform.openai.com/docs/guides/tools/computer-use) for autonomous browsing and desktop workflows. The model sees screenshots and sends back click, type, and scroll instructions.

```python computer_use_browser.py theme={null}
from openai import OpenAI
from smolvm import SmolVM

client = OpenAI()

with SmolVM.browser(
    headless=False,
    viewport={"width": 1440, "height": 900},
) as browser_sandbox:
    browser = browser_sandbox.connect_playwright()
    context = browser.contexts[0] if browser.contexts else browser.new_context()
    page = context.pages[0] if context.pages else context.new_page()
    page.goto("https://example.com", wait_until="domcontentloaded")

    response = client.responses.create(
        model="gpt-5.4",
        tools=[{"type": "computer"}],
        input="Find the main heading on the page.",
    )

    for item in response.output:
        if item.type == "computer_call":
            # Execute browser actions based on the model's instructions.
            pass

    browser.close()
```

<Tip>
  See the full working example in [`examples/agent_tools/computer_use_browser.py`](https://github.com/celestoai/smolvm/blob/main/examples/agent_tools/computer_use_browser.py) for a complete computer-use loop with action handling and domain allowlisting.
</Tip>

## Generic tool pattern

If you use a framework not listed above, the core pattern is the same:

```python theme={null}
from smolvm import SmolVM

def run_in_smolvm(command: str, timeout: int = 30) -> str:
    """Run a shell command inside an ephemeral SmolVM sandbox."""
    with SmolVM() as vm:
        result = vm.run(command, timeout=timeout)
        if result.ok:
            return result.stdout
        return f"Error (exit {result.exit_code}): {result.stderr}"
```

Register this function as a tool in whatever framework you use.
