> For the complete documentation index, see [llms.txt](/llms.txt).
> A full single-fetch corpus is available at [llms-full.txt](/llms-full.txt).
---
title: Use sandboxes with agents
description: Give an agent an isolated workspace where it can write files, read files, list files, and execute code.
last_verified: 2026-07-24
---

A **sandbox** is an isolated workspace attached to an **[agent](/docs/build/agents.md)**. The agent can write files, read files, list directories, and execute code without running generated code in your worker process. Use sandboxes when an agent needs to inspect code, create scripts, run tests, or verify calculations before it answers.

## Attach a sandbox

Pass `Sandbox()` to the agent constructor. AGNT5 creates the provider sandbox on first use, keeps the workspace available for the duration of the run, and closes it when the run ends.



**Python:**

```python
from agnt5 import Agent, Sandbox

agent = Agent(
    name="coder",
    model="openai/gpt-4o-mini",
    instructions=(
        "Use the sandbox workspace to write files, inspect files, "
        "and run code before you return an answer."
    ),
    sandbox=Sandbox(),
)

result = await agent.run(
    "Create answer.py, make it print 6 * 7 as JSON, run it, and show the output."
)

print(result.output)
```





**TypeScript:**

```ts
import { Agent, LM, Sandbox } from '@agnt5/sdk';

const agent = new Agent({
  name: 'coder',
  model: LM.openai(),
  modelName: 'openai/gpt-4o-mini',
  instructions:
    'Use the sandbox workspace to write files, inspect files, and run code before you return an answer.',
  sandbox: new Sandbox(),
});

const result = await agent.run(
  'Create answer.py, make it print 6 * 7 as JSON, run it, and show the output.'
);

console.log(result.output);
```





**Go:**

There's no `sandbox` option on `NewAgent` and no multi-provider `Sandbox` abstraction (`e2b`, `daytona`, `vercel`, `northflank`, `together`) in the Go SDK yet — only two concrete implementations of the `SandboxRunner` interface exist: `agnt5.NewInMemorySandbox()` (deterministic, in-process, for tests) and `agnt5.NewHTTPSandbox(endpoint, apiKey)` (a generic HTTP-backed executor you point at your own sandbox service). Attach one to the invocation's `*agnt5.Context` and give the agent custom tools that call it — there's no automatic file/code tool injection.

```go
sandbox := agnt5.NewHTTPSandbox(os.Getenv("SANDBOX_ENDPOINT"), os.Getenv("SANDBOX_API_KEY"))
ctx.SetSandbox(sandbox)

runCode, err := agnt5.NewTool("run_code", func(_ context.Context, args map[string]any) (any, error) {
    code, _ := args["code"].(string)
    return ctx.Sandbox().ExecuteCode(ctx, "python", code)
}, agnt5.WithToolDescription("Write and run Python code in the sandbox workspace."))

agent, err := agnt5.NewAgent("coder",
    agnt5.WithAgentModel(model),
    agnt5.WithAgentInstructions("Use run_code to write files, inspect files, and run code before you return an answer."),
    agnt5.WithAgentTools(runCode),
    agnt5.WithAgentMaxTurns(5), // NewAgent defaults to 1, which leaves no turn to answer after a tool call
)

result, err := agent.Run(ctx, agnt5.AgentInput{Message: "Create answer.py, make it print 6 * 7 as JSON, run it, and show the output."})
fmt.Println(result.Response)
```



The agent can write files, read files, list files, and execute code automatically. You still pass custom tools through `tools=[...]` when the agent needs other capabilities. The agent can write files, read files, list files, and execute code automatically. You still pass custom tools through `tools: [...]` when the agent needs other capabilities. In Go, the agent only gets the capabilities you expose as custom tools — there's no automatic file/execute tool set, so `run_code` above is the only capability this agent has. Add more tools (`read_file`, `list_files`, ...) wrapping `ctx.Sandbox()` methods for anything else it needs. 

## Choose a provider

`Sandbox()` auto-detects the first configured provider from environment variables. Pass a provider name to use a specific one.



**Python:**

```python
from agnt5 import Agent, Sandbox

agent = Agent(
    name="daytona_coder",
    model="openai/gpt-4o-mini",
    instructions="Use the Daytona sandbox for code and file work.",
    sandbox=Sandbox(provider="daytona"),
)
```





**TypeScript:**

```ts
import { Agent, LM, Sandbox } from '@agnt5/sdk';

const agent = new Agent({
  name: 'daytona-coder',
  model: LM.openai(),
  modelName: 'openai/gpt-4o-mini',
  instructions: 'Use the Daytona sandbox for code and file work.',
  sandbox: new Sandbox({ provider: 'daytona' }),
});
```





**Go:**

Not available — the Go SDK has no named-provider registry. Point `agnt5.NewHTTPSandbox(endpoint, apiKey)` at whichever sandbox service you run; there's no `provider: "daytona"`-style auto-detection.



Common provider names are `e2b`, `daytona`, `vercel`, `northflank`, and `together`. Configure the provider credentials before running the agent. See [Sandbox providers](/docs/integrations/sandbox-providers.md) for the required environment variables.

> **Together limitation:** The Together provider only supports Python code execution. Shell commands (`run_command`) are not available, and sessions expire automatically after 60 minutes and cannot be destroyed early. `auto_destroy` / `autoDestroy` is ignored.

## Configure the sandbox

Beyond `provider`, the `Sandbox` constructor accepts options to control the environment, resources, and lifetime.



**Python:**

```python
sandbox = Sandbox(
    provider="e2b",
    template="my-custom-image",        # specific sandbox image or snapshot
    env={"OPENAI_API_KEY": "sk-..."},  # environment variables inside the sandbox
    timeout_secs=600,                  # sandbox lifetime in seconds (default: 300)
    cpu_cores=2,                       # CPU cores to allocate
    memory_mib=2048,                   # memory in MiB to allocate
)
```





**TypeScript:**

```ts
const sandbox = new Sandbox({
  provider: 'e2b',
  template: 'my-custom-image',          // specific sandbox image or snapshot
  env: { OPENAI_API_KEY: 'sk-...' },   // environment variables inside the sandbox
  timeoutSecs: 600,                     // sandbox lifetime in seconds
  cpuCores: 2,                          // CPU cores to allocate
  memoryMib: 2048,                      // memory in MiB to allocate
});
```





**Go:**

Not available — `NewHTTPSandbox(endpoint, apiKey)` takes only an endpoint, an API key, and an optional `*http.Client`. There's no `template`, `env`, `timeoutSecs`, `cpuCores`, or `memoryMib` option; configure those on the sandbox service you're pointing at instead.



Not all providers support every option. `template`, `cpu_cores`/`cpuCores`, and `memory_mib`/`memoryMib` are passed through to the provider and have no effect when the provider does not support them.

## Use the sandbox from custom tools

Custom tools can use the same sandbox through `ctx.sandbox`. This lets you add project-specific behavior while sharing the agent's workspace.



**Python:**

```python
from agnt5 import Agent, Sandbox, tool
from agnt5.context import Context

@tool
async def count_lines(ctx: Context, path: str) -> dict:
    """Count lines in a sandbox file.

    Args:
        path: Path to the file inside the sandbox workspace.
    """
    content = await ctx.sandbox.read_file(path)
    text = content.content.decode("utf-8")
    return {"path": path, "lines": len(text.splitlines())}

agent = Agent(
    name="code_reviewer",
    model="openai/gpt-4o-mini",
    instructions="Use the sandbox and count_lines tool to inspect generated files.",
    sandbox=Sandbox(provider="e2b"),
    tools=[count_lines],
)
```





**TypeScript:**

```ts
import { Agent, LM, Sandbox, tool } from '@agnt5/sdk';

const countLines = tool(
  'count_lines',
  {
    description: 'Count lines in a sandbox file.',
    inputSchema: {
      type: 'object',
      properties: {
        path: { type: 'string', description: 'Path to the file inside the sandbox workspace.' },
      },
      required: ['path'],
    },
  },
  async (ctx, args) => {
    if (!ctx.sandbox) throw new Error('No sandbox is attached to this agent.');

    const file = await ctx.sandbox.readFile(args.path);
    return {
      path: args.path,
      lines: file.content.toString('utf-8').split('\n').length,
    };
  }
);

const agent = new Agent({
  name: 'code-reviewer',
  model: LM.openai(),
  modelName: 'openai/gpt-4o-mini',
  instructions: 'Use the sandbox and count_lines tool to inspect generated files.',
  sandbox: new Sandbox({ provider: 'e2b' }),
  tools: [countLines],
});
```





**Go:**

Custom tools can use the same sandbox through `ctx.Sandbox()`, since a sandbox is attached to the invocation's `*agnt5.Context`, not to the agent.

```go
countLines, err := agnt5.NewTool("count_lines", func(_ context.Context, args map[string]any) (any, error) {
    path, _ := args["path"].(string)
    file, err := ctx.Sandbox().ReadFile(ctx, path)
    if err != nil {
        return nil, err
    }
    lines := strings.Count(string(file.Content), "\n") + 1
    return map[string]any{"path": path, "lines": lines}, nil
}, agnt5.WithToolDescription("Count lines in a sandbox file."))

ctx.SetSandbox(agnt5.NewHTTPSandbox(os.Getenv("SANDBOX_ENDPOINT"), os.Getenv("SANDBOX_API_KEY")))

agent, err := agnt5.NewAgent("code_reviewer",
    agnt5.WithAgentModel(model),
    agnt5.WithAgentInstructions("Use the sandbox and count_lines tool to inspect generated files."),
    agnt5.WithAgentTools(countLines),
    agnt5.WithAgentMaxTurns(5),
)
```



## Run shell commands

The Python SDK exposes `run_command()` on the sandbox for running arbitrary shell commands. Use it from a custom tool when you need to install packages, run build steps, or execute scripts.



**Python:**

```python
from agnt5 import Agent, Sandbox, tool
from agnt5.context import Context

@tool
async def install_and_run(ctx: Context, package: str, script: str) -> dict:
    """Install a package and run a script inside the sandbox."""
    install = await ctx.sandbox.run_command("pip", args=["install", package])
    run = await ctx.sandbox.run_command("python", args=[script])
    return {"install": install.stdout, "output": run.stdout, "error": run.stderr}

agent = Agent(
    name="builder",
    model="openai/gpt-4o-mini",
    instructions="Use install_and_run to set up dependencies and execute scripts.",
    sandbox=Sandbox(provider="e2b"),
    tools=[install_and_run],
)
```





**Go:**

`SandboxRunner.RunCommand(ctx, command []string) (RunCommandResult, error)` runs a full command. Pass the binary and its arguments as one slice.

```go
installAndRun, err := agnt5.NewTool("install_and_run", func(_ context.Context, args map[string]any) (any, error) {
    pkg, _ := args["package"].(string)
    script, _ := args["script"].(string)

    install, err := ctx.Sandbox().RunCommand(ctx, []string{"pip", "install", pkg})
    if err != nil {
        return nil, err
    }
    run, err := ctx.Sandbox().RunCommand(ctx, []string{"python", script})
    if err != nil {
        return nil, err
    }
    return map[string]any{"install": install.Stdout, "output": run.Stdout, "error": run.Stderr}, nil
}, agnt5.WithToolDescription("Install a package and run a script inside the sandbox."))
```

`RunCommandResult` has `Stdout`, `Stderr`, and `ExitCode` — there's no separate `args`/`working_dir`/`env`/`timeout_ms` options or a streaming variant; pass the full command line yourself.



`run_command` accepts `args`, `working_dir`, `env`, and `timeout_ms`. It returns `stdout`, `stderr`, and `exit_code`. A streaming variant `run_command_stream` is also available for long-running commands.

> **Note:** `run_command` is Python-only among Python and TypeScript. TypeScript supports `executeCode` for running code but does not have a built-in shell command method. Go has a `RunCommand` method too, with a simpler, single-slice argument shape (see the Go tab above). See [Sandbox providers](/docs/integrations/sandbox-providers.md) for provider-specific capabilities.

## Control lifecycle

By default, AGNT5 owns the sandbox lifecycle for the agent run:

- **Create**: the provider sandbox is created on first use.
- **Share**: file and execution state stays available across sandbox calls in the run.
- **Close**: the provider sandbox is destroyed when the agent run finishes.

Set `auto_destroy=False` in Python or `autoDestroy: false` in TypeScript when you need to keep the provider sandbox alive after the run for debugging.



**Python:**

```python
sandbox = Sandbox(provider="e2b", auto_destroy=False)
```





**TypeScript:**

```ts
const sandbox = new Sandbox({ provider: 'e2b', autoDestroy: false });
```





**Go:**

Not available — there's no `auto_destroy`/`autoDestroy` option, and no AGNT5-managed lifecycle for a provider sandbox, since `HTTPSandbox` and `InMemorySandbox` don't own an external provider session the way Python/TypeScript's `Sandbox` does. Manage creation and teardown of whatever service `HTTPSandbox` points at yourself.



> **Warning:** Leaving provider sandboxes running incurs ongoing provider cost and leaves your files accessible in the provider environment until the session expires. Use `auto_destroy=False` only for short debugging sessions.

## Validate your provider setup

Use the `sandbox-smoke` template when you want to confirm that your credentials and provider are working correctly before building.

```bash
agnt5 create --template python/sandbox-smoke sandbox-smoke
cd sandbox-smoke
cp .env.example .env
agnt5 --env-file .env dev
```

Run the lifecycle check after the worker is connected:

```bash
agnt5 --env-file .env run sandbox_lifecycle_check \
  --input '{"provider": "e2b", "code": "print(6 * 7)", "language": "python"}'
```

The smoke template also includes checks for file write, file read, file list, direct code execution, and an agent that uses the sandbox through its built-in tools.

## Next steps

- [Sandbox providers](/docs/integrations/sandbox-providers.md): configure E2B, Daytona, Vercel, Northflank, or Together credentials.
- [Agents](/docs/build/agents.md): configure agent loops, tools, handoffs, and iteration limits.
- [Tools](/docs/build/tools.md): add custom tools that share the agent's sandbox workspace.
- [Local development](/docs/build/local-development.md): run a worker locally with `agnt5 dev`.
