Skip to main content

Sandbox Providers

Wit supports two sandbox provider modes for running AI agents in isolated environments:
  • Docker: Self-hosted container-based sandboxes for local development and air-gapped environments
  • ComputeSDK: Cloud sandboxes via ComputeSDK - unified access to E2B, Daytona, Modal, CodeSandbox, Vercel, and more

Overview

Sandbox providers enable:
  • Secure code execution - Isolated environments prevent AI from affecting your local system
  • Full development environments - PTY support, file system access, and command execution
  • Resource limits - Control CPU, memory, and disk usage
  • Network isolation - Optional network restrictions for security

Available Providers

ProviderStartup TimeUse CaseSelf-hosted
Docker~2-5sLocal development, self-hostedYes
ComputeSDKVariesCloud sandboxes, GPU workloadsNo

ComputeSDK Underlying Providers

ComputeSDK provides unified access to multiple cloud providers:
ProviderVia ComputeSDKStartupBest For
E2B~150msAI code execution, secure sandboxing
Daytona~2sFull dev environments, PTY, git
Modal~2sGPU/ML workloads
CodeSandbox~2sCollaborative coding
Vercel~1sNode.js/Python ephemeral compute
BlaxelVariesAI-powered code execution

Docker Provider

Local container-based sandboxes using Docker. Best for self-hosted deployments.

Features

  • Full PTY support via docker exec
  • Resource limits (CPU, memory, disk)
  • Network isolation
  • Volume mounting for repository access
  • No external dependencies (self-hosted)

Configuration

import { DockerProvider } from 'wit/server/sandbox/providers/docker';

const docker = new DockerProvider({
  type: 'docker',
  options: {
    image: 'wit-sandbox:latest',
    socketPath: '/var/run/docker.sock',
    security: {
      dropCapabilities: true,
      runAsNonRoot: true,
      readOnlyRootFs: false,
      noNetwork: false,
    },
  },
});

await docker.initialize();

Environment Variables

SANDBOX_PROVIDER=docker
DOCKER_SOCKET_PATH=/var/run/docker.sock
DOCKER_HOST=unix:///var/run/docker.sock
SANDBOX_IMAGE=wit-sandbox:latest
DOCKER_NETWORK=bridge

Creating a Session

const session = await docker.createSession({
  sessionId: 'session-123',
  userId: 'user-456',
  repository: 'myrepo',
  pty: { cols: 120, rows: 30 },
  env: {
    NODE_ENV: 'development',
  },
});

// Execute commands
const result = await session.exec('npm', ['install']);
console.log(result.stdout);

// Interactive PTY
session.on('data', (data) => console.log(data.toString()));
session.sendInput('ls -la\n');

// Cleanup
await session.stop();

Building the Sandbox Image

# Dockerfile for wit-sandbox
FROM node:20-slim

# Install common development tools
RUN apt-get update && apt-get install -y \
    git \
    curl \
    python3 \
    && rm -rf /var/lib/apt/lists/*

# Create non-root user
RUN useradd -m -u 1000 sandbox
USER sandbox
WORKDIR /workspace

CMD ["tail", "-f", "/dev/null"]
docker build -t wit-sandbox:latest .

ComputeSDK Provider

Unified multi-provider access via ComputeSDK. Provides access to E2B, Daytona, Modal (GPU!), CodeSandbox, Vercel, and more through a single API.

Features

  • Unified API across all cloud providers
  • Zero-config auto-detection from environment variables
  • GPU access via Modal for ML workloads
  • Collaborative sandboxes via CodeSandbox
  • Seamless provider switching without code changes

Configuration

import { ComputeSDKProvider } from 'wit/server/sandbox/providers/computesdk';

const computesdk = new ComputeSDKProvider({
  type: 'computesdk',
  options: {
    // Explicit provider selection (or auto-detect from env)
    provider: 'modal', // 'e2b' | 'daytona' | 'modal' | 'codesandbox' | 'vercel' | 'blaxel'
    timeoutMs: 300000,
    autoDetect: true, // Auto-detect provider from environment
  },
});

await computesdk.initialize();

Environment Variables

# Select ComputeSDK as the provider
SANDBOX_PROVIDER=computesdk

# Optional: explicitly select underlying provider
COMPUTESDK_PROVIDER=modal

# Provider credentials (auto-detected):

# For Modal (GPU workloads)
MODAL_TOKEN_ID=your_modal_token_id
MODAL_TOKEN_SECRET=your_modal_token_secret

# For E2B (fast microVMs)
E2B_API_KEY=your_e2b_key

# For Daytona (full dev environments)
DAYTONA_API_KEY=your_daytona_key

# For CodeSandbox (collaboration)
CODESANDBOX_TOKEN=your_codesandbox_token

# For Vercel (ephemeral Node.js/Python)
VERCEL_TOKEN=your_vercel_token

Auto-Detection Order

ComputeSDK auto-detects the provider based on which credentials are present:
  1. Modal - MODAL_TOKEN_ID + MODAL_TOKEN_SECRET
  2. E2B - E2B_API_KEY
  3. Daytona - DAYTONA_API_KEY
  4. CodeSandbox - CODESANDBOX_TOKEN

Creating a Session

const session = await computesdk.createSession({
  sessionId: 'session-123',
  userId: 'user-456',
  env: {
    NODE_ENV: 'development',
  },
});

// Execute commands (works across all providers)
const result = await session.exec('python', ['--version']);
console.log(result.stdout);

// Run code directly
const codeResult = await session.runCode(`
import numpy as np
print(np.array([1, 2, 3]) * 2)
`, 'python');

// Cleanup
await session.stop();

GPU Workloads with Modal

# Set up Modal credentials
export SANDBOX_PROVIDER=computesdk
export MODAL_TOKEN_ID=your_token_id
export MODAL_TOKEN_SECRET=your_token_secret
// GPU-accelerated Python via Modal
const session = await manager.createSession({ userId: 'user-123' });

const result = await session.runCode(`
import torch
print(f"CUDA available: {torch.cuda.is_available()}")
print(f"GPU: {torch.cuda.get_device_name(0) if torch.cuda.is_available() else 'N/A'}")
`, 'python');

console.log(result.stdout);
// CUDA available: True
// GPU: NVIDIA A100-SXM4-40GB

Quick Start

Using the Manager

The recommended way to use sandboxes is through the SandboxManager:
import { createSandboxManagerFromEnv } from 'wit/server/sandbox';

// Creates manager based on SANDBOX_PROVIDER env var
const manager = createSandboxManagerFromEnv('/var/lib/repos');
await manager.initialize();

// Create a session
const session = await manager.createSession({
  userId: 'user-123',
  repository: 'my-repo',
});

// Execute code
const result = await session.exec('npm', ['run', 'build']);
console.log(result.stdout);

// Cleanup
await session.stop();
await manager.shutdown();

Environment-Based Configuration

# For self-hosted Docker
SANDBOX_PROVIDER=docker

# For cloud providers via ComputeSDK
SANDBOX_PROVIDER=computesdk
MODAL_TOKEN_ID=xxx  # or E2B_API_KEY, DAYTONA_API_KEY, etc.
MODAL_TOKEN_SECRET=xxx

Provider Comparison

When to Use Each Provider

ScenarioRecommended
Local developmentDocker
Self-hosted / air-gappedDocker
Fast iteration (CI/CD)ComputeSDK (E2B)
Production AI agentsComputeSDK (E2B or Vercel)
Full dev environmentComputeSDK (Daytona)
GPU/ML workloadsComputeSDK (Modal)
Collaborative codingComputeSDK (CodeSandbox)

Feature Comparison

FeatureDockerComputeSDK
PTY SupportYesYes (varies)
File OperationsYesYes
Code InterpreterNoYes
Network IsolationYesYes
GPU SupportNoYes (Modal)
Self-hostedYesNo
Multi-providerNoYes

Health Checks

All providers implement health checks:
const health = await provider.healthCheck();

console.log(health);
// {
//   healthy: true,
//   message: 'ComputeSDK provider is ready (using modal)',
//   details: {
//     underlyingProvider: 'modal',
//     activeSessions: 3
//   }
// }

Session Management

Listing Sessions

// List all sessions
const sessions = await provider.listSessions();

// List sessions for a specific user
const userSessions = await provider.listSessions('user-456');

Getting Session Stats

const stats = await session.getStats();

console.log(stats);
// {
//   memoryBytes: 134217728,
//   cpuPercent: 15.5,
//   diskBytes: 52428800,
//   networkRxBytes: 1024000,
//   networkTxBytes: 512000,
//   uptimeSeconds: 300
// }

Session Information

const info = await session.getInfo();

console.log(info);
// {
//   id: 'session-123',
//   providerId: 'sandbox-abc',
//   state: 'running',
//   createdAt: Date,
//   metadata: { underlyingProvider: 'modal' }
// }

Error Handling

try {
  const session = await provider.createSession(config);
} catch (error) {
  if (error.message.includes('Session limit')) {
    // User has too many active sessions
  } else if (error.message.includes('not initialized')) {
    // Provider needs initialization
    await provider.initialize();
  } else if (error.message.includes('credentials')) {
    // Missing API keys
  } else {
    console.error('Failed to create session:', error);
  }
}

Best Practices

  1. Always clean up sessions - Call session.stop() when done
  2. Set appropriate timeouts - Prevent runaway sessions
  3. Use resource limits - Prevent resource exhaustion
  4. Handle errors gracefully - Sessions can fail unexpectedly
  5. Monitor session stats - Track resource usage
  6. Use environment variables - Never hardcode API keys
  7. Choose the right provider - Docker for self-hosted, ComputeSDK for cloud