Using the Sandbox API
Programmatic API for creating and managing sandboxes
Access sandbox functionality through ctx.sandbox in agents or c.var.sandbox in routes. Choose between one-shot execution for single commands or interactive sandboxes for multi-step workflows.
One-shot Execution
Use sandbox.run() when you need to execute a single command. The sandbox is automatically created and destroyed.
import { createAgent } from '@agentuity/runtime';
import { z } from 'zod';
const agent = createAgent('CodeRunner', {
schema: {
input: z.object({ code: z.string() }),
output: z.object({
success: z.boolean(),
output: z.string(),
exitCode: z.number(),
}),
},
handler: async (ctx, input) => {
const result = await ctx.sandbox.run({
command: {
exec: ['python3', '-c', input.code],
},
resources: { memory: '256Mi', cpu: '500m' },
timeout: { execution: '30s' },
});
return {
success: result.exitCode === 0,
output: result.stdout || result.stderr || '',
exitCode: result.exitCode,
};
},
});With File Input
Write files to the sandbox before execution:
const result = await ctx.sandbox.run({
command: {
exec: ['bun', 'run', 'index.ts'],
files: [
{
path: 'index.ts',
content: Buffer.from('console.log("Hello from TypeScript!")'),
},
{
path: 'data.json',
content: Buffer.from(JSON.stringify({ items: [1, 2, 3] })),
},
],
},
resources: { memory: '512Mi' },
});Interactive Sandbox
Use sandbox.create() for multi-step workflows. The sandbox persists until you explicitly destroy it.
import { createAgent } from '@agentuity/runtime';
const agent = createAgent('ProjectBuilder', {
handler: async (ctx, input) => {
// Create a persistent sandbox
const sandbox = await ctx.sandbox.create({
resources: { memory: '1Gi', cpu: '1000m' },
network: { enabled: true }, // Allow package downloads
dependencies: ['git'], // Pre-install apt packages
});
try {
// Run multiple commands in sequence
await sandbox.execute({ command: ['npm', 'init', '-y'] });
await sandbox.execute({ command: ['npm', 'install', 'zod'] });
// Write project files
await sandbox.writeFiles([
{
path: 'index.ts',
content: Buffer.from(`
import { z } from 'zod';
const schema = z.object({ name: z.string() });
console.log(schema.parse({ name: 'test' }));
`),
},
]);
// Build and run
const result = await sandbox.execute({
command: ['npx', 'tsx', 'index.ts'],
});
return { output: result.stdoutStreamUrl };
} finally {
// Always clean up
await sandbox.destroy();
}
},
});Writing Files
Write files to the sandbox workspace before or during execution:
await sandbox.writeFiles([
{ path: 'src/main.py', content: Buffer.from('print("Hello")') },
{ path: 'config.json', content: Buffer.from('{"debug": true}') },
]);Reading Files
Read files from the sandbox as streams:
const stream = await sandbox.readFile('output/results.json');
const reader = stream.getReader();
const chunks: Uint8Array[] = [];
while (true) {
const { done, value } = await reader.read();
if (done) break;
chunks.push(value);
}
const content = new TextDecoder().decode(Buffer.concat(chunks));
const data = JSON.parse(content);Streaming Output
Access stdout and stderr as streams for real-time output:
const sandbox = await ctx.sandbox.create();
// Start a long-running command
await sandbox.execute({ command: ['npm', 'run', 'build'] });
// Stream stdout with error handling
try {
const reader = sandbox.stdout.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
ctx.logger.info('Build output', { line: decoder.decode(value) });
}
} catch (error) {
ctx.logger.error('Failed to read stream', { error });
}Creating from Snapshot
Start sandboxes from pre-configured snapshots for faster cold starts:
How Snapshots Work
A snapshot is a saved filesystem state. You create sandboxes from snapshots rather than running them directly. See Snapshots for how to create them.
const sandbox = await ctx.sandbox.create({
snapshot: 'node-project-base', // Use tag or snapshot ID
resources: { memory: '512Mi' },
});
// Sandbox already has node_modules and dependencies installed
await sandbox.execute({ command: ['npm', 'run', 'build'] });Environment Variables
Pass environment variables to sandboxes:
const result = await ctx.sandbox.run({
command: { exec: ['node', '-e', 'console.log(process.env.API_KEY)'] },
env: {
API_KEY: 'secret-key',
NODE_ENV: 'test',
DEBUG: 'true',
},
resources: { memory: '256Mi' },
});Automatic Environment Variables
Every sandbox automatically receives environment variables that provide context about its runtime environment, letting your code access the sandbox ID, public URL, and more:
| Variable | Description |
|---|---|
AGENTUITY_SANDBOX_ID | The sandbox's unique identifier |
AGENTUITY_SANDBOX_RUNTIME | Runtime name (e.g., python, bun) |
AGENTUITY_SANDBOX_RUNTIME_ID | Runtime unique identifier |
AGENTUITY_SANDBOX_ORG_ID | Organization ID |
AGENTUITY_SANDBOX_PROJECT_ID | Project ID (only when project context exists) |
AGENTUITY_SANDBOX_URL | Public URL (only when network is enabled) |
const result = await ctx.sandbox.run({
command: {
exec: ['node', '-e', `
console.log('Sandbox:', process.env.AGENTUITY_SANDBOX_ID);
console.log('Runtime:', process.env.AGENTUITY_SANDBOX_RUNTIME);
if (process.env.AGENTUITY_SANDBOX_URL) {
console.log('URL:', process.env.AGENTUITY_SANDBOX_URL);
}
`],
},
network: { enabled: true },
resources: { memory: '256Mi' },
});Note that the code snippet above runs inside an isolated sandbox, not in the agent, so use standard logging (console.log, print, etc.) rather than ctx.logger.
Cancelling Execution
Use an AbortSignal to cancel long-running commands:
const controller = new AbortController();
// Set a 5-second timeout
setTimeout(() => controller.abort(), 5000);
try {
const result = await sandbox.execute({
command: ['npm', 'run', 'long-task'],
signal: controller.signal,
});
return { output: result.stdout };
} catch (error) {
if (error.name === 'AbortError') {
ctx.logger.warn('Execution cancelled');
return { output: '', cancelled: true };
}
throw error;
}Using in Routes
Routes access sandbox through c.var.sandbox:
import { createRouter } from '@agentuity/runtime';
const router = createRouter();
router.post('/execute', async (c) => {
const { language, code } = await c.req.json();
const commands: Record<string, string[]> = {
python: ['python3', '-c', code],
javascript: ['node', '-e', code],
typescript: ['bun', '-e', code],
};
if (!commands[language]) {
return c.json({ error: 'Unsupported language' }, 400);
}
const result = await c.var.sandbox.run({
command: { exec: commands[language] },
timeout: { execution: '10s' },
resources: { memory: '128Mi', cpu: '250m' },
});
return c.json({
success: result.exitCode === 0,
output: result.stdout || result.stderr,
exitCode: result.exitCode,
durationMs: result.durationMs,
});
});
export default router;Sandbox Management
Listing Sandboxes
const { sandboxes, total } = await ctx.sandbox.list({
status: 'idle', // Filter by status
projectId: 'proj_x', // Filter by project
snapshotId: 'snp_y', // Filter by snapshot
limit: 10,
offset: 0,
});
for (const info of sandboxes) {
ctx.logger.info('Sandbox', {
id: info.sandboxId,
status: info.status,
executions: info.executions,
});
}Getting Sandbox Info
const info = await ctx.sandbox.get('sbx_abc123');
ctx.logger.info('Sandbox details', {
status: info.status,
createdAt: info.createdAt,
snapshotId: info.snapshotId,
});Destroying Sandboxes
// Via sandbox instance
await sandbox.destroy();
// Via service (by ID)
await ctx.sandbox.destroy('sbx_abc123');Configuration Reference
SandboxCreateOptions
| Option | Type | Description |
|---|---|---|
runtime | string | Runtime environment: 'bun:1', 'python:3.14' |
name | string | Optional sandbox name |
description | string | Optional description |
resources.memory | string | Memory limit: '256Mi', '1Gi' |
resources.cpu | string | CPU in millicores: '500m', '1000m' |
resources.disk | string | Disk limit: '512Mi', '2Gi' |
network.enabled | boolean | Enable outbound network (default: false) |
timeout.idle | string | Auto-destroy after idle: '10m', '1h' |
timeout.execution | string | Max command duration: '30s', '5m' |
dependencies | string[] | Apt packages: ['python3', 'git'] |
snapshot | string | Snapshot ID or tag to restore from |
env | Record<string, string> | Environment variables |
metadata | Record<string, unknown> | User-defined metadata for tracking |
ExecuteOptions
| Option | Type | Description |
|---|---|---|
command | string[] | Command and arguments |
files | FileToWrite[] | Files to create before execution |
timeout | string | Override execution timeout |
signal | AbortSignal | Cancel the execution |
Execution
Returned by sandbox.execute():
| Field | Type | Description |
|---|---|---|
executionId | string | Unique execution ID for debugging |
status | string | 'queued', 'running', 'completed', 'failed', 'timeout', 'cancelled' |
exitCode | number | Process exit code (when completed) |
durationMs | number | Execution duration in milliseconds |
stdoutStreamUrl | string | URL to fetch stdout stream |
stderrStreamUrl | string | URL to fetch stderr stream |
SandboxRunResult
| Field | Type | Description |
|---|---|---|
sandboxId | string | Sandbox ID (for debugging) |
exitCode | number | Process exit code |
durationMs | number | Execution duration |
stdout | string | Captured stdout (if available) |
stderr | string | Captured stderr (if available) |
Best Practices
- Set resource limits: Control memory and CPU usage for predictable performance
- Use timeouts: Always set execution timeouts for untrusted code
- Enable network when needed: Required for package installation, API calls, and external requests
- Clean up interactive sandboxes: Use try/finally to ensure
destroy()is called - Use snapshots for common environments: Pre-install dependencies to reduce cold start time
Next Steps
- Snapshots: Skip dependency installation with pre-configured environments
- CLI Commands: Debug sandboxes and create snapshots from the terminal
Need Help?
Join our Community for assistance or just to hang with other humans building agents.
Send us an email at hi@agentuity.com if you'd like to get in touch.
Please Follow us on
If you haven't already, please Signup for your free account now and start building your first agent!