# How to Configure Sandbox Execution with SandboxBackendProtocol for Tool Execution in DeepAgents

> Configure sandbox execution with SandboxBackendProtocol in DeepAgents. Learn to set up providers, initialize sandboxes, and run isolated tool commands for secure agent operations.

- Repository: [LangChain/deepagents](https://github.com/langchain-ai/deepagents)
- Tags: how-to-guide
- Published: 2026-03-17

---

**Configure sandbox execution by selecting a provider (modal, runloop, daytona, or langsmith), initializing a sandbox via the `create_sandbox()` context manager, and calling `execute()` or `aexecute()` to run isolated tool commands.**

The **langchain-ai/deepagents** repository provides a robust sandboxing system that isolates tool execution through the `SandboxBackendProtocol`. This protocol enables secure, backend-agnostic command execution across multiple cloud providers while maintaining a consistent interface for file operations and process management.

## Understanding the SandboxBackendProtocol Architecture

The sandbox system centers on a protocol-based design that abstracts provider-specific implementations behind a unified interface.

### Protocol Definition and Core Methods

**`SandboxBackendProtocol`** extends `BackendProtocol` in [`libs/deepagents/deepagents/backends/protocol.py`](https://github.com/langchain-ai/deepagents/blob/main/libs/deepagents/deepagents/backends/protocol.py) to add sandbox-specific capabilities. The protocol requires implementations to provide:

- **`execute(command, timeout=None)`**: Synchronously run shell commands inside the isolated environment
- **`aexecute(command, timeout=None)`**: Asynchronous variant for non-blocking execution
- **`id` property**: A unique identifier for the sandbox instance

According to the source code in [`protocol.py`](https://github.com/langchain-ai/deepagents/blob/main/protocol.py) (lines 12-30 and 112-124), these methods must return an `ExecuteResponse` object containing the combined stdout/stderr output, exit code, and a truncated flag indicating whether output exceeded limits.

### Provider Factory Pattern

Concrete implementations are instantiated through a factory pattern defined in [`libs/cli/deepagents_cli/integrations/sandbox_factory.py`](https://github.com/langchain-ai/deepagents/blob/main/libs/cli/deepagents_cli/integrations/sandbox_factory.py). The `_get_provider()` method (lines 58-86) maps provider names to specific implementations:

- **`modal`**: Cloud-based containerized execution
- **`runloop`**: Alternative cloud provider integration
- **`daytona`**: Development environment sandboxing
- **`langsmith`**: LangChain-specific execution backend

Each provider must implement the abstract `SandboxProvider` interface defined in [`libs/cli/deepagents_cli/integrations/sandbox_provider.py`](https://github.com/langchain-ai/deepagents/blob/main/libs/cli/deepagents_cli/integrations/sandbox_provider.py) (lines 26-36), ensuring consistent lifecycle management across different backends.

## Step-by-Step Configuration Guide

### Select a Sandbox Provider

Choose a provider based on your infrastructure requirements. The provider name string determines which backend implementation the factory instantiates:

```python

# Available providers: "modal", "runloop", "daytona", "langsmith"

provider_name = "modal"

```

### Initialize the Sandbox with create_sandbox

Use the **`create_sandbox()`** context manager from [`sandbox_factory.py`](https://github.com/langchain-ai/deepagents/blob/main/sandbox_factory.py) (lines 71-110) to handle setup, status reporting, and automatic cleanup:

```python
from deepagents_cli.integrations.sandbox_factory import create_sandbox

# Context manager ensures proper resource cleanup

with create_sandbox("modal") as sandbox:
    # sandbox implements SandboxBackendProtocol

    pass

```

The context manager optionally accepts a **`setup_script_path`** parameter. When provided, the factory reads the script, substitutes environment variables (e.g., `${VAR}`), and executes it inside the sandbox with a 5-minute timeout before yielding control.

### Execute Tool Commands

Invoke commands through the **`execute()`** method for synchronous operations or **`aexecute()`** for async workflows. The `BaseSandbox` class in [`libs/deepagents/deepagents/backends/sandbox.py`](https://github.com/langchain-ai/deepagents/blob/main/libs/deepagents/deepagents/backends/sandbox.py) (lines 17-24) implements all file system operations (`read`, `write`, `edit`, `grep_raw`, `glob_info`) by delegating to shell snippets executed through these methods.

```python

# Synchronous execution

result = sandbox.execute("python /workspace/analyze.py", timeout=60)

```

The optional **`timeout`** parameter is validated through the `execute_accepts_timeout()` helper in [`protocol.py`](https://github.com/langchain-ai/deepagents/blob/main/protocol.py) (lines 70-89). If the concrete backend does not support timeout arguments, the parameter is safely ignored rather than raising an error.

### Handle Execution Responses

Process the **`ExecuteResponse`** object returned by execution calls. Defined in [`sandbox.py`](https://github.com/langchain-ai/deepagents/blob/main/sandbox.py) (lines 95-106), this dataclass provides:

- **`output`**: Combined stdout and stderr as a string
- **`exit_code`**: Integer return code from the process
- **`truncated`**: Boolean indicating whether output was truncated due to length limits

```python
if result.exit_code == 0:
    print("Output:", result.output)
else:
    print("Error occurred, truncated:", result.truncated)

```

## Practical Implementation Examples

### Synchronous Tool Execution

Run commands in a Modal-hosted sandbox with immediate feedback:

```python
from deepagents_cli.integrations.sandbox_factory import create_sandbox

with create_sandbox("modal") as sandbox:
    # Execute a file listing command

    result = sandbox.execute("ls -la /workspace")
    print(f"Exit code: {result.exit_code}")
    print(f"Output:\n{result.output}")

```

This example pulls the `ModalProvider` implementation and returns a `SandboxBackendProtocol` instance. The `execute` call runs inside the Modal container and returns an `ExecuteResponse` with full output capture.

### Asynchronous Execution with Timeouts

Handle long-running tools without blocking the event loop:

```python
import asyncio
from deepagents_cli.integrations.sandbox_factory import create_sandbox

async def run_long_task():
    async with create_sandbox("runloop") as sandbox:
        # 30-second timeout for the command

        resp = await sandbox.aexecute(
            "sleep 10 && echo 'Processing complete'", 
            timeout=30
        )
        
        if resp.exit_code == 0:
            print("Success:", resp.output.strip())
        else:
            print(f"Failed with code {resp.exit_code}")

asyncio.run(run_long_task())

```

The `aexecute` method automatically falls back to synchronous execution if the backend lacks native async support, ensuring compatibility across all providers.

### Setup Script Configuration

Initialize the sandbox environment with custom dependencies before tool execution:

```python
from deepagents_cli.integrations.sandbox_factory import create_sandbox

with create_sandbox(
    "daytona",
    setup_script_path="scripts/install_deps.sh"
) as sandbox:
    # Setup script runs first with env var substitution

    result = sandbox.execute("python -c 'import pandas; print(pandas.__version__)'")
    print(result.output)

```

The setup script execution occurs within the context manager initialization, ensuring the environment is ready before your tool commands run.

### Accessing Sandbox Metadata

Inspect the sandbox identifier for logging or external monitoring:

```python
with create_sandbox("langsmith") as sandbox:
    print(f"Sandbox ID: {sandbox.id}")
    # Use ID for external API calls or cleanup tracking

    result = sandbox.execute("echo 'Task started'")

```

The `id` property is required by the `SandboxBackendProtocol` specification and uniquely identifies the instance throughout its lifecycle.

## Key Implementation Files and Architecture

Understanding the source structure helps debug configuration issues:

- **[`libs/deepagents/deepagents/backends/protocol.py`](https://github.com/langchain-ai/deepagents/blob/main/libs/deepagents/deepagents/backends/protocol.py)**: Defines `SandboxBackendProtocol`, `ExecuteResponse`, and timeout validation utilities
- **[`libs/deepagents/deepagents/backends/sandbox.py`](https://github.com/langchain-ai/deepagents/blob/main/libs/deepagents/deepagents/backends/sandbox.py)**: Contains `BaseSandbox` with default file operation implementations built on `execute()`
- **[`libs/cli/deepagents_cli/integrations/sandbox_factory.py`](https://github.com/langchain-ai/deepagents/blob/main/libs/cli/deepagents_cli/integrations/sandbox_factory.py)**: High-level `create_sandbox` context manager and provider resolution logic
- **[`libs/cli/deepagents_cli/integrations/sandbox_provider.py`](https://github.com/langchain-ai/deepagents/blob/main/libs/cli/deepagents_cli/integrations/sandbox_provider.py)**: Abstract `SandboxProvider` interface for concrete implementations
- **Provider implementations** ([`libs/partners/modal/.../sandbox.py`](https://github.com/langchain-ai/deepagents/blob/main/libs/partners/modal/.../sandbox.py), etc.): Backend-specific subclasses of `BaseSandbox`

## Summary

- **SandboxBackendProtocol** extends `BackendProtocol` with `execute()`, `aexecute()`, and an `id` property for isolated command execution
- **Provider selection** (modal, runloop, daytona, langsmith) occurs through [`sandbox_factory.py`](https://github.com/langchain-ai/deepagents/blob/main/sandbox_factory.py)'s `_get_provider()` mapping
- **Initialization** uses the `create_sandbox()` context manager, which handles setup scripts and automatic resource cleanup
- **Execution** returns `ExecuteResponse` objects containing output, exit_code, and truncation status
- **Timeout handling** is optional and safely ignored if the backend implementation does not support it
- **File operations** in `BaseSandbox` delegate to shell commands executed through the protocol methods

## Frequently Asked Questions

### What providers are supported for SandboxBackendProtocol?

The deepagents CLI supports four providers: **modal**, **runloop**, **daytona**, and **langsmith**. Each implements the `SandboxProvider` interface and returns a concrete `SandboxBackendProtocol` instance. The mapping from provider name to implementation class is defined in [`sandbox_factory.py`](https://github.com/langchain-ai/deepagents/blob/main/sandbox_factory.py) (lines 58-86).

### How does the timeout parameter work in execute() calls?

The `timeout` parameter is optional and passed directly to the backend's `execute()` or `aexecute()` method. According to [`protocol.py`](https://github.com/langchain-ai/deepagents/blob/main/protocol.py) (lines 70-89), the system checks whether the concrete implementation accepts timeout arguments using `execute_accepts_timeout()`. If the backend does not support timeouts, the parameter is silently ignored rather than raising a `TypeError`.

### Can I run setup scripts before executing my tools?

Yes. Pass the `setup_script_path` parameter to `create_sandbox()`. The factory reads the specified file, substitutes environment variables (format `${VAR}`), and executes the script inside the sandbox with a 5-minute hard timeout before yielding the backend instance. This occurs in [`sandbox_factory.py`](https://github.com/langchain-ai/deepagents/blob/main/sandbox_factory.py) (lines 71-110).

### What information does ExecuteResponse contain?

`ExecuteResponse` is a dataclass defined in [`sandbox.py`](https://github.com/langchain-ai/deepagents/blob/main/sandbox.py) (lines 95-106) containing three fields: **`output`** (combined stdout and stderr as a string), **`exit_code`** (integer process return code), and **`truncated`** (boolean indicating whether the output exceeded length limits and was cut off).