| 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. |
E2B Sandbox Skill
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.
What is E2B?
E2B provides secure isolated sandboxes (small VMs) in the cloud that start very quickly (~150ms). Each sandbox has:
- Isolated filesystem (1GB Hobby tier, 5GB Pro tier)
- Full code execution capabilities (Python, JavaScript, TypeScript, Bash)
- Default lifetime of 5 minutes (configurable)
- Network access capabilities
- Real-time metrics monitoring (CPU, memory, disk)
- Lifecycle event tracking and webhooks
- MCP Gateway for 200+ tool integrations
Core Concepts
Sandbox Lifecycle
Creating a Sandbox:
from e2b_code_interpreter import Sandbox
sandbox = Sandbox.create()
sandbox = Sandbox.create(timeout=60)
sandbox = Sandbox.beta_create(
auto_pause=True,
timeout=10 * 60
)
sandbox = Sandbox.create(
metadata={'userId': '123', 'env': 'dev'}
)
sandbox = Sandbox.create(
envs={'API_KEY': 'secret_value'}
)
JavaScript:
import { Sandbox } from '@e2b/code-interpreter'
const sandbox = await Sandbox.create({
timeout: 60000,
metadata: { userId: '123' },
envs: { API_KEY: 'secret_value' }
})
Changing Timeout During Runtime:
sandbox.set_timeout(30)
Getting Sandbox Info:
info = sandbox.get_info()
Shutting Down:
sandbox.kill()
Sandbox.kill(sandbox_id)
Sandbox Management
List Sandboxes:
paginator = Sandbox.list()
sandboxes = paginator.next_items()
paginator = Sandbox.list(query={'state': ['running', 'paused']})
paginator = Sandbox.list(
query={'metadata': {'userId': '123', 'env': 'dev'}}
)
paginator = Sandbox.list(limit=100, next_token='<token>')
while paginator.has_next:
items = paginator.next_items()
Connect to Running Sandbox:
sandbox = Sandbox.connect(sandbox_id)
sandbox = sandbox.connect()
JavaScript:
const paginator = Sandbox.list({
query: {
state: ['running'],
metadata: { userId: '123' }
}
})
const sandboxes = await paginator.nextItems()
const sandbox = await Sandbox.connect(sandboxId)
Monitoring & Metrics
Get Sandbox Metrics:
import time
time.sleep(10)
metrics = sandbox.get_metrics()
metrics = Sandbox.get_metrics(sandbox_id)
JavaScript:
await new Promise(resolve => setTimeout(resolve, 10000))
const metrics = await sandbox.getMetrics()
CLI:
e2b sandbox metrics <sandbox_id>
Lifecycle Events (REST API):
import requests
response = requests.get(
f'https://api.e2b.app/events/sandboxes/{sandbox_id}',
headers={'X-API-Key': E2B_API_KEY}
)
events = response.json()
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.
Running Code
Execute Python Code (Default):
execution = sandbox.run_code('print("hello world")')
print(execution.text)
print(execution.logs.stdout)
print(execution.logs.stderr)
print(execution.results)
print(execution.error)
Execute JavaScript/TypeScript:
execution = sandbox.run_code(
'console.log("Hello from JS")',
language='javascript'
)
execution = sandbox.run_code('''
import axios from "axios";
const response = await axios.get("https://api.github.com/status");
response.data;
''', language='typescript')
Execute Bash:
execution = sandbox.run_code(
'ls -la /home/user',
language='bash'
)
With Environment Variables:
execution = sandbox.run_code(
'import os; print(os.environ.get("MY_VAR"))',
envs={'MY_VAR': 'my_value'}
)
JavaScript:
const exec = await sandbox.runCode('print("hello")')
const exec = await sandbox.runCode('console.log("hello")', {
language: 'js',
envs: { MY_VAR: 'value' }
})
Running Commands
Execute Bash Commands:
result = sandbox.commands.run('ls -l')
print(result)
result = sandbox.commands.run(
'echo $MY_VAR',
envs={'MY_VAR': '123'}
)
Streaming Output:
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:
command = sandbox.commands.run(
'echo hello; sleep 10; echo world',
background=True,
on_stdout=lambda data: print(data)
)
command.kill()
JavaScript:
await sandbox.commands.run('echo hello', {
onStdout: (data) => console.log(data),
onStderr: (data) => console.error(data)
})
const cmd = await sandbox.commands.run('sleep 100', {
background: true
})
await cmd.kill()
Environment Variables
Three scoping levels:
- Global (sandbox-wide):
sandbox = Sandbox.create(envs={'API_KEY': 'value'})
- Code execution scope:
sandbox.run_code(code, envs={'MY_VAR': 'value'})
- Command execution scope:
sandbox.commands.run(cmd, envs={'MY_VAR': 'value'})
Default Environment Variables:
E2B_SANDBOX=true - Indicates code is running in E2B
E2B_SANDBOX_ID - Current sandbox ID
E2B_TEAM_ID - Team ID that created sandbox
E2B_TEMPLATE_ID - Template used for sandbox
File Operations
Upload Files:
import fs
content = fs.read_file('local/file.csv')
file_info = sandbox.files.write('/home/user/data.csv', content)
print(file_info.path)
Download Files:
content = sandbox.files.read('/home/user/output.png')
fs.write_file('local/output.png', content)
List Files:
files = sandbox.files.list('/')
for file in files:
print(file)
Watch for Changes:
watcher = sandbox.files.watch('/home/user')
watcher.on_change(lambda event: print(f"Changed: {event}"))
See docs/filesystem.md for complete filesystem API.
Sandbox Persistence (Beta)
Pause and Resume:
sandbox.beta_pause()
print(f"Paused sandbox: {sandbox.sandbox_id}")
resumed = sandbox.connect()
resumed = Sandbox.connect(sandbox_id)
List Paused Sandboxes:
paginator = Sandbox.list(query={'state': ['paused']})
sandboxes = paginator.next_items()
Important Notes:
- Pausing takes ~4 seconds per 1 GiB of RAM
- Resuming takes ~1 second
- Sandbox can be used for up to 30 days
- When sandbox resumes, timeout resets to default (5 minutes) or custom value
Advanced Features
MCP Gateway (200+ Tool Integrations)
E2B provides built-in access to 200+ MCP (Model Context Protocol) servers for integrating external tools.
Enable MCP Servers:
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']}
}
)
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:
- Data & Databases: MongoDB, PostgreSQL, Redis, Elasticsearch, Astra DB
- Cloud: AWS, Azure, Google Cloud, Kubernetes
- Web & Content: Firecrawl, Brave Search, Perplexity, DuckDuckGo, Tavily
- Business: Slack, Notion, GitHub, Jira, Confluence, HubSpot
- Development: GitHub Chat, JetBrains IDE, ast-grep, Semgrep
- AI: OpenAI, Browserbase, Hugging Face, ElevenLabs
- Finance: Stripe, Razorpay, Mercado Pago
See docs/mcp-gateway.md for complete list and configuration.
Custom Templates
Build custom sandbox environments with specific dependencies:
e2b template build
cpu_count = 2
memory_mb = 2048
start_cmd = "python app.py"
ready_cmd = "curl localhost:8000/health"
See docs/custom-templates.md for Build System 2.0 details.
E2B CLI
e2b auth login
e2b sandbox list
e2b sandbox metrics <sandbox_id>
e2b template build
e2b sandbox connect <sandbox_id>
Integration Patterns
Connecting LLMs to E2B
E2B works with any LLM via tool use (function calling). The general pattern:
- Define a tool/function for code execution
- LLM generates code
- Execute code in E2B sandbox
- Return results to LLM
Example with Tool Use:
from anthropic import Anthropic
from e2b_code_interpreter import Sandbox
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"]
}
}]
client = Anthropic()
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
)
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)
Data Analysis Pattern
For data analysis workflows:
- Create sandbox
- Upload dataset
- LLM generates analysis code
- Execute in sandbox
- Extract results (charts, tables, data)
content = fs.read_file('dataset.csv')
dataset_path = sandbox.files.write('/home/user/dataset.csv', content)
execution = sandbox.run_code(analysis_code)
for result in execution.results:
if result.png:
fs.write_file('chart.png', result.png, encoding='base64')
Multi-User Session Management
sandbox = Sandbox.create(
metadata={'userId': user_id, 'sessionId': session_id}
)
paginator = Sandbox.list(
query={'metadata': {'userId': user_id}}
)
user_sandboxes = paginator.next_items()
if user_sandboxes:
sandbox = Sandbox.connect(user_sandboxes[0].sandbox_id)
Best Practices
Resource Management
- Always clean up sandboxes:
with Sandbox.create() as sandbox:
pass
sandbox = Sandbox.create()
try:
pass
finally:
sandbox.kill()
-
Set appropriate timeouts:
- Short tasks: 60-120 seconds
- Long-running analysis: 300-600 seconds
- Use auto-pause for interactive sessions
-
Use persistence wisely:
- Pause sandboxes between user interactions
- Don't pause for short breaks (<5 minutes)
- Kill sandboxes when truly done
-
Monitor resource usage:
metrics = sandbox.get_metrics()
if metrics:
latest = metrics[-1]
if latest['cpuUsedPct'] > 80:
print("Warning: High CPU usage")
Code Execution
- Handle errors gracefully:
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)
- Process results by type:
for result in execution.results:
if result.png:
save_image(result.png)
elif result.text:
print(result.text)
- Use appropriate language:
sandbox.run_code('import pandas as pd; df.describe()')
sandbox.run_code('await fetch(url)', language='js')
sandbox.run_code('tar -xzf archive.tar.gz', language='bash')
File Operations
- Always use absolute paths:
sandbox.files.write('/home/user/data.csv', content)
sandbox.files.write('data.csv', content)
- Upload files before executing code:
sandbox.files.write('/home/user/data.csv', dataset)
code = "import pandas as pd; df = pd.read_csv('/home/user/data.csv')"
sandbox.run_code(code)
Sandbox Discovery
- Use metadata for tracking:
sandbox = Sandbox.create(metadata={
'userId': '123',
'purpose': 'data-analysis',
'created': datetime.now().isoformat()
})
paginator = Sandbox.list(query={'metadata': {'userId': '123'}})
- Clean up orphaned sandboxes:
paginator = Sandbox.list(query={'state': ['running']})
sandboxes = paginator.next_items()
for sbx in sandboxes:
if should_cleanup(sbx):
Sandbox.kill(sbx.sandbox_id)
Common Patterns
Pattern 1: One-shot Code Execution
with Sandbox.create() as sandbox:
result = sandbox.run_code(llm_generated_code)
return result.text
Pattern 2: Multi-step Analysis
sandbox = Sandbox.create(timeout=300)
try:
sandbox.files.write('/home/user/data.csv', data)
sandbox.run_code("import pandas as pd; df = pd.read_csv('/home/user/data.csv')")
result = sandbox.run_code(analysis_code)
for r in result.results:
if r.png:
save_chart(r.png)
finally:
sandbox.kill()
Pattern 3: Interactive Session with Persistence
sandbox = Sandbox.beta_create(auto_pause=True, timeout=600)
sandbox.run_code(initial_code)
sandbox.beta_pause()
save_sandbox_id(sandbox.sandbox_id)
sandbox = Sandbox.connect(saved_sandbox_id)
sandbox.run_code(next_code)
Pattern 4: MCP Tool Integration
const sandbox = await Sandbox.create({
mcp: {
github: { githubPersonalAccessToken: process.env.GITHUB_TOKEN },
slack: { botToken: process.env.SLACK_BOT_TOKEN }
}
})
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)
const tools = await client.listTools()
Environment Variables
Required environment variable:
E2B_API_KEY=e2b_***
Get your API key from: https://e2b.dev/dashboard?tab=keys
SDK Installation
pip install e2b-code-interpreter
npm i @e2b/code-interpreter
API Differences: Python vs JavaScript
| 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() |
Troubleshooting
Sandbox Times Out Too Quickly
- Increase timeout on creation:
Sandbox.create(timeout=300)
- Or reset during runtime:
sandbox.set_timeout(300)
Code Execution Fails
- Check
execution.error for details
- Verify file paths are absolute
- Ensure required packages are available
- Check language parameter matches code type
Files Not Found
- Use absolute paths:
/home/user/filename
- Verify file was uploaded successfully
- Check file exists:
sandbox.files.list('/home/user')
Persistence Issues
- Sandboxes auto-delete after 30 days
- Check sandbox still exists before connecting
- Handle
NotFoundException when connecting
High Resource Usage
- Check metrics:
sandbox.get_metrics()
- Kill unused sandboxes
- Use smaller datasets or optimize code
MCP Connection Issues
- Verify API keys for MCP servers
- Check MCP URL and token are valid
- Use MCP Inspector for debugging:
npx @modelcontextprotocol/inspector
Reference Documentation
For detailed API documentation and additional examples: