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.

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 different Python versions (3.9, 3.10, 3.11, 3.12)
  • 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.9', 'python3.10', 'python3.11', 'python3.12']

# Use Python 3.9 for legacy compatibility
result_py39 = client.jupyter.execute_code(
    code="""
import sys
print(f"Python: {sys.version}")
# Use older syntax features
from typing import List  # Pre-3.10 style
def process(items: List[str]) -> None:
    for item in items:
        print(item)
process(['a', 'b', 'c'])
""",
    kernel_name="python3.9"
)

# 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