Code Execution

Safe, multi-language code execution in isolated containers

View as Markdown

Modbox is an excellent foundation for platforms that need to execute user-submitted or LLM-generated code safely. Each execution runs in a completely isolated container — no shared filesystem, no shared network, no shared processes.

Use cases

  • 🎓 Education platforms — Let students run code exercises safely
  • 🧑‍💻 Online IDEs / REPLs — Persistent environments per user session
  • 🤖 LLM tool calls — Give your LLM a run_code tool backed by a real sandbox
  • 🔬 Data science notebooks — Isolated Python/R kernels per user

Single execution (stateless)

For simple, one-shot code execution, provision a sandbox, run the code, and destroy:

import { ModboxClient } from "modbox-sdk";
const modbox = new ModboxClient({ token: process.env.MODBOX_API_TOKEN });
async function executeCode(code: string, language: string) {
const taskId = `exec-${crypto.randomUUID()}`;
await modbox.provisionSandbox({
taskId,
imageId: process.env.CODE_EXEC_IMAGE_ID,
ttlSeconds: 60, // short TTL — destroy after 60s no matter what
});
await modbox.waitForSandbox({ taskId, timeout: 30 });
const sandbox = await modbox.getSandbox(taskId);
const response = await fetch(`${sandbox.sandboxUrl}/modbox/api/exec`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${process.env.SANDBOX_API_KEY}`,
},
body: JSON.stringify({ command: `${language} -c "${code.replace(/"/g, '\\"')}"` }),
});
const result = await response.json();
// Explicit cleanup (TTL will also handle it)
await modbox.destroySandbox({ taskId });
return result;
// → { exitCode: 0, stdout: "Hello, world!\n", stderr: "", durationMs: 42 }
}

Session-based execution (stateful)

For online IDEs or multi-step notebooks, keep a sandbox alive per user session so state persists between executions:

// Session manager — one sandbox per user
const sessions = new Map<string, string>(); // userId → sandboxUrl
async function getOrCreateSession(userId: string): Promise<string> {
if (sessions.has(userId)) {
return sessions.get(userId)!;
}
const taskId = `session-${userId}`;
await modbox.provisionSandbox({
taskId,
imageId: process.env.CODE_EXEC_IMAGE_ID,
ttlSeconds: 3600, // 1 hour idle timeout
envVars: { USER_ID: userId },
});
await modbox.waitForSandbox({ taskId, timeout: 30 });
const sandbox = await modbox.getSandbox(taskId);
sessions.set(userId, sandbox.sandboxUrl);
return sandbox.sandboxUrl;
}
async function runInSession(userId: string, code: string) {
const sandboxUrl = await getOrCreateSession(userId);
// State persists — variables, installed packages, files all remain.
const result = await fetch(`${sandboxUrl}/modbox/api/exec`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${process.env.SANDBOX_API_KEY}`,
},
body: JSON.stringify({ command: `python3 -c "${code.replace(/"/g, '\\"')}"` }),
});
return result.json();
}

LLM tool call integration

Give your LLM a run_code tool backed by a Modbox sandbox:

const tools = [
{
type: "function",
function: {
name: "run_code",
description: "Execute Python code and return stdout/stderr",
parameters: {
type: "object",
properties: {
code: { type: "string", description: "Python code to execute" },
},
required: ["code"],
},
},
},
];
// When the LLM calls run_code:
async function handleToolCall(toolCall: ToolCall, sandboxUrl: string) {
if (toolCall.function.name === "run_code") {
const { code } = JSON.parse(toolCall.function.arguments);
const result = await fetch(`${sandboxUrl}/modbox/api/exec`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${process.env.SANDBOX_API_KEY}`,
},
body: JSON.stringify({ command: `python3 -c "${code.replace(/"/g, '\\"')}"` }),
});
const { stdout, stderr, exitCode } = await result.json();
return `stdout:\n${stdout}\nstderr:\n${stderr}\nexitCode: ${exitCode}`;
}
}

Supported languages

Languages available depend on your image. The default Modbox code execution image includes:

LanguageVersionInvocation
Python3.12python3
Node.js22node
Bash5.2bash
Go1.23go run

Bring your own Docker image to support any language or runtime. See the Images guide.