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__stringifiesdatetimeattributes (e.g.start_timeappears as"2026-07-25 14:35:07.284").
Computed properties¶
success— True ifexit_code==0,not timed_out,not memory_limit_hit,no errors,is_valid_pythonfailed—not 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.
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¶
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
)