Starphix
Agentic Engineering / Sources
The Lab / Sources / Agentic Engineering / ToolUse/Code-Execution.md

Code Execution

Sandboxed code execution for agents: environments, security, patterns, and tools.


Why Code Execution?

Capability Use Case
Data analysis Pandas, NumPy, SQL, visualization
Code generation Write, test, debug code
Math/computation SymPy, numerical solving
Prototyping Rapid iteration, REPL
Verification Run tests, type check, lint
Automation Scripts, file ops, API calls

Sandbox Options

Sandbox Type Startup Isolation Best For
E2B Cloud VM ~1s Strong (VM) Production, long-running
Modal Cloud functions ~100ms Strong (container) GPU, custom images
Daytona Cloud workspaces ~2s Strong (VM) Persistent, IDE integration
Firecracker MicroVM ~100ms Strongest (KVM) High-security, multi-tenant
gVisor User-space kernel ~10ms Strong (no KVM needed) Containers, no KVM
Docker Container ~100ms Medium Standard workloads
WASM Wasmtime/Wasmer ~1ms Strong (no kernel) Edge, plugins, untrusted
Restricted Python Interpreter ~1ms Weak (AST-based) Simple, trusted code only
Local (subprocess) Local ~1ms None (host) Trusted, dev only

E2B (Cloud VM)

Setup

pip install e2b
export E2B_API_KEY="your-key"

Basic Usage

from e2b import Sandbox

sandbox = Sandbox()

# Run code
result = sandbox.run_code("""
import pandas as pd
df = pd.read_csv("data.csv")
print(df.describe())
""")

print(result.stdout)
print(result.stderr)
print(result.error)

# Files
sandbox.files.write("data.csv", open("data.csv", "rb").read())
result = sandbox.run_code("print(open('data.csv').read()[:100])")

Advanced

# Persistent sandbox
sandbox = Sandbox(template="base", timeout=300)

# Install packages
sandbox.run_code("!pip install numpy scikit-learn -q")

# GPU support
sandbox = Sandbox(gpu=True)

# Internet access (default: true)
sandbox = Sandbox(internet_access=False)

# Commands
sandbox.commands.run("ls -la")

Setup

pip install modal
modal token new

Basic Usage

import modal

app = modal.App("code-execution")

image = modal.Image.debian_slim().pip_install(
    "pandas", "numpy", "matplotlib", "scikit-learn"
)

@app.function(image=image, timeout=300, cpu=2, memory=4096)
def run_code(code: str) -> dict:
    # Execute in isolated environment
    import subprocess, sys, tempfile, os

    with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
        f.write(code)
        f.flush()
        try:
            result = subprocess.run(
                [sys.executable, f.name],
                capture_output=True,
                text=True,
                timeout=60
            )
            return {
                "stdout": result.stdout,
                "stderr": result.stderr,
                "returncode": result.returncode
            }
        finally:
            os.unlink(f.name)

# Local testing
if __name__ == "__main__":
    with modal.run():
        result = run_code.remote("print('Hello from Modal!')")
        print(result)

GPU/GPU

@app.function(
    image=image,
    gpu="A10G",  # or "H100", "A100"
    timeout=600
)
def train_model(code: str):
    # GPU-accelerated execution
    ...

Daytona (Cloud Workspaces)

Setup

pip install daytona
daytona auth login

Usage

from daytona import Daytona, CreateWorkspaceParams

daytona = Daytona()

workspace = daytona.create(CreateWorkspaceParams(
    repository="github.com/user/repo",
    # or blank for empty
))

# Execute in workspace
execution = workspace.execute("python script.py")
print(execution.output)

# File operations
workspace.fs.write_file("script.py", "print('hello')")
workspace.fs.read_file("output.txt")

# Terminal access
terminal = workspace.terminal.create()
terminal.send("python -c 'print(1+1)'")
print(terminal.read())

Local Sandboxes

Docker

import docker

client = docker.from_env()

def run_in_docker(code: str, image="python:3.11-slim") -> dict:
    container = client.containers.run(
        image,
        command=["python", "-c", code],
        detach=True,
        mem_limit="512m",
        cpu_quota=50000,  # 0.5 CPU
        network_mode="none",  # No network
        remove=True
    )

    try:
        result = container.wait(timeout=60)
        logs = container.logs(stdout=True, stderr=True).decode()
        return {"exit_code": result["StatusCode"], "logs": logs}
    except Exception as e:
        container.kill()
        return {"error": str(e)}

gVisor (Stronger Isolation)

# Install gVisor
# runsc install
def run_in_gvisor(code: str) -> dict:
    # runsc provides stronger isolation than Docker
    result = subprocess.run(
        ["runsc", "run", "--", "python", "-c", code],
        capture_output=True,
        text=True,
        timeout=60
    )
    return {"stdout": result.stdout, "stderr": result.stderr}

WASM (Wasmtime)

import wasmtime

# Compile Python to WASM (using wasm32-wasi target)
# Then execute in Wasmtime

engine = wasmtime.Engine()
store = wasmtime.Store(engine)
module = wasmtime.Module.from_file(engine, "python.wasm")
instance = wasmtime.Instance(store, module, [])

# Call exported functions
result = instance.exports(store)["main"]()

Code Execution Patterns

1. REPL / Interactive

class REPLSession:
    def __init__(self, sandbox):
        self.sandbox = sandbox
        self.namespace = {}

    def execute(self, code: str) -> ExecutionResult:
        # Wrap in function to capture returns
        wrapped = f"""
import sys
import io
old_stdout = sys.stdout
sys.stdout = io.StringIO()
try:
    {code}
    result = sys.stdout.getvalue()
finally:
    sys.stdout = old_stdout
print(repr(result))
"""
        return self.sandbox.run_code(wrapped)

2. Notebook-Style (Cell-Based)

class NotebookSession:
    def __init__(self, sandbox):
        self.sandbox = sandbox
        self.cells = []
        self.outputs = []

    def add_cell(self, code: str, cell_type="code"):
        self.cells.append({"code": code, "type": cell_type})

    def execute_cell(self, index: int) -> CellOutput:
        cell = self.cells[index]
        # Build context from previous cells
        context = "\n".join(c["code"] for c in self.cells[:index])
        full_code = context + "\n" + cell["code"]
        result = self.sandbox.run_code(full_code)
        self.outputs.append(result)
        return result

3. Code Generation + Verification

async def generate_and_verify(generator, verifier, max_attempts=3):
    for attempt in range(max_attempts):
        code = await generator.generate()

        # Syntax check
        try:
            compile(code, "<generated>", "exec")
        except SyntaxError as e:
            continue

        # Run tests
        test_result = await run_tests(code)
        if test_result.passed:
            return code

        # Feedback to generator
        await generator.feedback(test_result.failures)

    raise GenerationFailed("Max attempts exceeded")

Security

Threat Model

Threat Mitigation
Code injection Sandbox isolation
File system access Chroot, read-only mounts
Network access Network namespace, egress filtering
Resource exhaustion cgroups: CPU, memory, pids limits
Privilege escalation No root, no caps, user namespaces
Data exfiltration No network, output limits
Crypto mining CPU limits, timeout

Hardening Checklist

SANDBOX_CONFIG = {
    # Resource limits
    "cpu_quota": 50000,        # 0.5 CPU
    "memory_limit": "512m",
    "pids_limit": 100,
    "timeout": 60,

    # Filesystem
    "read_only_root": True,
    "tmpfs": ["/tmp", "/home/user"],
    "no_new_privs": True,

    # Network
    "network": "none",  # or "bridge" with egress filter

    # Capabilities
    "drop_all_caps": True,
    "add_caps": [],  # None

    # User
    "user": "1000:1000",  # Non-root
    "working_dir": "/home/user",

    # Output
    "stdout_limit": "10MB",
    "stderr_limit": "10MB"
}

Language Support

Python

# Standard
result = sandbox.run_code("print('Hello')")

# With data science stack
image = modal.Image.debian_slim().pip_install(
    "pandas", "numpy", "matplotlib", "seaborn",
    "scikit-learn", "torch", "transformers"
)

JavaScript/TypeScript

// Node.js sandbox
const result = await sandbox.runCode(`
const fetch = require('node-fetch');
const response = await fetch('https://api.example.com/data');
console.log(await response.json());
`);

SQL

# DuckDB for analytical SQL
result = sandbox.run_code("""
import duckdb
conn = duckdb.connect()
result = conn.execute("SELECT * FROM 'data.parquet' LIMIT 10").fetchdf()
print(result.to_markdown())
""")

R, Julia, Go, Rust

# Any language with container/WASM support
# Just need appropriate base image or WASM target

Output Handling

Capture & Format

class CodeExecutor:
    def __init__(self, sandbox):
        self.sandbox = sandbox

    def execute(self, code: str, capture="all") -> ExecutionResult:
        # Wrap to capture stdout/stderr/return value
        wrapped = self._wrap_for_capture(code)
        result = self.sandbox.run_code(wrapped)

        return ExecutionResult(
            stdout=result.stdout,
            stderr=result.stderr,
            return_value=self._parse_return(result.stdout),
            error=result.error,
            execution_time=result.execution_time
        )

    def _wrap_for_capture(self, code: str) -> str:
        return f"""
import sys, io, json, traceback
old_stdout, old_stderr = sys.stdout, sys.stderr
sys.stdout, sys.stderr = io.StringIO(), io.StringIO()
try:
    result = {code}
    output = {{"stdout": sys.stdout.getvalue(), "stderr": sys.stderr.getvalue(), "return": result}}
except Exception as e:
    output = {{"stdout": sys.stdout.getvalue(), "stderr": traceback.format_exc(), "return": None}}
finally:
    sys.stdout, sys.stderr = old_stdout, old_stderr
print(json.dumps(output))
"""

Streaming Output

async def execute_streaming(code: str) -> AsyncIterator[OutputChunk]:
    # For long-running code with progress
    process = await asyncio.create_subprocess_exec(
        "python", "-c", code,
        stdout=asyncio.subprocess.PIPE,
        stderr=asyncio.subprocess.PIPE
    )

    async def read_stream(stream, type_):
        async for line in stream:
            yield OutputChunk(type=type_, content=line.decode())

    async with asyncio.TaskGroup() as tg:
        tg.create_task(read_stream(process.stdout, "stdout"))
        tg.create_task(read_stream(process.stderr, "stderr"))

    await process.wait()


Sources: E2B docs, Modal docs, Daytona docs, Docker security, gVisor, Firecracker, Wasmtime, Python sandboxing, modal.com, e2b.dev, daytona.io, NIST sandboxing guidelines.

From the Agentic Engineering research vault · CC BY 4.0 · all notes · raw markdown