Code Execution

Safe, multi-language code execution in isolated containers

View as MarkdownOpen in Claude

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:

1import { ModboxClient } from "modbox-sdk";
2
3const modbox = new ModboxClient({ token: process.env.MODBOX_API_TOKEN });
4
5async function executeCode(code: string, language: string) {
6 const taskId = `exec-${crypto.randomUUID()}`;
7
8 await modbox.provisionSandbox({
9 taskId,
10 imageId: process.env.CODE_EXEC_IMAGE_ID,
11 ttlSeconds: 60, // short TTL — destroy after 60s no matter what
12 });
13
14 await modbox.waitForSandbox({ taskId, timeout: 30 });
15 const sandbox = await modbox.getSandbox(taskId);
16
17 const response = await fetch(`${sandbox.sandboxUrl}/modbox/api/exec`, {
18 method: "POST",
19 headers: {
20 "Content-Type": "application/json",
21 "Authorization": `Bearer ${process.env.SANDBOX_API_KEY}`,
22 },
23 body: JSON.stringify({ command: `${language} -c "${code.replace(/"/g, '\\"')}"` }),
24 });
25
26 const result = await response.json();
27
28 // Explicit cleanup (TTL will also handle it)
29 await modbox.destroySandbox({ taskId });
30
31 return result;
32 // → { exitCode: 0, stdout: "Hello, world!\n", stderr: "", durationMs: 42 }
33}

Session-based execution (stateful)

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

1// Session manager — one sandbox per user
2const sessions = new Map<string, string>(); // userId → sandboxUrl
3
4async function getOrCreateSession(userId: string): Promise<string> {
5 if (sessions.has(userId)) {
6 return sessions.get(userId)!;
7 }
8
9 const taskId = `session-${userId}`;
10
11 await modbox.provisionSandbox({
12 taskId,
13 imageId: process.env.CODE_EXEC_IMAGE_ID,
14 ttlSeconds: 3600, // 1 hour idle timeout
15 envVars: { USER_ID: userId },
16 });
17
18 await modbox.waitForSandbox({ taskId, timeout: 30 });
19 const sandbox = await modbox.getSandbox(taskId);
20
21 sessions.set(userId, sandbox.sandboxUrl);
22 return sandbox.sandboxUrl;
23}
24
25async function runInSession(userId: string, code: string) {
26 const sandboxUrl = await getOrCreateSession(userId);
27
28 // State persists — variables, installed packages, files all remain.
29 const result = await fetch(`${sandboxUrl}/modbox/api/exec`, {
30 method: "POST",
31 headers: {
32 "Content-Type": "application/json",
33 "Authorization": `Bearer ${process.env.SANDBOX_API_KEY}`,
34 },
35 body: JSON.stringify({ command: `python3 -c "${code.replace(/"/g, '\\"')}"` }),
36 });
37
38 return result.json();
39}

LLM tool call integration

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

1const tools = [
2 {
3 type: "function",
4 function: {
5 name: "run_code",
6 description: "Execute Python code and return stdout/stderr",
7 parameters: {
8 type: "object",
9 properties: {
10 code: { type: "string", description: "Python code to execute" },
11 },
12 required: ["code"],
13 },
14 },
15 },
16];
17
18// When the LLM calls run_code:
19async function handleToolCall(toolCall: ToolCall, sandboxUrl: string) {
20 if (toolCall.function.name === "run_code") {
21 const { code } = JSON.parse(toolCall.function.arguments);
22
23 const result = await fetch(`${sandboxUrl}/modbox/api/exec`, {
24 method: "POST",
25 headers: {
26 "Content-Type": "application/json",
27 "Authorization": `Bearer ${process.env.SANDBOX_API_KEY}`,
28 },
29 body: JSON.stringify({ command: `python3 -c "${code.replace(/"/g, '\\"')}"` }),
30 });
31
32 const { stdout, stderr, exitCode } = await result.json();
33 return `stdout:\n${stdout}\nstderr:\n${stderr}\nexitCode: ${exitCode}`;
34 }
35}

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.