Skip to content

API Reference

Sandbox

The unified entrypoint that routes code between Monty and Container backends.

class Sandbox:
    def __init__(
        self,
        max_duration_sec: float | None = None,
        max_memory_mb: int | None = None,
        max_cpus: float | None = None,
        enable_network: bool | None = None,
        enable_package_cache: bool | None = None,
        tmpfs_size_mb: int | None = None,
        image_name: str | None = None,
        workspace: list[Path | str] | None = None,
        sandbox_type: SandboxType | str | None = None,
        readonly: bool | None = None,
        max_output_bytes: int | None = None,
        progress_callback: ReplayProgressCallback | None = None,
    )

All parameters can be set via BACKYARD_* environment variables, which take effect when the corresponding argument is not passed. Explicit constructor arguments always take precedence over env vars.

Constructor parameters

Parameter Default Scope Description
max_duration_sec 10.0 Both Max execution time per call (seconds)
max_memory_mb 128 Both Max memory (MB)
max_cpus 1.0 Container CPU limit
enable_network False Container Network access
enable_package_cache False Container Persist PyPI cache via volume
tmpfs_size_mb 16 Container Size (MB) of in-memory tmpfs for /tmp inside container. Set to 0 to disable.
image_name None Container Container image name (default: backyard-sandbox)
workspace None Both Paths to mount into sandbox
sandbox_type "auto" Routing Backend selection: "auto" (Monty, converts to container when needed), "container" (container from start), or "monty" (Monty only)
readonly False Both Read-only mounts
max_output_bytes 10 MiB Container Maximum bytes for serialized output before truncation
progress_callback None Both Callback invoked during history replay (current, total, execution, phase)

Methods

Method Description
run(code, **kwargs) Execute Python code synchronously
run_async(code, **kwargs) Execute Python code asynchronously
clear() Reset execution state and history for both sandboxes
reset_session() Lightweight reset (clears state, preserves container)
ping() Check if sandbox backend is responsive
close() Release all container resources
close_async() Async version of close
convert(target, *, force=False) Convert between backends (Monty, Container, or Auto)
convert_async(target, *, force=False) Async version of convert
install_packages(packages) Install PyPI packages (container required)
install_packages_async(packages) Async version of install_packages
grant_write_access() Switch to read-write mode
revoke_write_access() Switch to read-only mode
grant_write_access_async() Async version
revoke_write_access_async() Async version
update_resource_limits(memory_mb, cpus) Update memory/CPU limits at runtime

Properties

Property Type Description
active_sandbox_type SandboxType \| None Current backend in use
sandbox_type SandboxType Configured backend selection strategy (AUTO, MONTY, or CONTAINER)
history list[SandboxExecution] Successful execution history
readonly bool Whether read-only mode is active
monty MontySandbox \| None Monty backend instance
container ContainerSandbox \| None Container backend instance

Kwargs for run() / run_async()

Kwarg Backend Description
env_vars Both Environment variables
external_functions Both (Monty native, Container uses inspect.getsource) Callable injection
inputs Both Named variables injected into namespace
dependencies Container PyPI packages to install
type_check Monty Enable type checking
type_check_stubs Monty Type stub source
dataclass_registry Monty Dataclass types for type checker

MontySandbox

Python sandbox using pydantic-monty, a minimal, Rust-based Python interpreter.

class MontySandbox:
    def __init__(
        self,
        max_duration_sec: float | None = 10.0,
        max_memory_mb: int | None = 64,
        max_recursion_depth: int | None = 1_000,
        workspace: list[Path] | None = None,
        readonly: bool = False,
    )

Methods

Method Description
run(code, **kwargs) Execute code synchronously
run_async(code, **kwargs) Execute code asynchronously
clear() Reset the session, discard execution state
grant_write_access() Switch to read-write mode
revoke_write_access() Switch to read-only mode

Monty-specific run() kwargs

Kwarg Type Description
env_vars dict[str, str] Environment variables
external_functions dict[str, Callable] Callable injection
type_check bool Enable type checking
type_check_stubs str Type stub source
dataclass_registry list[type] Dataclass types for type checker
inputs dict[str, Any] Named variables (also via **kwargs)

ContainerSandbox

Container sandbox using Podman or Docker supporting all Python features, including third-party packages (if enabled).

class ContainerSandbox:
    IMAGE_NAME: str = "backyard-sandbox"

    def __init__(
        self,
        max_duration_sec: float = 10.0,
        max_memory_mb: int | None = 128,
        max_cpus: float | None = 1.0,
        enable_network: bool | None = False,
        enable_package_cache: bool | None = False,
        image_name: str | None = None,
        workspace: list[Path | str] | None = None,
        readonly: bool = False,
        tmpfs_size_mb: int = 16,
        max_output_bytes: int = 10 * 1024 * 1024,
    )

Methods

Method Description
run(code, **kwargs) Execute code synchronously
run_async(code, **kwargs) Execute code asynchronously
install_packages(packages) Install PyPI packages synchronously
install_packages_async(packages) Install PyPI packages asynchronously
ping() Check if daemon is responsive
reset_session() Reset daemon namespaces
close() Stop and remove container
close_async() Async version
grant_write_access() Restart with read-write mounts
revoke_write_access() Restart with read-only mounts
update_resource_limits(memory_mb, cpus) Live resource limit update

Properties

Property Type Description
container_id str \| None Running container ID
container_name str \| None Running container name
container_runtime str Detected runtime (podman or docker)
installed_packages set[str] Packages installed in container

Container-specific run() kwargs

Kwarg Type Description
dependencies list[str] Additional PyPI packages
env_vars dict[str, str] Environment variables
external_functions dict[str, Callable] Functions (serialized via inspect.getsource)

SandboxExecution

Results of a code execution.

@dataclass
class SandboxExecution:
    stdout: str
    stderr: str
    errors: list[SandboxError] | None = None
    files: list[MemoryFile] | None = None
    rich_outputs: list[RichOutput] | None = None
    file_changes: FileChanges | None = None
    is_valid_python: bool = True
    exit_code: int = 0
    start_time: datetime.datetime
    end_time: datetime.datetime
    duration_sec: float = 0.0
    timed_out: bool = False
    memory_limit_hit: bool = False
    inputs: SandboxInput | None = None
    result: Any | None = None

    @property
    def success(self) -> bool: ...

    @property
    def failed(self) -> bool: ...

Notes

  • __repr__ stringifies datetime attributes (e.g. start_time appears as "2026-07-25 14:35:07.284").

Computed properties

  • success — True if exit_code==0, not timed_out, not memory_limit_hit, no errors, is_valid_python
  • failednot success

SandboxInput

Input for a single code execution.

@dataclass
class SandboxInput:
    code: str
    env_vars: dict[str, str] | None = None
    input_files: list[Path] | None = None
    dependencies: list[str] | None = None  # Container
    external_functions: dict[str, Callable] | None = None  # Monty
    inputs: dict[str, Any] | None = None  # Monty
    type_check: bool = False  # Monty
    type_check_stubs: str | None = None  # Monty
    dataclass_registry: list[type[Any]] | None = None  # Monty
    max_duration_sec: float | None = None  # Per-call override
    max_memory_mb: int | None = None  # Per-call override

SandboxConfig

Configuration dataclass.

@dataclass
class SandboxConfig:
    max_duration_sec: float | None = 10.0
    max_memory_mb: int | None = 128
    max_cpus: float | None = 1.0  # Container only
    enable_network: bool | None = False  # Container only
    enable_package_cache: bool | None = False  # Container only
    tmpfs_size_mb: int = 16  # Container only
    image_name: str | None = None  # Container only
    max_recursion_depth: int | None = 1_000  # Monty only
    workspace: list[Path | str] | None = None

FileChanges

File system changes detected during execution.

@dataclass
class FileChanges:
    added: list[Path]
    modified: list[Path]
    deleted: list[Path]
    all_changes: list[FileChange]

    @property
    def has_changes(self) -> bool: ...

FileChange

A single file change detected during execution.

@dataclass
class FileChange:
    path: Path
    timestamp: datetime.datetime
    change_type: str  # "added", "modified", or "deleted"

InstallResult

Result of a package installation request.

@dataclass
class InstallResult:
    success: bool
    output: str = ""
    error: str | None = None

RichOutput

Rich media output from the sandbox.

@dataclass
class RichOutput:
    mime_type: str  # e.g. "image/png", "text/html"
    content: str | bytes  # Raw text or base64 encoded bytes

Error classes

from backyard.errors import (
    SandboxError,
    SandboxTimeoutError,
    SandboxMemoryError,
    SandboxSyntaxError,
    SandboxRuntimeError,
    SandboxNotSupportedError,
    SandboxPermissionError,
)

class SandboxError(Exception):
    def __init__(self, message: str, traceback: str | None = None)

class SandboxTimeoutError(SandboxError): ...      # Exit code 124
class SandboxMemoryError(SandboxError): ...        # Exit code 137
class SandboxSyntaxError(SandboxError): ...
class SandboxRuntimeError(SandboxError): ...
class SandboxNotSupportedError(SandboxError): ...  # Monty incompatibility
class SandboxPermissionError(SandboxError): ...    # Read-only violation

SandboxType

class SandboxType(StrEnum):
    CONTAINER = "container"
    MONTY = "monty"
    AUTO = "auto"

Utility exports (backyard.utils)

from backyard.utils import (
    ALWAYS_IGNORED,             # frozenset of always-hidden directory names
    STD_LIB,                    # set of standard library module names
    FileChangesTracker,         # Helper for tracking file changes
    GitIgnorePattern,           # Gitignore-style pattern matching
    check_gvisor_available,     # Check if runsc runtime is available
    detect_container_runtime,   # Detect podman or docker
    detect_dependencies,        # AST-based dependency detection
    env_bool,                   # Read bool from BACKYARD_* env var
    env_float,                  # Read float from BACKYARD_* env var
    env_int,                    # Read int from BACKYARD_* env var
    env_str,                    # Read str from BACKYARD_* env var
    get_background_loop,        # Get/create the background event loop
    get_directory_snapshot,     # Recursive directory scan
    get_file_changes,           # Compare two snapshots
    get_logger,                 # Get structured logger
    is_binary,                  # Check if file is binary
    is_readonly_error,          # Check if error message indicates read-only
    load_module_mapping,        # Load module→PyPI name mapping
    parse_gitignore,            # Parse .gitignore files
    run_sync,                   # Run async function synchronously
    split_workspace_paths,      # Split paths into dirs and files
)