Letting an agent write and run code turns vague tasks into solvable ones — data analysis, format conversion, scraping. It also hands untrusted output an execution surface.
Non-negotiable controls:
- Run in an isolated container or microVM, never the app process. - No credentials in the sandbox environment. - Deny egress by default; allow-list specific hosts. - Wall-clock, memory, and disk limits; destroy the sandbox after the run. - Mount inputs read-only and collect outputs from a dedicated directory.
ts
const sandbox = await createSandbox({ image: "python:3.12-slim", timeoutMs: 30_000, network: "none" });
try {
const { stdout, stderr, exitCode } = await sandbox.run("python", ["-c", code]);
return { stdout: stdout.slice(0, 8_000), stderr: stderr.slice(0, 2_000), exitCode };
} finally {
await sandbox.destroy();
}Feed `stderr` back to the model: a self-correcting write-run-fix loop with two retries fixes most first-attempt errors, and truncating output protects the context window.
Exercise: give the agent a messy CSV and ask for the median of a column. Verify from logs that it executed code rather than estimating the answer.