Langchain for Sandboxes - A unified Python interface for sandbox providers
Grainchain provides a clean, consistent API for interacting with various sandbox providers, enabling developers to write code once and run it across multiple sandbox environments. Just like Langchain abstracts LLM providers, Grainchain abstracts sandbox providers.
import asyncio
from grainchain import Sandbox
async def main():
# Create a sandbox with the default provider
async with Sandbox() as sandbox:
# Execute code
result = await sandbox.execute("echo 'Hello, Grainchain!'")
print(result.stdout) # "Hello, Grainchain!"
# Upload and run a Python script
await sandbox.upload_file("script.py", "print('Hello from Python!')")
result = await sandbox.execute("python script.py")
print(result.stdout) # "Hello from Python!"
asyncio.run(main())
Before using Grainchain, check which sandbox providers are available and properly configured:
# Check all providers
grainchain providers
# Show detailed setup instructions
grainchain providers --verbose
# Check specific provider
grainchain providers --check e2b
# Show only available providers
grainchain providers --available-only
Example output:
๐ง Grainchain Sandbox Providers
๐ Default provider: local โ
โ
LOCAL
Dependencies: โ
Configuration: โ
โ E2B
Dependencies: โ
Install: pip install grainchain[e2b]
Configuration: โ
Missing: E2B_API_KEY
Setup:
Set the following environment variables:
export E2B_API_KEY='your-e2b-api-key-here'
๐ Summary: 1/5 providers available
from grainchain import get_providers_info, get_available_providers, check_provider
# Get all provider information
providers = get_providers_info()
for name, info in providers.items():
print(f"{name}: {'๏ฟฝ๏ฟฝ๏ฟฝ' if info.available else 'โ'}")
# Get only available providers
available = get_available_providers()
print(f"Ready to use: {', '.join(available)}")
# Check specific provider
e2b_info = check_provider("e2b")
if not e2b_info.available:
print(f"E2B setup needed: {e2b_info.missing_config}")
Provider | Dependencies | Environment Variables | Install Command |
---|---|---|---|
Local | None | None | Built-in โ |
E2B | e2b |
E2B_API_KEY |
pip install grainchain[e2b] |
Modal | modal |
MODAL_TOKEN_ID , MODAL_TOKEN_SECRET |
pip install grainchain[modal] |
Daytona | daytona |
DAYTONA_API_KEY |
pip install daytona-sdk |
Morph | morphcloud |
MORPH_API_KEY |
pip install morphcloud |
Compare sandbox providers with comprehensive performance testing:
# Test individual providers
grainchain benchmark --provider local
grainchain benchmark --provider e2b
grainchain benchmark --provider daytona
grainchain benchmark --provider morph
# Generate timestamped results
grainchain benchmark --provider local --output benchmarks/results/
# Check latest benchmark status (without running new tests)
./scripts/benchmark_status.sh
Run comprehensive benchmarks across all providers:
# Quick: Run all providers and save results
for provider in local e2b daytona morph; do
echo "๐ Testing $provider..."
grainchain benchmark --provider $provider --output benchmarks/results/
done
# Comprehensive: Generate a full report that can be committed
./scripts/benchmark_all.sh
# Advanced: Use the detailed benchmark script
./benchmarks/scripts/run_grainchain_benchmark.sh "local e2b daytona morph" 3
The benchmark_all.sh
script generates timestamped reports in benchmarks/results/
that include:
- Performance comparison tables
- Environment details (OS, commit hash)
- Analysis and recommendations
- Raw benchmark data for tracking trends
Latest benchmark results (updated 2024-05-31):
Provider | Total Time | Basic Echo | Python Test | File Ops | Performance |
---|---|---|---|---|---|
Local | 0.036s | 0.007s | 0.021s | 0.008s | โก Fastest |
E2B | 0.599s | 0.331s | 0.111s | 0.156s | ๐ Balanced |
Daytona | 1.012s | 0.305s | 0.156s | 0.551s | ๐ก๏ธ Comprehensive |
Morph | 0.250s | 0.005s | 0.010s | 0.005s | ๐ Instant Snapshots |
Performance Notes:
- Local: Best for development/testing (17x faster than E2B, 28x faster than Daytona)
- E2B: Production-ready with good speed and reliability
- Daytona: Full workspace environments with comprehensive tooling
- Morph: Custom base images, instant snapshots, <250ms startup
Results are automatically saved to benchmarks/results/
and can be committed to track performance over time.
The sandbox ecosystem is rapidly expanding with providers like E2B, Daytona, Morph, and others. Each has different APIs and capabilities, creating:
- Vendor Lock-in: Applications become tightly coupled to specific providers
- Learning Curve: Developers must learn multiple APIs
- Migration Complexity: Switching providers requires significant code changes
- Testing Challenges: Testing across multiple providers is cumbersome
Grainchain solves these problems with a unified interface that abstracts provider-specific implementations.
โโโโโโโโโโโโโโโโโโโ
โ Application โ
๏ฟฝ๏ฟฝ๏ฟฝ๏ฟฝ๏ฟฝ๏ฟฝ๏ฟฝโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโ๏ฟฝ๏ฟฝ๏ฟฝโโโโโโโ
โ Grainchain โ
โ Core API โ
โโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโ
โ Provider โ
โ Adapters โ
โโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโ
โ Sandbox โ
โ Providers โ
โ (E2B, Daytona) โ
โโโโโโโโโโโโโโโโโโโ
# Basic installation
pip install grainchain
# With E2B support
pip install grainchain[e2b]
# With Daytona support
pip install grainchain[daytona]
# With Morph support
pip install grainchain[morph]
# With Local provider support
pip install grainchain[local]
# With Docker provider support
pip install grainchain[docker]
# With all sandbox providers
pip install grainchain[all]
# For benchmarking (docker, psutil)
pip install grainchain[benchmark]
# For data science examples (numpy, pandas, matplotlib)
pip install grainchain[examples]
# Clone the repository
git clone https://github.com/codegen-sh/grainchain.git
cd grainchain
# Set up development environment with uv
uv venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Install core development dependencies
uv sync --extra dev
# Optional: Install benchmarking tools (if you need docker benchmarks)
uv sync --extra benchmark
# Optional: Install data science dependencies (if you need examples)
uv sync --extra examples
# Or install everything
uv sync --all-extras
# Install pre-commit hooks
grainchain install-hooks
Provider | Status | Features |
---|---|---|
E2B | โ Supported | Code interpreter, custom images, file operations |
Daytona | โ Supported | Development environments, workspace management |
Morph | โ Supported | Custom base images, instant snapshots, <250ms startup |
Local | โ Supported | Local development and testing |
Docker | ๐ง Planned | Local Docker containers |
If you encounter SSL certificate errors with Daytona:
SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate
This typically indicates:
- Development Environment: The API endpoint may be using self-signed certificates
- API Key Environment: Ensure your API key matches the intended environment (production vs staging)
- Network Issues: Check if you're behind a corporate firewall
Solution: Verify your Daytona API key is for the correct environment and contact Daytona support if the issue persists.
Morph.so provides instant snapshots and custom base images with <250ms startup times. Key configuration options:
from grainchain import Sandbox, SandboxConfig
# Basic Morph configuration
config = SandboxConfig(
provider_config={
"image_id": "morphvm-minimal", # or your custom base image
"vcpus": 2, # CPU cores
"memory": 2048, # Memory in MB
"disk_size": 8192, # Disk size in MB
}
)
async with Sandbox(provider="morph", config=config) as sandbox:
# Your code here
pass
Key Features:
- Custom Base Images: Use
image_id
to specify your custom-configured base image - Instant Snapshots: Create and restore snapshots in milliseconds
- Fast Startup: <250ms startup times for rapid development cycles
- Resource Control: Fine-tune CPU, memory, and disk allocation
Environment Variables:
export MORPH_API_KEY=your-morph-api-key
from grainchain import Sandbox
# Use default provider (configured via environment or config file)
async with Sandbox() as sandbox:
result = await sandbox.execute("pip install requests")
result = await sandbox.execute("python -c 'import requests; print(requests.__version__)'")
from grainchain import Sandbox
# Use specific provider
async with Sandbox(provider="e2b") as sandbox:
result = await sandbox.execute("echo 'Using E2B'")
async with Sandbox(provider="daytona") as sandbox:
result = await sandbox.execute("echo 'Using Daytona'")
async with Sandbox(provider="local") as sandbox:
result = await sandbox.execute("echo 'Using Local'")
async with Sandbox(provider="morph") as sandbox:
result = await sandbox.execute("echo 'Using Morph'")
from grainchain import Sandbox, SandboxConfig
config = SandboxConfig(
timeout=300,
memory_limit="2GB",
cpu_limit=2.0,
environment_vars={"API_KEY": "secret"},
working_directory="/workspace"
)
async with Sandbox(provider="e2b", config=config) as sandbox:
result = await sandbox.execute("echo $API_KEY")
async with Sandbox() as sandbox:
# Upload files
await sandbox.upload_file("data.csv", csv_content)
await sandbox.upload_file("script.py", python_code)
# Execute uploaded script
result = await sandbox.execute("python script.py")
# Download results
output = await sandbox.download_file("results.json")
# List files
files = await sandbox.list_files("/workspace")
for file in files:
print(f"{file.name}: {file.size} bytes")
async with Sandbox(provider="local") as sandbox:
# Set up environment
await sandbox.execute("pip install numpy")
await sandbox.upload_file("data.py", "import numpy as np")
# Create snapshot
snapshot_id = await sandbox.create_snapshot()
# Make changes
await sandbox.execute("pip install pandas")
# Restore to snapshot
await sandbox.restore_snapshot(snapshot_id)
# Default provider
export GRAINCHAIN_DEFAULT_PROVIDER=e2b
# E2B configuration
export E2B_API_KEY=your-e2b-key
export E2B_TEMPLATE=python-data-science
# Daytona configuration
export DAYTONA_API_KEY=your-daytona-key
export DAYTONA_WORKSPACE_TEMPLATE=python-dev
# Morph configuration
export MORPH_API_KEY=your-morph-key
export MORPH_TEMPLATE=custom-base-image
Create grainchain.yaml
in your project root:
default_provider: e2b
providers:
e2b:
api_key: ${E2B_API_KEY}
template: python-data-science
timeout: 300
daytona:
api_key: ${DAYTONA_API_KEY}
timeout: 300
morph:
api_key: ${MORPH_API_KEY}
template: custom-base-image
timeout: 300
sandbox_defaults:
timeout: 180
working_directory: /workspace
auto_cleanup: true
Check out the examples directory for comprehensive usage examples:
basic_usage.py
- Core functionality and provider usagedata_analysis.py
- Data science workflow example
# Set up development environment
uv venv
source .venv/bin/activate
uv sync --all-extras
# Install pre-commit hooks
grainchain install-hooks
# Run tests
grainchain test
# Run tests with coverage
grainchain test --cov
# Format and fix code
grainchain format
# Lint code
grainchain lint --fix
# Type check (currently disabled)
grainchain typecheck
# Run all quality checks
grainchain check
# Run benchmarks
grainchain benchmark --provider local
# Generate comprehensive performance report (committable)
./scripts/benchmark_all.sh
# Check latest performance status
./scripts/benchmark_status.sh
Grainchain includes a comprehensive CLI for development:
grainchain --help # Show all commands
grainchain providers # Check provider availability
grainchain providers --verbose # Show detailed setup instructions
grainchain test # Run pytest
grainchain test --cov # Run tests with coverage
grainchain lint # Run ruff linting
grainchain format # Format with ruff
grainchain typecheck # Type checking (temporarily disabled)
grainchain benchmark # Run performance benchmarks
grainchain install-hooks # Install pre-commit hooks
grainchain check # Run all quality checks
All code is automatically checked with:
- Ruff - Fast Python linting, formatting, and import sorting
- mypy - Static type checking (temporarily disabled)
- Pre-commit hooks - Automated quality checks
- Core interface design
- Base provider abstraction
- Configuration system
- E2B provider implementation
- Daytona provider implementation
- Morph provider implementation
- Local provider for testing
- Comprehensive test suite
- Error handling improvements
- Performance optimizations
- Documentation website
- Docker provider
- Plugin system for custom providers
- Monitoring and observability
- Cost optimization features
We welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create a feature branch
- Set up development environment:
uv sync --all-extras
- Make your changes
- Run quality checks:
grainchain check
- Submit a pull request
MIT License - see LICENSE for details.
- Inspired by Langchain for LLM abstraction
- Built for the E2B, Daytona, and Morph communities
- Thanks to all contributors and early adopters
Built with โค๏ธ by the Codegen team