AI Agent Sandboxing
Learn how to use Noid for safe, isolated execution of AI-generated code.
Overview
AI agents often need to execute arbitrary code in response to user requests. Noid provides fast, secure sandboxes for this use case with:
- Instant isolation: New VM in seconds
- State management: Checkpoint/restore for consistency
- Resource limits: Prevent runaway processes
- Quick cleanup: Fast VM destruction
Use Case: Code Interpreter
Execute user-provided Python code safely:
import { NoidClient } from '@noid/sdk';
const noid = new NoidClient({
serverUrl: process.env.NOID_SERVER!,
token: process.env.NOID_TOKEN!,
});
async function executeCodeSafely(code: string) {
const vmName = `sandbox-${Date.now()}`;
try {
// Create isolated sandbox
await noid.createVM({
name: vmName,
vcpus: 2,
memory: 1024, // 1GB limit
});
// Install Python environment (or use golden snapshot)
await noid.exec(vmName, 'apt-get update && apt-get install -y python3');
// Execute user code with timeout
const result = await noid.exec(
vmName,
`timeout 30s python3 -c "${code.replace(/"/g, '\\"')}"`,
{ timeout: 35000 }
);
return {
success: result.exitCode === 0,
output: result.stdout,
error: result.stderr,
};
} finally {
// Always cleanup
await noid.destroyVM(vmName).catch(console.error);
}
}
// Example usage
const result = await executeCodeSafely(`
print("Hello from sandbox!")
import os
print(f"Running as: {os.getuid()}")
`);
console.log(result.output);
Golden Snapshot Pattern
Pre-configure VMs with common dependencies:
async function createPythonGolden() {
const baseVM = 'python-base';
// Create base VM
await noid.createVM({ name: baseVM });
// Install Python environment
await noid.exec(baseVM, 'apt-get update -y');
await noid.exec(baseVM, 'apt-get install -y python3 python3-pip');
await noid.exec(baseVM, 'pip3 install numpy pandas matplotlib');
// Create golden checkpoint
await noid.createCheckpoint(baseVM, 'golden', {
label: 'Python 3 with data science libraries',
});
console.log('✓ Golden snapshot ready');
}
// Fast sandbox from golden snapshot
async function executeWithGolden(code: string) {
const vmName = `sandbox-${Date.now()}`;
// Restore from golden (< 5 seconds)
await noid.restore('python-base', 'golden', { as: vmName });
// Execute immediately
const result = await noid.exec(vmName, `python3 -c "${code}"`);
await noid.destroyVM(vmName);
return result;
}
Multi-Agent Collaboration
Run multiple agents in parallel:
async function runAgentTeam(tasks: string[]) {
const agents = tasks.map((task, idx) => ({
name: `agent-${idx}`,
task,
}));
// Create VMs in parallel
await Promise.all(
agents.map(agent =>
noid.restore('python-base', 'golden', { as: agent.name })
)
);
// Execute tasks in parallel
const results = await Promise.all(
agents.map(agent =>
noid.exec(agent.name, `python3 -c "${agent.task}"`)
)
);
// Cleanup
await Promise.all(
agents.map(agent => noid.destroyVM(agent.name))
);
return results;
}
// Example: parallel data processing
const results = await runAgentTeam([
'import pandas as pd; df = pd.read_csv("data1.csv"); print(df.mean())',
'import pandas as pd; df = pd.read_csv("data2.csv"); print(df.mean())',
'import pandas as pd; df = pd.read_csv("data3.csv"); print(df.mean())',
]);
Tool Execution Sandbox
Safely execute agent tools:
interface Tool {
name: string;
description: string;
execute: (args: any) => Promise<any>;
}
class SafeToolExecutor {
private noid: NoidClient;
private vmPool: string[] = [];
constructor(noid: NoidClient, poolSize: number = 5) {
this.noid = noid;
this.initializePool(poolSize);
}
private async initializePool(size: number) {
// Pre-create VM pool
for (let i = 0; i < size; i++) {
const vmName = `tool-vm-${i}`;
await this.noid.restore('python-base', 'golden', { as: vmName });
this.vmPool.push(vmName);
}
}
async executeTool(tool: Tool, args: any): Promise<any> {
const vm = this.vmPool.pop();
if (!vm) throw new Error('No VMs available');
try {
// Execute tool in sandbox
const code = `
import json
args = json.loads('${JSON.stringify(args)}')
result = ${tool.name}(args)
print(json.dumps(result))
`;
const result = await this.noid.exec(vm, `python3 -c "${code}"`);
// Reset VM to clean state
await this.noid.restore('python-base', 'golden');
return JSON.parse(result.stdout);
} finally {
this.vmPool.push(vm);
}
}
}
// Usage
const executor = new SafeToolExecutor(noid);
const result = await executor.executeTool(
{
name: 'web_scraper',
description: 'Scrape web content',
execute: async (args) => {
// Tool implementation
},
},
{ url: 'https://example.com' }
);
Resource Limits
Prevent resource exhaustion:
async function executeWithLimits(code: string) {
const vmName = `sandbox-${Date.now()}`;
await noid.createVM({
name: vmName,
vcpus: 1, // Single CPU
memory: 512, // 512MB max
});
// Set additional limits inside VM
await noid.exec(vmName, `
ulimit -t 30 # 30 seconds CPU time
ulimit -v 524288 # 512MB virtual memory
ulimit -f 10240 # 10MB file size
`);
try {
const result = await noid.exec(
vmName,
`python3 -c "${code}"`,
{ timeout: 35000 }
);
return result;
} finally {
await noid.destroyVM(vmName);
}
}
Security Best Practices
1. Network Isolation
// Create VM without network access
await noid.createVM({
name: vmName,
network: 'isolated',
});
// Or disable network inside VM
await noid.exec(vmName, 'iptables -P OUTPUT DROP');
2. Input Sanitization
function sanitizeCode(code: string): string {
// Remove dangerous imports
const dangerous = ['os.system', 'subprocess', 'eval', 'exec'];
for (const keyword of dangerous) {
if (code.includes(keyword)) {
throw new Error(`Dangerous operation: ${keyword}`);
}
}
return code;
}
3. Output Filtering
function filterOutput(output: string): string {
// Remove sensitive information
return output
.replace(/\b(?:\d{1,3}\.){3}\d{1,3}\b/g, '[IP REDACTED]')
.replace(/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g, '[EMAIL REDACTED]');
}
Monitoring Agent Execution
Track agent performance and resource usage:
async function executeWithMetrics(code: string) {
const vmName = `sandbox-${Date.now()}`;
const startTime = Date.now();
await noid.createVM({ name: vmName });
try {
const result = await noid.exec(vmName, `python3 -c "${code}"`);
const duration = Date.now() - startTime;
// Log metrics
console.log({
vm: vmName,
duration_ms: duration,
exit_code: result.exitCode,
output_length: result.stdout.length,
});
return result;
} finally {
await noid.destroyVM(vmName);
}
}
Example: LangChain Integration
import { Tool } from 'langchain/tools';
class NoidPythonREPLTool extends Tool {
name = 'python_repl';
description = 'Execute Python code in a safe sandbox';
private noid: NoidClient;
constructor(noid: NoidClient) {
super();
this.noid = noid;
}
async _call(code: string): Promise<string> {
const vmName = `langchain-${Date.now()}`;
try {
await this.noid.restore('python-base', 'golden', { as: vmName });
const result = await this.noid.exec(
vmName,
`python3 -c "${code.replace(/"/g, '\\"')}"`,
{ timeout: 30000 }
);
return result.stdout || result.stderr;
} finally {
await this.noid.destroyVM(vmName).catch(console.error);
}
}
}
// Use with LangChain agent
import { initializeAgentExecutorWithOptions } from 'langchain/agents';
import { ChatOpenAI } from 'langchain/chat_models/openai';
const tools = [new NoidPythonREPLTool(noid)];
const llm = new ChatOpenAI({ temperature: 0 });
const executor = await initializeAgentExecutorWithOptions(tools, llm, {
agentType: 'openai-functions',
});
const result = await executor.run(
'Calculate the factorial of 10 using Python'
);
Next Steps
- Development Environments - Dev environment use case
- TypeScript SDK - SDK documentation
- Security - Security architecture