Dynamiq
Advanced

Sandboxes

Give agents an isolated remote filesystem and shell with E2B or Daytona sandbox backends — attach via SandboxConfig or drive the sandbox directly.

The dynamiq.sandboxes package provides isolated remote environments where agents can write files, run shell commands, and serve apps — without touching your host. Attach a sandbox to an Agent and it automatically gains shell, file, and sandbox-info tools; or drive the sandbox object directly from your own code. This is the SDK counterpart of the platform's Agent Sandbox.

Backends

All backends subclass Sandbox (dynamiq/sandboxes/base.py) and share base_path, file operations, and shell execution.

BackendImportConnectionNotes
E2BSandboxdynamiq.sandboxesdynamiq.connections.E2B (E2B_API_KEY)Default base_path="/home/user", session timeout=3600s; supports custom template, envs, metadata, and reconnecting via sandbox_id.
DaytonaSandboxdynamiq.sandboxesdynamiq.connections.Daytona (DAYTONA_API_KEY, DAYTONA_API_URL)Default base_path="/home/daytona"; supports image or snapshot, envs, labels, auto_stop_interval, and reconnecting via sandbox_id.
E2BDesktopSandboxdynamiq.sandboxesdynamiq.connections.E2BE2B desktop environment for computer-use scenarios.

Both E2B and Daytona create the remote sandbox lazily on first use, retry creation on rate limits with exponential backoff (creation_error_handling), and can reattach to a still-running sandbox by passing its sandbox_id.

Attach a sandbox to an Agent

Pass a SandboxConfig to the agent's sandbox field. The agent then extends its tool list with the sandbox's tools automatically:

import os

from dynamiq import Workflow
from dynamiq.connections import E2B as E2BConnection
from dynamiq.connections import OpenAI as OpenAIConnection
from dynamiq.flows import Flow
from dynamiq.nodes.agents import Agent
from dynamiq.nodes.llms import OpenAI
from dynamiq.sandboxes import SandboxConfig
from dynamiq.sandboxes.e2b import E2BSandbox

llm = OpenAI(connection=OpenAIConnection(), model="gpt-4o", temperature=0.2)

sandbox = E2BSandbox(
    connection=E2BConnection(api_key=os.environ["E2B_API_KEY"]),
    timeout=3600,
    base_path="/home/user",
)

agent = Agent(
    id="sandbox-agent",
    name="SandboxAgent",
    llm=llm,
    sandbox=SandboxConfig(enabled=True, backend=sandbox),
    role="You are a coding assistant that writes and runs scripts in the sandbox.",
    max_loops=10,
)

wf = Workflow(flow=Flow(nodes=[agent]))
result = wf.run(
    input_data={
        "input": "Create hello.py that prints 'Hello from E2B!', run it with python, and show the output."
    }
)
print(result.output["sandbox-agent"]["output"]["content"])

sandbox.close()

For Daytona, swap the connection and backend (DaytonaSandbox(connection=Daytona(api_key=...))) — everything else is identical. Full scripts: agent_e2b_sandbox.py and agent_daytona_sandbox.py.

Tools the agent gains

backend.get_tools(llm=...) adds these nodes to the agent's tool list:

ToolWhat the agent uses it for
sandbox-shell (SandboxShellTool)Execute shell commands with a timeout (default 60s) or in the background; supports a blocked_commands denylist.
File write / file readRead and edit files in the sandbox filesystem (read requires the agent's LLM for large-file handling).
Todo writeMaintain a task list file for long multi-step jobs.
sandbox-info (SandboxInfoTool)Get base_path, sandbox_id, and — given a port — the public HTTPS URL of a service the agent started (for example a dev server).

File conventions baked into the tool prompts: input files uploaded with the run land under {base_path}/input, and anything the agent writes to {base_path}/output is collected and returned after the run.

An agent cannot enable both files (file store) and sandbox at the same time — the sandbox already provides file storage, and the SDK raises a validation error if both are set.

Driving a sandbox directly

The Sandbox interface is useful on its own — for fixtures, cleanups, or custom tooling:

import os

from dynamiq.connections import E2B as E2BConnection
from dynamiq.sandboxes.e2b import E2BSandbox

with E2BSandbox(connection=E2BConnection(api_key=os.environ["E2B_API_KEY"])) as sandbox:
    sandbox.upload_file("data.csv", b"name,score\nada,1\n", destination_path="/home/user/input/data.csv")

    result = sandbox.run_command_shell("wc -l /home/user/input/data.csv", timeout=30)
    print(result.stdout, result.exit_code)

    print(sandbox.list_files("/home/user/input"))
    print(sandbox.retrieve("/home/user/input/data.csv"))

    info = sandbox.get_sandbox_info(port=8000)
    print(info.sandbox_id, info.public_url)

Key methods on every backend:

  • run_command_shell(command, timeout=60, run_in_background_enabled=False)ShellCommandResult with stdout, stderr, exit_code, and is_success.
  • upload_file(file_name, content, destination_path=None) / list_files(target_dir=None) / exists(path) / retrieve(path) for the filesystem.
  • get_sandbox_info(port=None)SandboxInfo with base_path, sandbox_id, and public_url for an exposed port.
  • close(kill=False) — disconnect; kill=True also terminates the remote sandbox. The context-manager form closes automatically.

Reconnect to a long-lived sandbox across processes by persisting sandbox.current_sandbox_id and constructing the backend later with sandbox_id=<saved id>.

YAML workflows

Sandbox-backed agents serialize like any other node, so you can define the sandbox in a workflow YAML and load it with WorkflowYAMLLoader — see the YAML sandbox example and YAML Workflows.

Next steps

On this page