返回 Skills
cloudflare/skills· Apache-2.0 内容可用

sandbox-sdk

Build sandboxed applications for secure code execution. Load when building AI code execution, code interpreters, CI/CD systems, interactive dev environments, or executing untrusted code. Covers Sandbox SDK lifecycle, commands, files, code interpreter, and preview URLs. Biases towards retrieval from Cloudflare docs over pre-trained knowledge.

安装

与 skills.sh 相同的 Command / Prompt 安装方式


name: sandbox-sdk description: Build sandboxed applications for secure code execution. Load when building AI code execution, code interpreters, CI/CD systems, interactive dev environments, or executing untrusted code. Covers Sandbox SDK lifecycle, commands, files, code interpreter, and preview URLs. Biases towards retrieval from Cloudflare docs over pre-trained knowledge.

Cloudflare Sandbox SDK

Build secure, isolated code execution environments on Cloudflare Workers.

FIRST: Verify Installation

npm install @cloudflare/sandbox
docker info  # Must succeed - Docker required for local dev

Retrieval Sources

Your knowledge of the Sandbox SDK may be outdated. Prefer retrieval over pre-training for any Sandbox SDK task.

ResourceURL
Docshttps://developers.cloudflare.com/sandbox/
API Referencehttps://developers.cloudflare.com/sandbox/api/
Exampleshttps://github.com/cloudflare/sandbox-sdk/tree/main/examples
Get Startedhttps://developers.cloudflare.com/sandbox/get-started/

When implementing features, fetch the relevant doc page or example first.

Required Configuration

wrangler.jsonc (exact - do not modify structure):

{
  "containers": [{
    "class_name": "Sandbox",
    "image": "./Dockerfile",
    "instance_type": "lite",
    "max_instances": 1
  }],
  "durable_objects": {
    "bindings": [{ "class_name": "Sandbox", "name": "Sandbox" }]
  },
  "migrations": [{ "new_sqlite_classes": ["Sandbox"], "tag": "v1" }]
}

Worker entry - must re-export Sandbox class:

import { getSandbox } from '@cloudflare/sandbox';
export { Sandbox } from '@cloudflare/sandbox';  // Required export

Quick Reference

TaskMethod
Get sandboxgetSandbox(env.Sandbox, 'user-123')
Run commandawait sandbox.exec('python script.py')
Run code (interpreter)await sandbox.runCode(code, { language: 'python' })
Write fileawait sandbox.writeFile('/workspace/app.py', content)
Read fileawait sandbox.readFile('/workspace/app.py')
Create directoryawait sandbox.mkdir('/workspace/src', { recursive: true })
List filesawait sandbox.listFiles('/workspace')
Expose portawait sandbox.exposePort(8080)
Destroyawait sandbox.destroy()

Core Patterns

Execute Commands

const sandbox = getSandbox(env.Sandbox, 'user-123');
const result = await sandbox.exec('python --version');
// result: { stdout, stderr, exitCode, success }

Code Interpreter (Recommended for AI)

Use runCode() for executing LLM-generated code with rich outputs:

const ctx = await sandbox.createCodeContext({ language: 'python' });

await sandbox.runCode('import pandas as pd; data = [1,2,3]', { context: ctx });
const result = await sandbox.runCode('sum(data)', { context: ctx });
// result.results[0].text = "6"

Languages: python, javascript, typescript

State persists within context. Create explicit contexts for production.

File Operations

await sandbox.mkdir('/workspace/project', { recursive: true });
await sandbox.writeFile('/workspace/project/main.py', code);
const file = await sandbox.readFile('/workspace/project/main.py');
const files = await sandbox.listFiles('/workspace/project');

When to Use What

NeedUseWhy
Shell commands, scriptsexec()Direct control, streaming
LLM-generated coderunCode()Rich outputs, state persistence
Build/test pipelinesexec()Exit codes, stderr capture
Data analysisrunCode()Charts, tables, pandas

Extending the Dockerfile

Base image (docker.io/cloudflare/sandbox:0.7.0) includes Python 3.11, Node.js 20, and common tools.

Add dependencies by extending the Dockerfile:

FROM docker.io/cloudflare/sandbox:0.7.0

# Python packages
RUN pip install requests beautifulsoup4

# Node packages (global)
RUN npm install -g typescript

# System packages
RUN apt-get update && apt-get install -y ffmpeg && rm -rf /var/lib/apt/lists/*

EXPOSE 8080  # Required for local dev port exposure

Keep images lean - affects cold start time.

Preview URLs (Port Exposure)

Expose HTTP services running in sandboxes:

const { url } = await sandbox.exposePort(8080);
// Returns preview URL for the service

Production requirement: Preview URLs need a custom domain with wildcard DNS (*.yourdomain.com). The .workers.dev domain does not support preview URL subdomains.

See: https://developers.cloudflare.com/sandbox/guides/expose-services/

OpenAI Agents SDK Integration

The SDK provides helpers for OpenAI Agents at @cloudflare/sandbox/openai:

import { Shell, Editor } from '@cloudflare/sandbox/openai';

See examples/openai-agents for complete integration pattern.

Sandbox Lifecycle

  • getSandbox() returns immediately - container starts lazily on first operation
  • Containers sleep after 10 minutes of inactivity (configurable via sleepAfter)
  • Use destroy() to immediately free resources
  • Same sandboxId always returns same sandbox instance

Anti-Patterns

  • Don't use internal clients (CommandClient, FileClient) - use sandbox.* methods
  • Don't skip the Sandbox export - Worker won't deploy without export { Sandbox }
  • Don't hardcode sandbox IDs for multi-user - use user/session identifiers
  • Don't forget cleanup - call destroy() for temporary sandboxes

Detailed References

附带文件

references/api-quick-ref.md
# Sandbox SDK API Reference

Detailed API for `@cloudflare/sandbox`. For full docs: https://developers.cloudflare.com/sandbox/api/

## Lifecycle

```typescript
getSandbox(binding: DurableObjectNamespace<Sandbox>, sandboxId: string, options?: SandboxOptions): Sandbox

interface SandboxOptions {
  sleepAfter?: string;     // Duration before auto-sleep (default: "10m")
  keepAlive?: boolean;     // Prevent auto-sleep (default: false)
  normalizeId?: boolean;   // Lowercase IDs for preview URLs (default: false)
}

await sandbox.destroy(): Promise<void>  // Immediately terminate and delete all state
```

## Commands

```typescript
await sandbox.exec(command: string, options?: ExecOptions): Promise<ExecResult>

interface ExecOptions {
  cwd?: string;           // Working directory
  env?: Record<string, string>;  // Environment variables
  timeout?: number;       // Timeout in ms (no default; runs without timeout if unset)
  stdin?: string;         // Input to command
}

interface ExecResult {
  stdout: string;
  stderr: string;
  exitCode: number;
  success: boolean;       // exitCode === 0
}
```

## Code Interpreter

```typescript
await sandbox.createCodeContext(options?: CreateContextOptions): Promise<CodeContext>

interface CreateContextOptions {
  language?: 'python' | 'javascript' | 'typescript';  // default: 'python'
  cwd?: string;           // Working directory (default: '/workspace')
  envVars?: Record<string, string>;
  timeout?: number;       // Request timeout in ms (default: 30000)
}

await sandbox.runCode(code: string, options?: RunCodeOptions): Promise<ExecutionResult>

interface RunCodeOptions {
  context?: CodeContext;  // Reuse context for state persistence
  language?: 'python' | 'javascript' | 'typescript';
  timeout?: number;       // Execution timeout in ms (default: 60000)
}

interface ExecutionResult {
  code: string;
  logs: { stdout: string[]; stderr: string[] };
  results: RichOutput[];  // text, html, png, json, etc.
  error?: { name: string; value: string; traceback: string[] };
  executionCount: number;
}
```

## Files

```typescript
await sandbox.writeFile(path: string, content: string | Uint8Array): Promise<void>
await sandbox.readFile(path: string): Promise<{ content: string }>
await sandbox.mkdir(path: string, options?: { recursive?: boolean }): Promise<void>
await sandbox.listFiles(path: string): Promise<FileMetadata[]>
await sandbox.deleteFile(path: string): Promise<void>

interface FileMetadata {
  name: string;
  path: string;
  isDirectory: boolean;
  size: number;
  modifiedAt: string;
}
```

## Ports

```typescript
await sandbox.exposePort(port: number): Promise<{ url: string; token: string }>
await sandbox.unexposePort(port: number): Promise<void>
await sandbox.listPorts(): Promise<PortInfo[]>
```

## Error Handling

Errors include context about the operation:

```typescript
try {
  await sandbox.exec('invalid-command');
} catch (error) {
  // error.message includes command and sandbox context
}
```

For `runCode()`, check `result.error` instead of catching:

```typescript
const result = await sandbox.runCode('1/0', { language: 'python' });
if (result.error) {
  console.error(result.error.name);  // "ZeroDivisionError"
}
```
references/examples.md
# Sandbox SDK Examples

All examples: https://github.com/cloudflare/sandbox-sdk/tree/main/examples

## Example Index

| Example | Use Case | Key File |
|---------|----------|----------|
| `minimal` | Basic setup, exec, file ops | `src/index.ts` |
| `code-interpreter` | AI code execution with Workers AI | `src/index.ts` |
| `openai-agents` | OpenAI Agents SDK integration | `src/index.ts` |
| `opencode` | OpenCode agent integration | `src/index.ts` |
| `claude-code` | Claude Code agent integration | `src/index.ts` |
| `typescript-validator` | TypeScript compilation/validation | `src/index.ts` |
| `authentication` | Auth patterns for sandboxes | `src/index.ts` |

## When to Use Which Example

| Building | Start With |
|----------|------------|
| AI code execution | `code-interpreter` |
| Agent with shell + file editing | `openai-agents` |
| Basic command execution | `minimal` |
| Code validation service | `typescript-validator` |
| Multi-user sandboxes | `authentication` |

## Common Patterns from Examples

**Sandbox per user/session** (from `openai-agents`):
```typescript
const sandbox = getSandbox(env.Sandbox, `session-${sessionId}`);
```

**Code context reuse** (from `code-interpreter`):
```typescript
const pythonCtx = await sandbox.createCodeContext({ language: 'python' });
const result = await sandbox.runCode(code, { context: pythonCtx });
```

**Resource cleanup** (from `code-interpreter`):
```typescript
try {
  // ... use sandbox
} finally {
  await sandbox.destroy();
}
```

Fetch the full example source when implementing similar patterns.