TypeScript SDK for the Tangle Sandbox platform. Create isolated dev containers, run AI agents, and build automation workflows.
npm install @tangle-network/sandbox
# or
pnpm add @tangle-network/sandbox
# or
yarn add @tangle-network/sandboximport { Sandbox } from "@tangle-network/sandbox";
// Initialize the client
const client = new Sandbox({
apiKey: "sk_sandbox_...",
});
// Create a sandbox
const box = await client.create({
name: "my-project",
image: "node:20",
});
// Execute commands
const result = await box.exec("npm install && npm test");
console.log(result.stdout);
// Run an AI agent task
const task = await box.task("Fix any failing tests and commit the changes");
console.log(task.response);
// Clean up
await box.delete();- Sandbox Management - Create, list, stop, resume, and delete sandboxes
- Command Execution - Run shell commands in isolated containers
- AI Agent Tasks - Multi-turn agent execution with automatic tool use
- Snapshots - Save and restore sandbox state
- BYOS3 - Bring your own S3 storage for snapshots
- Batch Execution - Run tasks across multiple sandboxes in parallel
- Event Streaming - Real-time SSE streams for agent events
A sandbox is an isolated dev container with:
- A sidecar API for programmatic control
- Optional SSH access
- Optional web terminal
- Persistent storage with snapshots
const box = await client.create({
name: "my-sandbox",
image: "python:3.12",
env: { DEBUG: "true" },
sshEnabled: true,
maxLifetimeSeconds: 7200, // 2 hours
idleTimeoutSeconds: 1800, // 30 min idle timeout
resources: {
cpuCores: 2,
memoryMB: 4096,
diskGB: 20,
},
});pending -> provisioning -> running -> stopped -> deleted
|
v
failed
import { Sandbox } from "@tangle-network/sandbox";
const client = new Sandbox({
apiKey: "sk_sandbox_...",
baseUrl: "https://agents.tangle.network", // optional
timeoutMs: 30000, // optional
});Create a new sandbox.
const box = await client.create({
name: "my-project",
image: "node:20", // or "typescript" for pre-built image
agentIdentifier: "my-agent", // agent to run
env: { NODE_ENV: "development" },
sshEnabled: true,
sshPublicKey: "ssh-ed25519 AAAA...",
webTerminalEnabled: true,
maxLifetimeSeconds: 3600,
idleTimeoutSeconds: 900,
resources: {
cpuCores: 2,
memoryMB: 4096,
diskGB: 20,
},
metadata: { team: "platform" },
// BYOS3: Customer-provided storage
storage: {
type: "s3",
bucket: "my-snapshots",
region: "us-east-1",
credentials: {
accessKeyId: "AKIA...",
secretAccessKey: "...",
},
},
fromSnapshot: "snap_abc123", // restore from snapshot
});List all sandboxes.
const sandboxes = await client.list({
status: "running", // filter by status
limit: 10,
offset: 0,
});Get a sandbox by ID.
const box = await client.get("sandbox_abc123");
if (box) {
console.log(box.status);
}Get account usage information.
const usage = await client.usage();
console.log(`Active: ${usage.activeSandboxes}`);
console.log(`Compute: ${usage.computeMinutes} minutes`);Run tasks across multiple sandboxes in parallel.
const result = await client.runBatch([
{ id: "task-1", message: "Analyze code quality" },
{ id: "task-2", message: "Run security scan" },
{ id: "task-3", message: "Generate documentation" },
], {
timeoutMs: 300000,
scalingMode: "balanced", // "fastest" | "balanced" | "cheapest"
});
console.log(`Success rate: ${result.successRate}%`);After creating or retrieving a sandbox, you get a SandboxInstance with these methods:
Execute a shell command.
const result = await box.exec("npm install", {
cwd: "/workspace",
env: { CI: "true" },
timeoutMs: 60000,
});
console.log(result.exitCode); // 0
console.log(result.stdout);
console.log(result.stderr);Send a single prompt to the AI agent.
const result = await box.prompt("What files are in this project?", {
sessionId: "session_123", // for conversation continuity
model: "anthropic/claude-sonnet-4-20250514",
timeoutMs: 120000,
});
console.log(result.response);
console.log(result.usage); // { inputTokens, outputTokens }Run a multi-turn agent task. The agent keeps working until completion.
const result = await box.task("Set up a REST API with authentication", {
maxTurns: 20, // limit turns (0 = unlimited)
sessionId: "...", // continue previous session
});
console.log(result.turnsUsed);
console.log(result.response);Stream agent events in real-time.
for await (const event of box.streamPrompt("Explain this codebase")) {
switch (event.type) {
case "message.updated":
process.stdout.write(event.data.content);
break;
case "tool_call":
console.log(`Tool: ${event.data.name}`);
break;
case "done":
console.log("\nComplete!");
break;
}
}Stream a multi-turn task with real-time events.
for await (const event of box.streamTask("Build a CLI tool")) {
// Handle events...
}Subscribe to sandbox lifecycle events.
for await (const event of box.events({ signal: controller.signal })) {
console.log(`Event: ${event.type}`, event.data);
}Create a snapshot of the sandbox state.
const snapshot = await box.snapshot({
tags: ["v1.0", "stable"],
paths: ["/workspace"], // specific paths (default: all)
});
console.log(snapshot.snapshotId);
console.log(snapshot.sizeBytes);List all snapshots for this sandbox.
const snapshots = await box.listSnapshots();
for (const snap of snapshots) {
console.log(`${snap.snapshotId}: ${snap.createdAt}`);
}Store snapshots in your own S3-compatible storage. Supports AWS S3, Google Cloud Storage, and Cloudflare R2.
const box = await client.create({
name: "my-sandbox",
storage: {
type: "s3", // "s3" | "gcs" | "r2"
bucket: "my-snapshots",
region: "us-east-1",
endpoint: "https://s3.us-east-1.amazonaws.com", // optional
credentials: {
accessKeyId: "AKIA...",
secretAccessKey: "...",
},
prefix: "sandbox-snapshots/", // optional path prefix
},
fromSnapshot: "snap_abc123", // restore from your storage
});When storage is configured, snapshots are written directly to your bucket:
// Create snapshot to your S3
const snap = await box.snapshot({
tags: ["production"],
storage: {
type: "s3",
bucket: "my-snapshots",
credentials: { accessKeyId: "...", secretAccessKey: "..." },
},
});
// List snapshots from your S3
const snapshots = await box.listSnapshots({
type: "s3",
bucket: "my-snapshots",
credentials: { ... },
});
// Restore from your S3
await box.restoreFromStorage({
type: "s3",
bucket: "my-snapshots",
credentials: { ... },
});For advanced use cases, you can communicate directly with the sidecar API using the provided auth token:
const box = await client.create({ name: "my-sandbox" });
// Wait for running status
await box.waitForRunning();
// Get connection info
const { sidecarUrl, authToken } = box.connection;
// Make direct API calls
const response = await fetch(`${sidecarUrl}/snapshots`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${authToken}`,
},
body: JSON.stringify({
projectId: box.id,
storage: myS3Config,
tags: ["manual"],
}),
});// Stop (preserves state)
await box.stop();
// Resume
await box.resume();
// Delete (destroys everything)
await box.delete();
// Refresh status from API
await box.refresh();
// Wait for specific status
await box.waitForRunning({ timeoutMs: 60000 });box.id // Unique identifier
box.name // Human-readable name
box.status // "pending" | "provisioning" | "running" | "stopped" | "failed"
box.connection // { sidecarUrl, authToken, ssh, webTerminalUrl }
box.metadata // Custom metadata
box.createdAt // Date
box.startedAt // Date | undefined
box.lastActivityAt // Date | undefined
box.expiresAt // Date | undefined
box.error // Error message if failedimport {
AuthError,
NetworkError,
NotFoundError,
QuotaError,
StateError,
TimeoutError,
ValidationError,
} from "@tangle-network/sandbox";
try {
await box.exec("npm test");
} catch (err) {
if (err instanceof TimeoutError) {
console.log("Command timed out");
} else if (err instanceof StateError) {
console.log(`Invalid state: ${err.currentState}`);
} else if (err instanceof NetworkError) {
console.log("Connection failed");
}
}Full TypeScript support with exported types:
import type {
SandboxClientConfig,
CreateSandboxOptions,
SandboxInfo,
SandboxStatus,
SandboxConnection,
ExecResult,
ExecOptions,
PromptResult,
PromptOptions,
TaskResult,
TaskOptions,
SnapshotResult,
SnapshotOptions,
SnapshotInfo,
StorageConfig,
BatchTask,
BatchResult,
BatchOptions,
UsageInfo,
} from "@tangle-network/sandbox";See the examples directory for complete runnable examples:
basic-usage.ts- Creating sandboxes and running commandsagent-tasks.ts- Multi-turn AI agent executionstreaming.ts- Real-time event streamingsnapshots.ts- Creating and restoring snapshotsbyos3.ts- Using customer-provided S3 storagebatch.ts- Parallel task execution
MIT
This repository ships a generated OpenAPI artifact for SDK-facing HTTP endpoints:
openapi/sandbox-api.openapi.jsonopenapi/metadata.json(generation provenance)- Package export:
@tangle-network/sandbox/openapi
Commands:
pnpm openapi:validate # Validate spec structure
pnpm openapi:types # Generate TypeScript contract types
pnpm openapi:pull # Pull latest spec from deployed API endpointpnpm docs:buildThis generates:
docs/api/index.html(OpenAPI reference)docs/sdk/index.html(TypeDoc API reference)
GitHub workflows included in this repo:
CIfor typecheck/build/spec validationPublishfor npm release with provenanceDocsfor GitHub Pages deployment