// Execute AI-generated code in secure isolated E2B cloud sandboxes with advanced monitoring, MCP gateway integration (200+ tools), and multi-language support. Use for running Python/JavaScript/TypeScript/Bash code, managing sandbox lifecycle (create, pause, resume, kill, list, connect), monitoring metrics (CPU, memory, disk), handling lifecycle events, uploading/downloading files, streaming command output, environment variable management, and integrating LLMs with code execution capabilities.
| name | e2b-sandbox |
| description | Execute AI-generated code in secure isolated E2B cloud sandboxes with advanced monitoring, MCP gateway integration (200+ tools), and multi-language support. Use for running Python/JavaScript/TypeScript/Bash code, managing sandbox lifecycle (create, pause, resume, kill, list, connect), monitoring metrics (CPU, memory, disk), handling lifecycle events, uploading/downloading files, streaming command output, environment variable management, and integrating LLMs with code execution capabilities. |
This skill provides comprehensive guidance for using E2B sandboxes - secure, isolated cloud VMs for executing AI-generated code with advanced monitoring, event handling, and integration capabilities.
E2B provides secure isolated sandboxes (small VMs) in the cloud that start very quickly (~150ms). Each sandbox has:
Creating a Sandbox:
from e2b_code_interpreter import Sandbox
# Create with default 5 minute timeout
sandbox = Sandbox.create()
# Create with custom timeout (in seconds)
sandbox = Sandbox.create(timeout=60)
# With auto-pause (beta)
sandbox = Sandbox.beta_create(
auto_pause=True,
timeout=10 * 60 # 10 minutes
)
# With metadata for tracking
sandbox = Sandbox.create(
metadata={'userId': '123', 'env': 'dev'}
)
# With environment variables
sandbox = Sandbox.create(
envs={'API_KEY': 'secret_value'}
)
JavaScript:
import { Sandbox } from '@e2b/code-interpreter'
// Create with metadata and env vars
const sandbox = await Sandbox.create({
timeout: 60000, // milliseconds
metadata: { userId: '123' },
envs: { API_KEY: 'secret_value' }
})
Changing Timeout During Runtime:
# Reset timeout to 30 seconds from now
sandbox.set_timeout(30)
Getting Sandbox Info:
info = sandbox.get_info()
# Returns: sandboxId, templateId, name, metadata, startedAt, endAt
Shutting Down:
# Terminate sandbox immediately
sandbox.kill()
# Or kill by ID
Sandbox.kill(sandbox_id)
List Sandboxes:
# List with pagination
paginator = Sandbox.list()
sandboxes = paginator.next_items()
# Filter by state
paginator = Sandbox.list(query={'state': ['running', 'paused']})
# Filter by metadata
paginator = Sandbox.list(
query={'metadata': {'userId': '123', 'env': 'dev'}}
)
# Advanced pagination
paginator = Sandbox.list(limit=100, next_token='<token>')
while paginator.has_next:
items = paginator.next_items()
Connect to Running Sandbox:
# Connect by ID
sandbox = Sandbox.connect(sandbox_id)
# Or reconnect to current
sandbox = sandbox.connect()
JavaScript:
// List and filter
const paginator = Sandbox.list({
query: {
state: ['running'],
metadata: { userId: '123' }
}
})
const sandboxes = await paginator.nextItems()
// Connect to existing
const sandbox = await Sandbox.connect(sandboxId)
Get Sandbox Metrics:
import time
# Wait for metrics to collect (every 5 seconds)
time.sleep(10)
metrics = sandbox.get_metrics()
# Returns: [{timestamp, cpuUsedPct, cpuCount, memUsed, memTotal, diskUsed, diskTotal}]
# Or by ID
metrics = Sandbox.get_metrics(sandbox_id)
JavaScript:
await new Promise(resolve => setTimeout(resolve, 10000))
const metrics = await sandbox.getMetrics()
// Returns array of timestamped metrics
CLI:
e2b sandbox metrics <sandbox_id>
# Shows: CPU, Memory, Disk usage over time
Lifecycle Events (REST API):
import requests
# Get events for specific sandbox
response = requests.get(
f'https://api.e2b.app/events/sandboxes/{sandbox_id}',
headers={'X-API-Key': E2B_API_KEY}
)
events = response.json()
# Get latest 10 events for all sandboxes
response = requests.get(
'https://api.e2b.app/events/sandboxes?limit=10',
headers={'X-API-Key': E2B_API_KEY}
)
Event types: sandbox.lifecycle.created, sandbox.lifecycle.updated, sandbox.lifecycle.paused, sandbox.lifecycle.resumed, sandbox.lifecycle.killed
See docs/monitoring-and-events.md for webhook configuration.
Execute Python Code (Default):
# Run Python code and get results
execution = sandbox.run_code('print("hello world")')
# Access results
print(execution.text) # Combined output text
print(execution.logs.stdout) # Standard output
print(execution.logs.stderr) # Standard error
print(execution.results) # Execution results (charts, tables, etc.)
print(execution.error) # Runtime errors if any
Execute JavaScript/TypeScript:
# JavaScript
execution = sandbox.run_code(
'console.log("Hello from JS")',
language='javascript' # or 'js'
)
# TypeScript with top-level await and ESM imports
execution = sandbox.run_code('''
import axios from "axios";
const response = await axios.get("https://api.github.com/status");
response.data;
''', language='typescript') # or 'ts'
Execute Bash:
execution = sandbox.run_code(
'ls -la /home/user',
language='bash'
)
With Environment Variables:
# Scoped to this execution only
execution = sandbox.run_code(
'import os; print(os.environ.get("MY_VAR"))',
envs={'MY_VAR': 'my_value'}
)
JavaScript:
// Python (default)
const exec = await sandbox.runCode('print("hello")')
// JavaScript/TypeScript
const exec = await sandbox.runCode('console.log("hello")', {
language: 'js',
envs: { MY_VAR: 'value' }
})
Execute Bash Commands:
# Run terminal commands
result = sandbox.commands.run('ls -l')
print(result)
# With environment variables
result = sandbox.commands.run(
'echo $MY_VAR',
envs={'MY_VAR': '123'}
)
Streaming Output:
# Stream stdout/stderr in real-time
process = sandbox.commands.run(
'for i in {1..5}; do echo "Line $i"; sleep 1; done',
on_stdout=lambda data: print(f"OUT: {data}"),
on_stderr=lambda data: print(f"ERR: {data}")
)
Background Commands:
# Run in background, returns immediately
command = sandbox.commands.run(
'echo hello; sleep 10; echo world',
background=True,
on_stdout=lambda data: print(data)
)
# Kill later
command.kill()
JavaScript:
// Streaming
await sandbox.commands.run('echo hello', {
onStdout: (data) => console.log(data),
onStderr: (data) => console.error(data)
})
// Background
const cmd = await sandbox.commands.run('sleep 100', {
background: true
})
await cmd.kill()
Three scoping levels:
sandbox = Sandbox.create(envs={'API_KEY': 'value'})
sandbox.run_code(code, envs={'MY_VAR': 'value'})
sandbox.commands.run(cmd, envs={'MY_VAR': 'value'})
Default Environment Variables:
E2B_SANDBOX=true - Indicates code is running in E2BE2B_SANDBOX_ID - Current sandbox IDE2B_TEAM_ID - Team ID that created sandboxE2B_TEMPLATE_ID - Template used for sandboxUpload Files:
import fs
# Read local file
content = fs.read_file('local/file.csv')
# Upload to sandbox (absolute path required)
file_info = sandbox.files.write('/home/user/data.csv', content)
print(file_info.path) # Path in sandbox
Download Files:
# Download file from sandbox
content = sandbox.files.read('/home/user/output.png')
# Save locally
fs.write_file('local/output.png', content)
List Files:
# List files in directory
files = sandbox.files.list('/')
for file in files:
print(file)
Watch for Changes:
# Monitor filesystem changes
watcher = sandbox.files.watch('/home/user')
watcher.on_change(lambda event: print(f"Changed: {event}"))
See docs/filesystem.md for complete filesystem API.
Pause and Resume:
# Pause sandbox (saves filesystem + memory state)
sandbox.beta_pause()
print(f"Paused sandbox: {sandbox.sandbox_id}")
# Resume later by reconnecting
resumed = sandbox.connect()
# Or connect by ID
resumed = Sandbox.connect(sandbox_id)
List Paused Sandboxes:
# Get paginated list of paused sandboxes
paginator = Sandbox.list(query={'state': ['paused']})
sandboxes = paginator.next_items()
Important Notes:
E2B provides built-in access to 200+ MCP (Model Context Protocol) servers for integrating external tools.
Enable MCP Servers:
# Python (JS SDK)
sandbox = Sandbox.create(
mcp={
'browserbase': {
'apiKey': os.environ['BROWSERBASE_API_KEY'],
'geminiApiKey': os.environ['GEMINI_API_KEY'],
'projectId': os.environ['BROWSERBASE_PROJECT_ID']
},
'exa': {'apiKey': os.environ['EXA_API_KEY']},
'notion': {'internalIntegrationToken': os.environ['NOTION_API_KEY']}
}
)
# Get MCP URL and token
mcp_url = sandbox.get_mcp_url()
mcp_token = sandbox.get_mcp_token()
Connect from Outside Sandbox:
import { Client } from '@modelcontextprotocol/sdk/client/index.js'
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'
const client = new Client({ name: 'e2b-mcp-client', version: '1.0.0' })
const transport = new StreamableHTTPClientTransport(
new URL(sandbox.getMcpUrl()),
{
requestInit: {
headers: { 'Authorization': `Bearer ${await sandbox.getMcpToken()}` }
}
}
)
await client.connect(transport)
const tools = await client.listTools()
MCP Server Categories:
See docs/mcp-gateway.md for complete list and configuration.
Build custom sandbox environments with specific dependencies:
# Using E2B CLI
e2b template build
# Specify CPU/RAM in e2b.toml
cpu_count = 2
memory_mb = 2048
# Add start commands
start_cmd = "python app.py"
# Add readiness checks
ready_cmd = "curl localhost:8000/health"
See docs/custom-templates.md for Build System 2.0 details.
# Authenticate
e2b auth login
# List sandboxes
e2b sandbox list
# Get metrics
e2b sandbox metrics <sandbox_id>
# Build custom template
e2b template build
# Connect to sandbox
e2b sandbox connect <sandbox_id>
E2B works with any LLM via tool use (function calling). The general pattern:
Example with Tool Use:
from anthropic import Anthropic
from e2b_code_interpreter import Sandbox
# Define tool
tools = [{
"name": "execute_python",
"description": "Execute python code in a Jupyter notebook cell and return result",
"input_schema": {
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "The python code to execute in a single cell"
}
},
"required": ["code"]
}
}]
# Create Anthropic client
client = Anthropic()
# Send message with tools
message = client.messages.create(
model="claude-3-5-sonnet-20240620",
max_tokens=1024,
messages=[{
"role": "user",
"content": "Calculate how many r's are in the word 'strawberry'"
}],
tools=tools
)
# Execute tool if called
if message.stop_reason == "tool_use":
tool_use = next(block for block in message.content if block.type == "tool_use")
if tool_use.name == "execute_python":
with Sandbox.create() as sandbox:
code = tool_use.input['code']
execution = sandbox.run_code(code)
result = execution.text
print(result)
For data analysis workflows:
# Upload dataset
content = fs.read_file('dataset.csv')
dataset_path = sandbox.files.write('/home/user/dataset.csv', content)
# Run analysis code (generated by LLM)
execution = sandbox.run_code(analysis_code)
# Extract chart if generated
for result in execution.results:
if result.png:
# PNG is base64 encoded
fs.write_file('chart.png', result.png, encoding='base64')
# Create sandbox per user with metadata
sandbox = Sandbox.create(
metadata={'userId': user_id, 'sessionId': session_id}
)
# Later: Find user's sandboxes
paginator = Sandbox.list(
query={'metadata': {'userId': user_id}}
)
user_sandboxes = paginator.next_items()
# Reconnect to existing session
if user_sandboxes:
sandbox = Sandbox.connect(user_sandboxes[0].sandbox_id)
# Use context manager (recommended)
with Sandbox.create() as sandbox:
# Your code here
pass # Sandbox automatically killed on exit
# Or manually
sandbox = Sandbox.create()
try:
# Your code here
pass
finally:
sandbox.kill()
Set appropriate timeouts:
Use persistence wisely:
Monitor resource usage:
# Check metrics before intensive operations
metrics = sandbox.get_metrics()
if metrics:
latest = metrics[-1]
if latest['cpuUsedPct'] > 80:
print("Warning: High CPU usage")
execution = sandbox.run_code(code)
if execution.error:
print(f"Error: {execution.error.name}")
print(f"Message: {execution.error.value}")
print(f"Traceback: {execution.error.traceback}")
else:
print(execution.text)
for result in execution.results:
if result.png:
# Handle chart/image
save_image(result.png)
elif result.text:
# Handle text output
print(result.text)
# Python for data analysis
sandbox.run_code('import pandas as pd; df.describe()')
# JavaScript for async API calls
sandbox.run_code('await fetch(url)', language='js')
# Bash for system operations
sandbox.run_code('tar -xzf archive.tar.gz', language='bash')
# Good
sandbox.files.write('/home/user/data.csv', content)
# Bad (relative paths may not work as expected)
sandbox.files.write('data.csv', content)
# Upload dataset first
sandbox.files.write('/home/user/data.csv', dataset)
# Then run code that uses it
code = "import pandas as pd; df = pd.read_csv('/home/user/data.csv')"
sandbox.run_code(code)
# Tag sandboxes with identifying information
sandbox = Sandbox.create(metadata={
'userId': '123',
'purpose': 'data-analysis',
'created': datetime.now().isoformat()
})
# Find and reconnect
paginator = Sandbox.list(query={'metadata': {'userId': '123'}})
# Find all running sandboxes
paginator = Sandbox.list(query={'state': ['running']})
sandboxes = paginator.next_items()
# Kill old ones
for sbx in sandboxes:
if should_cleanup(sbx):
Sandbox.kill(sbx.sandbox_id)
with Sandbox.create() as sandbox:
result = sandbox.run_code(llm_generated_code)
return result.text
sandbox = Sandbox.create(timeout=300)
try:
# Step 1: Upload data
sandbox.files.write('/home/user/data.csv', data)
# Step 2: Load and explore
sandbox.run_code("import pandas as pd; df = pd.read_csv('/home/user/data.csv')")
# Step 3: Analyze (code from LLM)
result = sandbox.run_code(analysis_code)
# Step 4: Extract results
for r in result.results:
if r.png:
save_chart(r.png)
finally:
sandbox.kill()
# Initial creation
sandbox = Sandbox.beta_create(auto_pause=True, timeout=600)
# Do some work
sandbox.run_code(initial_code)
# Pause when user is inactive
sandbox.beta_pause()
save_sandbox_id(sandbox.sandbox_id)
# Later: Resume when user returns
sandbox = Sandbox.connect(saved_sandbox_id)
sandbox.run_code(next_code)
// Create sandbox with MCP servers
const sandbox = await Sandbox.create({
mcp: {
github: { githubPersonalAccessToken: process.env.GITHUB_TOKEN },
slack: { botToken: process.env.SLACK_BOT_TOKEN }
}
})
// Connect MCP client
const client = new Client({ name: 'app', version: '1.0.0' })
const transport = new StreamableHTTPClientTransport(
new URL(sandbox.getMcpUrl()),
{ requestInit: { headers: { 'Authorization': `Bearer ${await sandbox.getMcpToken()}` }}}
)
await client.connect(transport)
// List available tools
const tools = await client.listTools()
Required environment variable:
E2B_API_KEY=e2b_***
Get your API key from: https://e2b.dev/dashboard?tab=keys
# Python
pip install e2b-code-interpreter
# JavaScript/TypeScript
npm i @e2b/code-interpreter
| Operation | Python | JavaScript |
|---|---|---|
| Create | Sandbox.create() | await Sandbox.create() |
| Set timeout | sandbox.set_timeout(60) | await sandbox.setTimeout(60000) (milliseconds) |
| Get info | sandbox.get_info() | await sandbox.getInfo() |
| Run code | sandbox.run_code(code) | await sandbox.runCode(code) |
| Run command | sandbox.commands.run(cmd) | await sandbox.commands.run(cmd) |
| Get metrics | sandbox.get_metrics() | await sandbox.getMetrics() |
| List sandboxes | Sandbox.list() | Sandbox.list() |
| Connect | Sandbox.connect(id) | await Sandbox.connect(id) |
| Kill | sandbox.kill() | await sandbox.kill() |
| Pause | sandbox.beta_pause() | await sandbox.betaPause() |
Sandbox.create(timeout=300)sandbox.set_timeout(300)execution.error for details/home/user/filenamesandbox.files.list('/home/user')NotFoundException when connectingsandbox.get_metrics()npx @modelcontextprotocol/inspectorFor detailed API documentation and additional examples: