Code Execution

Agent Sandbox provides powerful code execution capabilities for Python and JavaScript/Node.js, enabling you to run code in isolated environments with full control over execution and session management.

This page is kept as an overview. For the current split guides, see Unified Code Execution, Jupyter, and Node.js.

Overview

The sandbox offers two main execution environments:

  • Jupyter Kernel: For Python code execution with persistent sessions and variable state
  • Node.js Runtime: For JavaScript code execution in fresh, isolated environments

Both environments support timeout control, output streaming, and comprehensive error handling.

Python Execution (Jupyter)

The sandbox integrates with JupyterLab to provide a powerful Python execution environment. JupyterLab offers an interactive computing platform with support for notebooks, code execution, and rich output visualization.

JupyterLab Interface

Features

  • Interactive Development: Execute Python code with immediate feedback
  • Rich Output Support: Display plots, tables, HTML, and multimedia content
  • Session Persistence: Maintain variable state across multiple executions
  • Multiple Kernels: Support for Python 3.10, 3.11, and 3.12 kernels
  • Notebook Compatibility: Full compatibility with Jupyter notebook format

Basic Execution

Execute Python code using the Jupyter kernel with automatic session management:

Python SDK
cURL
from agent_sandbox import Sandbox

client = Sandbox(base_url="http://127.0.0.1:8080")

# Execute Python code
result = client.jupyter.execute_code(
    code="""
import numpy as np

data = np.random.randn(10, 5)
mean = np.mean(data, axis=0)
print(f"Shape: {data.shape}")
print(f"Mean values: {mean}")
data.sum()
"""
)

print(f"Status: {result.status}")
print(f"Outputs: {result.outputs}")

Session Management

Maintain variable state across multiple code executions using sessions:

Python SDK
cURL
# First execution - initialize variables
result1 = client.jupyter.execute_code(
    code="x = 42\ny = 'Hello'",
    session_id="my_session"
)

# Second execution - use previous variables
result2 = client.jupyter.execute_code(
    code="print(f'{y}, the answer is {x}')",
    session_id="my_session"  # Same session ID
)

# List active sessions
sessions = client.jupyter.list_sessions()
print(f"Active sessions: {sessions.sessions}")

# Clean up specific session
client.jupyter.cleanup_session(session_id="my_session")

Multi-Version Python Support

The sandbox supports multiple Python versions through different Jupyter kernels:

Python SDK
cURL
# Check available Python versions
info = client.jupyter.info()
print(f"Available kernels: {info.available_kernels}")
# Output: ['python3', 'python3.10', 'python3.11', 'python3.12']

# Use Python 3.10
result_py310 = client.jupyter.execute_code(
    code="""
import sys
print(f"Python: {sys.version}")
def process(items: list[str]) -> None:
    for item in items:
        print(item)
process(['a', 'b', 'c'])
""",
    kernel_name="python3.10"
)

# Use Python 3.11 for new features
result_py311 = client.jupyter.execute_code(
    code="""
import sys
print(f"Python: {sys.version}")
# Use Python 3.11+ features
def process(items: list[str]) -> None:  # New syntax
    match items:  # Structural pattern matching
        case []:
            print("Empty")
        case [single]:
            print(f"One item: {single}")
        case _:
            print(f"Multiple items: {items}")
process(['hello', 'world'])
""",
    kernel_name="python3.11"
)

# Use Python 3.12 for latest features
result_py312 = client.jupyter.execute_code(
    code="""
import sys
print(f"Python: {sys.version}")
# Use Python 3.12+ features
type Point = tuple[float, float]  # Type alias syntax
def distance(p1: Point, p2: Point) -> float:
    return ((p1[0] - p2[0])**2 + (p1[1] - p2[1])**2)**0.5
print(distance((0, 0), (3, 4)))
""",
    kernel_name="python3.12"
)

Advanced Options

Configure kernel, timeout, and other execution parameters:

# Use specific kernel with timeout
result = client.jupyter.execute_code(
    code="""
import time
import sys

print(f"Python version: {sys.version}")
time.sleep(2)
print("Processing complete")
""",
    kernel_name="python3.11",  # Specific kernel version
    timeout=30,  # 30 second timeout
)

# Get Jupyter environment info
info = client.jupyter.info()
print(f"Available kernels: {info.available_kernels}")
print(f"Default kernel: {info.default_kernel}")
print(f"Session timeout: {info.session_timeout_seconds}s")
print(f"Max sessions: {info.max_sessions}")

Output Types

Jupyter execution returns different output types based on the code:

result = client.jupyter.execute_code(code="...")

# Check execution status
print(f"Status: {result.status}")  # 'ok', 'error', or 'timeout'
print(f"Execution count: {result.execution_count}")

# Process outputs
for output in result.outputs:
    if output.output_type == "stream":
        # Standard output/error
        print(f"{output.name}: {output.text}")
    elif output.output_type == "execute_result":
        # Return value
        print(f"Result: {output.data}")
    elif output.output_type == "display_data":
        # Rich display (plots, HTML, etc.)
        print(f"Display: {output.data}")
    elif output.output_type == "error":
        # Error traceback
        print(f"Error: {output.ename}: {output.evalue}")
        for line in output.traceback:
            print(line)

JavaScript/Node.js Execution

Basic Execution

Execute JavaScript code in an isolated Node.js environment:

Python SDK
JavaScript/TypeScript
cURL
# Execute JavaScript code
result = client.nodejs.execute_nodejs_code(
    code="""
const fs = require('fs');
const crypto = require('crypto');

// Generate random hash
const hash = crypto.randomBytes(16).toString('hex');
console.log(`Generated hash: ${hash}`);

// Return a value
const result = {
    timestamp: new Date().toISOString(),
    hash: hash,
    nodeVersion: process.version
};
console.log(JSON.stringify(result, null, 2));
"""
)

print(f"Status: {result.status}")
print(f"Output: {result.stdout}")
print(f"Exit code: {result.exit_code}")

Working with Files

Create additional files in the execution environment:

Python SDK
JavaScript/TypeScript
# Execute with additional files
result = client.nodejs.execute_nodejs_code(
    code="""
const fs = require('fs');

// Read the config file we created
const config = JSON.parse(fs.readFileSync('config.json', 'utf8'));
console.log('Config loaded:', config);

// Read the data file
const data = fs.readFileSync('data.txt', 'utf8');
console.log('Data:', data);

// Process and output
console.log(`Processing ${config.name} with ${data.split('\\n').length} lines`);
""",
    files={
        "config.json": '{"name": "test", "version": "1.0.0"}',
        "data.txt": "line1\\nline2\\nline3"
    }
)

Standard Input

Provide input to the Node.js process:

Python SDK
JavaScript/TypeScript
# Interactive script with stdin
result = client.nodejs.execute_nodejs_code(
    code="""
const readline = require('readline');

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

let lines = [];
rl.on('line', (line) => {
    lines.push(line);
});

rl.on('close', () => {
    console.log('Received lines:', lines.length);
    lines.forEach((line, i) => {
        console.log(`Line ${i + 1}: ${line}`);
    });
});
""",
    stdin="Hello\\nWorld\\nFrom stdin",
    timeout=5
)

Runtime Information

Get information about the Node.js environment:

Python SDK
JavaScript/TypeScript
# Get Node.js runtime info
info = client.nodejs.info()

print(f"Node version: {info.node_version}")
print(f"npm version: {info.npm_version}")
print(f"Supported languages: {info.supported_languages}")
print(f"Runtime directory: {info.runtime_directory}")

Error Handling

Both execution environments provide comprehensive error information:

Python Errors

try:
    result = client.jupyter.execute_code(
        code="print(undefined_variable)"
    )

    if result.status == "error":
        for output in result.outputs:
            if output.output_type == "error":
                print(f"Error: {output.ename}")
                print(f"Message: {output.evalue}")
                print("Traceback:")
                for line in output.traceback:
                    print(line)
except Exception as e:
    print(f"Execution failed: {e}")

JavaScript Errors

result = client.nodejs.execute_nodejs_code(
    code="throw new Error('Something went wrong');"
)

if result.status == "error":
    print(f"Error output: {result.stderr}")
    print(f"Exit code: {result.exit_code}")

    # Check outputs for error details
    for output in result.outputs:
        if output.output_type == "error":
            print(f"Error: {output.ename}: {output.evalue}")

Best Practices

1. Session Management

  • Use sessions for related computations that share state
  • Clean up sessions when done to free resources
  • Sessions auto-expire after 30 minutes of inactivity

2. Timeout Configuration

  • Set appropriate timeouts for long-running operations
  • Default timeout is 30 seconds, maximum is 300 seconds
  • Consider breaking very long computations into smaller chunks

3. Resource Usage

  • Be mindful of memory usage in persistent sessions
  • Node.js environments are fresh for each execution
  • Clean up large variables in Jupyter sessions when not needed

4. Error Recovery

# Robust execution with error handling
def execute_with_retry(code, max_retries=3):
    for attempt in range(max_retries):
        try:
            result = client.jupyter.execute_code(
                code=code,
                timeout=60
            )

            if result.status == "ok":
                return result
            elif result.status == "timeout":
                print(f"Timeout on attempt {attempt + 1}")
                continue
            else:
                # Handle error
                print(f"Error on attempt {attempt + 1}")
                break
        except Exception as e:
            print(f"Exception on attempt {attempt + 1}: {e}")
            if attempt == max_retries - 1:
                raise

    return None

5. Output Processing

def process_outputs(result):
    """Extract and organize different output types"""
    stdout = []
    stderr = []
    results = []
    errors = []

    for output in result.outputs:
        if output.output_type == "stream":
            if output.name == "stdout":
                stdout.append(output.text)
            elif output.name == "stderr":
                stderr.append(output.text)
        elif output.output_type == "execute_result":
            results.append(output.data)
        elif output.output_type == "error":
            errors.append({
                "name": output.ename,
                "value": output.evalue,
                "traceback": output.traceback
            })

    return {
        "stdout": "".join(stdout),
        "stderr": "".join(stderr),
        "results": results,
        "errors": errors
    }

API Reference

Jupyter Endpoints

EndpointMethodDescription
/v1/jupyter/executePOSTExecute Python code
/v1/jupyter/infoGETGet Jupyter environment info
/v1/jupyter/sessionsGETList active sessions
/v1/jupyter/sessionsDELETEClean up all sessions
/v1/jupyter/sessions/{id}DELETEClean up specific session

Node.js Endpoints

EndpointMethodDescription
/v1/nodejs/executePOSTExecute JavaScript code
/v1/nodejs/infoGETGet Node.js runtime info

Response Models

JupyterExecuteResponse

interface JupyterExecuteResponse {
  kernel_name: string;      // Kernel used for execution
  session_id: string;        // Session identifier
  status: string;            // 'ok', 'error', or 'timeout'
  execution_count?: number;  // Execution counter
  outputs: JupyterOutput[];  // Execution outputs
  code: string;              // Executed code
  msg_id?: string;           // Message ID
}

NodeJSExecuteResponse

interface NodeJSExecuteResponse {
  language: string;          // Always 'javascript'
  status: string;            // 'ok', 'error', or 'timeout'
  execution_count?: number;  // Execution counter
  outputs: NodeJSOutput[];   // Execution outputs
  code: string;              // Executed code
  stdout: string;            // Standard output
  stderr: string;            // Standard error
  exit_code: number;         // Process exit code
}

Next Steps