Skip to content

Sandbox API ​

Package: elsai-agents  v0.3.0+

Sandbox execution APIs live in elsai.execution and elsai.agent. Remote backends (AgentCore, Daytona) ship in elsai-agents-tools.

Concept guides: Sandbox overview · Shared workspace · Backends


Sandbox ​

python
from elsai.execution import Sandbox

Shared sandbox workspace for one or more agents in a single process. The application creates and owns the Sandbox; agents attach via AgentConfig(sandbox=...).

python
async with Sandbox(
    workspace_id="graph-run-1",
    backend=backend_template,
    ttl_seconds=7200,
    seed_from="/path/to/project",
) as sandbox:
    ...

Sandbox.__init__ ​

ParameterRequiredDefaultDescription
workspace_idYes—Registry key for this workspace in the current process. All agents on the same Sandbox instance share one backend. Not a cross-process sharing key.
backendYes—Backend instance or template (LocalSandboxBackend, AgentCoreSandboxTemplate, DaytonaSandboxTemplate, …).
ttl_secondsYes—Workspace idle TTL (seconds). Required — choose explicitly (for example 7200). Idle time is measured from the last sandbox activity. Enforced when SandboxManager.cleanup_expired() runs; primary teardown is stop() or async with Sandbox. See Timeouts and TTL.
managerNoauto SandboxManager(ttl_seconds=...)Session manager instance. Override for tests or multi-sandbox applications.
seed_fromNoNoneHost project directory copied into the workspace on start().
seed_excludeNoNoneExtra glob patterns merged with DEFAULT_SANDBOX_SEED_EXCLUDES.
sync_policyNodefault_sandbox_sync_policy()Include/exclude globs for flush().
sync_destNoseed_fromHost path for artifact sync when flush() dest is omitted.

Properties ​

PropertyTypeDescription
is_startedboolTrue after a successful start().
owner_idstr | NoneIn-process ownership token for the current start cycle.

Sandbox.start ​

python
await sandbox.start()  # -> WorkspaceSeedResult | None

Create the backend, claim the workspace, and seed when seed_from is set. Idempotent.

Raises: SandboxStartError when another Sandbox instance already owns this workspace_id in-process.

Sandbox.stop ​

python
await sandbox.stop(sync=True)

Detach all attached agents, optionally flush() artifacts, then close the backend session.

ParameterRequiredDefaultDescription
syncNoTrueWhen True, run flush() before closing.

Sandbox.add_files ​

python
await sandbox.add_files(files, overwrite=True)  # -> list[str]

Write or upload files into the workspace without an agent turn (orchestrator API).

ParameterRequiredDefaultDescription
filesYes—Mapping of workspace-relative path → str, bytes, or host Path.
overwriteNoTrueWhen False, skip paths that already exist in the workspace.

Returns: List of workspace paths written.

Sandbox.download_files ​

python
await sandbox.download_files(files, overwrite=True)  # -> list[str]

Download sandbox files to host paths.

ParameterRequiredDefaultDescription
filesYes—Mapping of sandbox-relative path → host destination path.
overwriteNoTrueWhen False, skip when the host destination already exists.

Returns: Sandbox paths downloaded successfully.

Raises: OSError when a sandbox file cannot be read or written on the host.

Sandbox.delete_files ​

python
await sandbox.delete_files(paths)

Delete workspace-relative paths. Host-side API — not restricted by agent attach mode.

ParameterRequiredDescription
pathsYesList of workspace-relative file paths.

Sandbox.move_file ​

python
await sandbox.move_file(src, dest)

Move or rename a file within the workspace (read → write → delete).

ParameterRequiredDescription
srcYesSource workspace-relative path.
destYesDestination workspace-relative path.

Sandbox.read_file ​

python
await sandbox.read_file(path)  # -> str

Convenience read for applications and tests.

ParameterRequiredDescription
pathYesWorkspace-relative path.

Sandbox.flush ​

python
await sandbox.flush(dest=None)  # -> WorkspaceSyncResult | None

Sync sandbox artifacts to the host per sync_policy.

ParameterRequiredDefaultDescription
destNosync_dest or seed_fromHost directory for synced files. Returns None when no destination is configured.

Sandbox.attach ​

python
sandbox.attach(agent, mode=SandboxAttachMode.READ_WRITE)

Wire an agent to this sandbox. Normally invoked automatically from AgentConfig(sandbox=...) — callers rarely call this directly.

ParameterRequiredDefaultDescription
agentYes—Agent instance to attach.
modeNoREAD_WRITESandboxAttachMode — tool access level.

Raises: SandboxAttachError when the sandbox is not started, the agent is already attached elsewhere, or attach cannot complete.

Sandbox.detach ​

python
sandbox.detach(agent)

Remove an agent's binding without stopping the sandbox VM. Idempotent when the agent is not attached.

See Shared workspace — Attach and detach.

Sandbox.ref ​

python
sandbox.ref()  # -> SandboxRef

Return a forward-compatible handle stub (v1 — not used for cross-process sharing).

Context manager ​

python
async with Sandbox(...) as sandbox:
    ...

Calls start() on enter and stop(sync=True) on exit.


SandboxManager ​

python
from elsai.execution import SandboxManager

Get-or-create sandbox sessions keyed by workspace_id, with optional TTL expiry.

python
SandboxManager(ttl_seconds=3600.0)
ParameterRequiredDefaultDescription
ttl_secondsNo3600.0Idle seconds before a session is eligible for cleanup_expired(). Set to None to disable idle expiry checks. Does not run automatically — call cleanup_expired() on a schedule in long-running apps.

Methods ​

MethodDescription
resolve_workspace_id(agent)Workspace key: _sandbox_workspace_id → SessionManager.session_id → agent_id.
resolve_session_id(agent)Legacy alias for resolve_workspace_id.
get_session(session_id)Return ManagedSandboxSession or None.
get_or_create(session_id, factory)Return or create a managed session (per-agent path).
claim_session(session_id, factory, owner_id=...)Atomically claim a workspace for a Sandbox start cycle.
mark_prepared(session_id, seed_result=...)Mark session as seeded.
close_session(session_id, sync_artifacts=True, agent=None)Destroy session and close backend.
cleanup_expired()Close all idle sessions past ttl_seconds. Returns closed session IDs. Call periodically if you rely on TTL as a backstop when stop() is missed.
backend_factory_for_session(template, session_id)Build a factory; uses build_for_session when the template supports it.

LocalSandboxBackend ​

python
from elsai.execution import LocalSandboxBackend

Host-mounted workspace for local development only — no process isolation.

Not isolated

Commands run as subprocesses on the host. Use AgentCore or Daytona for production workloads.

python
LocalSandboxBackend(
    workspace_root="/tmp/sandbox-ws",
    timeout=120,
    max_output_bytes=100_000,
)
ParameterRequiredDefaultDescription
workspace_rootYes—Host directory used as the workspace root.
timeoutNo120Default command timeout in seconds. Timeout → exit code 124.
max_output_bytesNo100000Max combined stdout/stderr captured; longer output is truncated.
inherit_envNoTrueWhether subprocesses inherit the parent process environment.
envNoNoneExtra environment variables (merged when inherit_env=True).

Remote backend templates and their environment variables are documented in Sandbox backends.


SandboxPlugin ​

python
from elsai.plugins.sandbox import SandboxPlugin

Registers sandbox workspace tools when a backend is active. When AgentConfig(sandbox=...) is set, the plugin is auto-registered on attach if not already present.

See Plugins — SandboxPlugin.

Tools ​

execute ​

ParameterTypeRequiredDescription
commandstrYesShell command to run in the workspace.
cwdstrNoWorking directory override inside the workspace.

Omitted when the backend does not implement SandboxBackend (no shell execution support).

read_file ​

ParameterTypeRequiredDefaultDescription
pathstrYes—Workspace-relative file path.
offsetintNo0Line offset for partial reads.
limitintNoNoneMaximum number of lines to read.

write_file ​

ParameterTypeRequiredDescription
pathstrYesWorkspace-relative file path.
contentstrYesText content to write.

list_dir ​

ParameterTypeRequiredDescription
pathstrYesWorkspace-relative directory path.

Custom tool helpers ​

python
from elsai.plugins.sandbox import (
    run_command,
    read_workspace_file,
    write_workspace_file,
    list_workspace_dir,
    format_execute_result,
)
HelperDescription
run_command(agent, command, cwd=None)Run a shell command; returns formatted exit code and output.
read_workspace_file(agent, path, offset=0, limit=None)Read a workspace file from a custom @tool.
write_workspace_file(agent, path, content)Write a workspace file from a custom @tool.
list_workspace_dir(agent, path)List a directory from a custom @tool.
format_execute_result(result)Format an ExecuteResult like the execute tool.

Mutating helpers call ensure_sandbox_mutation_allowed — raises on read-only or detached agents.

For custom timeouts on run_command, wrap with async with asyncio.timeout(seconds):.


AgentConfig sandbox fields ​

python
from elsai.agent import AgentConfig, SandboxMode, SandboxAttachMode, WorkspaceSyncPolicy, SandboxOutputOffloadPolicy
FieldTypeDefaultDescription
sandboxSandbox | NoneNoneShared workspace. Triggers attach at agent init. Do not combine with execution_backend, workspace_root, or sandbox_manager.
sandbox_attach_modeSandboxAttachModeREAD_WRITEAccess mode when attaching to sandbox.
sandbox_modeSandboxModeOFFSandbox execution mode. See SandboxMode.
sandbox_output_offloadSandboxOutputOffloadPolicy | NoneNoneAuto-register ContextOffloader for large sandbox tool outputs.
execution_backendAnyNoneAdvanced: per-agent backend template or instance (single-agent path).
workspace_rootstr | NoneNoneAdvanced: host directory seeded into the sandbox (per-agent path).
workspace_sync_policyWorkspaceSyncPolicydefaultsInclude/exclude globs for seed and artifact sync.
sandbox_managerSandboxManager | NoneNoneAdvanced: session manager for per-agent path. Auto-created when sandbox mode is enabled without sandbox=.

Validation errors at Agent.__init__:

Invalid combinationError
sandbox= + execution_backendDual config — use Sandbox only
sandbox= + workspace_rootUse Sandbox(seed_from=...)
sandbox= + sandbox_managerManager is owned by Sandbox
sandbox_mode=SANDBOX without backend or sandbox=Missing backend

SandboxMode ​

python
from elsai.agent import SandboxMode
ValueDescription
offNo sandbox backend active. Host prebuilt tools run normally.
sandboxProduction mode. Host execution tools (shell, file_read, file_write, python_repl, environment) are blocked — use sandbox plugin tools instead.
local_devSandbox tools active and host prebuilt tools remain available. Development only.

SandboxAttachMode ​

python
from elsai.agent import SandboxAttachMode
# also: from elsai.execution import SandboxAttachMode
ValueAgent tools
read_writeexecute, read_file, write_file, list_dir
read_onlyread_file, list_dir only

Read-only enforcement uses tool unregistration plus runtime hooks. Custom mutating helpers raise SandboxMutationDeniedError.


WorkspaceSyncPolicy ​

python
from elsai.agent import WorkspaceSyncPolicy
FieldDefaultDescription
exclude_patterns.git, node_modules, __pycache__, .venvGlob patterns skipped when seeding into the sandbox.
sync_include_patternsNoneGlobs copied back on flush. When omitted, backends use default sync behavior.

SandboxOutputOffloadPolicy ​

python
from elsai.agent import SandboxOutputOffloadPolicy
FieldRequiredDefaultDescription
storageYes—Offload backend (InMemoryStorage, FileStorage, S3Storage, …).
max_result_tokensNo2500Offload results above this token count.
preview_tokensNo1000Preview tokens kept in active context.
include_retrieval_toolNoTrueRegister retrieve_offloaded_content.
tool_namesNoexecute, read_file, write_file, list_dirTools whose outputs are eligible.

Workspace helpers ​

python
from elsai.execution import (
    prepare_workspace,
    sync_workspace_artifacts,
    close_sandbox_workspace,
    sync_workspace_for_sandbox,
    sandbox_is_active,
    workspace_is_prepared,
    WorkspaceOrchestrator,
)
SymbolDescription
prepare_workspace(agent)Create backend and seed if needed. Usually automatic via WorkspaceOrchestrator on first invocation.
sync_workspace_artifacts(agent)Sync artifacts from sandbox to host per agent workspace_sync_policy.
close_sandbox_workspace(agent, sync_artifacts=True)Optional sync, then close per-agent sandbox session.
sync_workspace_for_sandbox(sandbox, dest=None)Alias for sandbox.flush(dest).
sandbox_is_active(agent)True when sandbox_mode != off and backend is configured.
workspace_is_prepared(agent)True after prepare completed for this agent.
WorkspaceOrchestratorHook provider — calls prepare_workspace before each agent invocation.

Workspace ID helpers ​

python
from elsai.execution import workspace_id_for_run, workspace_id_for_context
FunctionReturnsUse case
workspace_id_for_run(run_id)graph-{run_id}Graph or workflow runs
workspace_id_for_context(context_id, shared=False)context_id or {context_id}:shared-wsA2A isolated vs team workspace

Default constants ​

python
from elsai.execution import (
    DEFAULT_SANDBOX_SEED_EXCLUDES,
    DEFAULT_SANDBOX_SYNC_INCLUDE,
    default_sandbox_sync_policy,
    HOST_EXECUTION_TOOL_NAMES,
    SANDBOX_OFFLOAD_TOOL_NAMES,
)

DEFAULT_SANDBOX_SEED_EXCLUDES ​

.git, node_modules, __pycache__, .venv, .env, *.pem, credentials.json, secrets/

DEFAULT_SANDBOX_SYNC_INCLUDE ​

src/**, tests/**, *.md, *.py, *.json, *.yaml, *.yml, dist/**, build/**

HOST_EXECUTION_TOOL_NAMES ​

Host tools blocked when sandbox_mode=sandbox: shell, python_repl, file_read, file_write, environment.

Other prebuilt tools (for example editor, http_request, retrieve) are not in this set.


Result types ​

ExecuteResult ​

FieldTypeDescription
outputstrCombined stdout (and primary output text).
exit_codeintProcess exit code.
truncatedboolWhether output was truncated.
stderrstrStderr text when captured separately.
successbool (property)True when exit_code == 0.

FileInfo ​

FieldTypeDescription
pathstrWorkspace-relative path.
is_dirboolWhether the entry is a directory.
sizeint | NoneFile size in bytes when available.

FileTransferResult ​

FieldTypeDescription
pathstrFile path.
contentbytes | NoneTransferred content.
errorstr | NoneError message when transfer failed.
successbool (property)True when error is None.

WorkspaceSeedResult ​

FieldTypeDescription
files_seededintNumber of files copied.
bytes_seededintTotal bytes copied.
skipped_pathslist[str]Paths skipped by exclude patterns.
errorslist[str]Errors encountered during seeding.
successbool (property)True when errors is empty.

WorkspaceSyncResult ​

FieldTypeDescription
files_syncedintNumber of files synced to host.
bytes_syncedintTotal bytes synced.
errorslist[str]Errors during sync.
successbool (property)True when errors is empty.

SandboxRef ​

FieldTypeDescription
workspace_idstrWorkspace identifier.
backend_typestrBackend class name.
manager_idstr | NoneOptional manager hint (forward-compatible).

ManagedSandboxSession ​

FieldTypeDescription
session_idstrWorkspace / session key.
backendAnyLive backend instance.
preparedboolWhether seeding completed.
seed_resultWorkspaceSeedResult | NoneSeed summary.
owner_idstr | NoneOwning Sandbox instance for this cycle.
created_atfloatMonotonic creation time.
last_used_atfloatLast activity time (for TTL).

Protocols ​

ExecutionBackend ​

Minimal backend for filesystem and workspace operations: id, create, close, read_file, write_file, list_dir, remove_file, seed_workspace, sync_artifacts, upload_files, download_files.

SandboxBackend ​

Extends ExecutionBackend with execute(command, timeout=None, cwd=None, **kwargs).

python
from elsai.execution import supports_execution
supports_execution(backend)  # True when execute tools should register

Exceptions ​

ExceptionWhen raised
SandboxStartErrorSecond Sandbox instance claims the same workspace_id in-process.
SandboxAttachErrorAttach before start(), wrong Sandbox instance, agent already attached elsewhere, or partial attach failure.
AgentSandboxDetachedErrorDetached agent calls a mutating sandbox helper.
SandboxMutationDeniedErrorRead-only attached agent attempts execute or write_file.
WorkspacePrepareErrorSeeding or sync reports errors.

Observability ​

Structured audit events are emitted to the logger elsai.sandbox.audit at INFO level for lifecycle and mutation events (sandbox.start, sandbox.add_files, sandbox.execute, sandbox.flush, sandbox.stop, attach, detach, …).

Shell command audit records command length and SHA-256 prefix — not full command text. Optional inferred_op labels (for example shell_delete) are best-effort.


Copyright © 2026 elsai foundry.