A model writes code, a sandbox runs its tests
A sandbox with infer:run and no internet asks the node's model for a function, runs the tests on it and sends failures back, at most three times.
The sandbox is created with two settings that do the work:
api.scopes: ["infer:run"]lets code inside it call the node's model athttp://127.0.0.1:7700/v1/infer, andspend_cap_usd: 1stops those calls once they have cost a dollar, whatever the model-written code does. The create setsOPENAI_BASE_URL, a placeholderOPENAI_API_KEYandB3OS_MODELin its environment, so a stock OpenAI client (or plain HTTP, as here) works with no key inside the sandbox.egress: {mode: "deny"}leaves it no other way out. The recipe checks that:curl https://example.comfrom the sandbox fails (internet: blocked), while the model calls succeed.
Verified 2026-11-06: this recipe's last run passed against https://beta-api.b3os.org, label live-recorded (recorded from production), from commit 9fd4273e. The recipe harness runs it again, and a failed run takes this page out of the cookbook.
Run it
Each tab uploads the three files from this recipe's folder, checks that the sandbox cannot reach the internet, runs
agent.py and prints the solution it kept.
bashAPI=https://beta-api.b3os.orgAUTH="Authorization: Bearer $B3OS_API_KEY"post() { curl -s "$API$1" -H "$AUTH" -H "Content-Type: application/json" -d @-; }SBX=$(echo '{"template": "base", "timeout_s": 300, "egress": {"mode": "deny"}, "api": {"scopes": ["infer:run"], "spend_cap_usd": 1}}' | post /v1/sandboxes | jq -r .id)for f in agent.py task.md test_solution.py; do curl -s -X PUT "$API/v1/sandboxes/$SBX/files?path=/workspace/$f" -H "$AUTH" \ -H "Content-Type: application/octet-stream" --data-binary @"$f" > /dev/nulldoneecho '{"cmd": "curl -s -m 5 -o /dev/null https://example.com && echo reached || echo blocked"}' \ | post "/v1/sandboxes/$SBX/exec" | jq -r .stdoutecho '{"cmd": ["python3", "/workspace/agent.py"], "timeout_ms": 58000}' \ | post "/v1/sandboxes/$SBX/exec" | jq -r '.stdout | split("\n") | map(select(. != "")) | last'curl -s "$API/v1/sandboxes/$SBX/files?path=/workspace/solution.py" -H "$AUTH"curl -s -X DELETE "$API/v1/sandboxes/$SBX" -H "$AUTH" > /dev/null
tsimport { readFileSync } from "node:fs";const API = "https://beta-api.b3os.org";const auth = { authorization: `Bearer ${process.env.B3OS_API_KEY}` };const call = async (method: string, path: string, body?: unknown): Promise<any> => ( await fetch(`${API}${path}`, { method, headers: { ...auth, "content-type": "application/json" }, body: body === undefined ? undefined : JSON.stringify(body), }) ).json();const sbx = await call("POST", "/v1/sandboxes", { template: "base", timeout_s: 300, api: { scopes: ["infer:run"], spend_cap_usd: 1 }, egress: { mode: "deny" },});for (const f of ["agent.py", "task.md", "test_solution.py"]) await fetch(`${API}/v1/sandboxes/${sbx.id}/files?path=/workspace/${f}`, { method: "PUT", headers: { ...auth, "content-type": "application/octet-stream" }, body: readFileSync(f, "utf8"), });const probe = await call("POST", `/v1/sandboxes/${sbx.id}/exec`, { cmd: "curl -s -m 5 -o /dev/null https://example.com && echo reached || echo blocked",});console.log(`internet: ${probe.stdout.trim()}`);const r = await call("POST", `/v1/sandboxes/${sbx.id}/exec`, { cmd: ["python3", "/workspace/agent.py"], timeout_ms: 58000 });console.log(JSON.parse(r.stdout.trim().split("\n").at(-1) ?? "{}"));const solution = await fetch(`${API}/v1/sandboxes/${sbx.id}/files?path=/workspace/solution.py`, { headers: auth });console.log(await solution.text());await call("DELETE", `/v1/sandboxes/${sbx.id}`);
pythonimport jsonimport osimport requestsAPI = "https://beta-api.b3os.org"s = requests.Session()s.headers["Authorization"] = f"Bearer {os.environ['B3OS_API_KEY']}"sbx = s.post(f"{API}/v1/sandboxes", json={ "template": "base", "timeout_s": 300, "egress": {"mode": "deny"}, "api": {"scopes": ["infer:run"], "spend_cap_usd": 1},}).json()["id"]for f in ["agent.py", "task.md", "test_solution.py"]: with open(f, "rb") as fh: s.put(f"{API}/v1/sandboxes/{sbx}/files", params={"path": f"/workspace/{f}"}, data=fh.read(), headers={"Content-Type": "application/octet-stream"})probe = s.post(f"{API}/v1/sandboxes/{sbx}/exec", json={ "cmd": "curl -s -m 5 -o /dev/null https://example.com && echo reached || echo blocked",}).json()print("internet:", probe["stdout"].strip())r = s.post(f"{API}/v1/sandboxes/{sbx}/exec", json={"cmd": ["python3", "/workspace/agent.py"], "timeout_ms": 58000}).json()print(json.loads(r["stdout"].strip().split("\n")[-1]))print(s.get(f"{API}/v1/sandboxes/{sbx}/files", params={"path": "/workspace/solution.py"}).text)s.delete(f"{API}/v1/sandboxes/{sbx}")
The MCP sandbox_create tool takes no api grant, and without infer:run the sandbox has no OPENAI_BASE_URL for
agent.py to call. Create the sandbox with the API, with the same B3OS_API_KEY your MCP client sends:
bashcurl -s https://beta-api.b3os.org/v1/sandboxes -H "Authorization: Bearer $B3OS_API_KEY" \ -H "Content-Type: application/json" -d '{"template": "base", "timeout_s": 600, "egress": {"mode": "deny"}, "api": {"scopes": ["infer:run"], "spend_cap_usd": 1}}' | jq -r .id
Then, on the remote B3OS MCP server, with the three files' contents in the conversation, ask your agent:
textIn sandbox <id>, write agent.py, task.md and test_solution.py to /workspace. Check that curl https://example.comfails from inside it, then run python3 /workspace/agent.py with a 58 second timeout, show me /workspace/solution.pyand say how many tests passed, then delete the sandbox.
The agent calls sandbox_write_file three times, sandbox_exec twice, sandbox_read_file and sandbox_delete.
Inside the sandbox, agent.py (standard library only) sends task.md to the model, writes the answer's code block
to solution.py, runs python3 -m unittest test_solution and, when a test fails, sends the failure back and tries
again, at most three times. The task is parse_duration("1h30m") == 5400 with seven tests, including the inputs it
must refuse ("30m1h", "1.5h", "10").
The outputs are the run's own measurements: model_ms is the time spent in model calls and tests_ms the last test
run, both measured inside the sandbox; create_ms is the create's server-side total from its timing; exec_ms is
the agent's exec as the client saw it. The sandbox is deleted at the end, whatever happened.
Files: run.mjs (the client), agent.py, task.md and test_solution.py (uploaded to the sandbox).
Owner: Sandboxes. Products: Sandboxes, Infer.
Output of the last green run
json{ "model": "b3os/qwen3.5-9b", "internet": "blocked", "attempts": 1, "all_passed": true, "tests_total": 7, "tests_passed": 7, "model_ms": 2722.6, "completion_tokens": 624, "tests_ms": 92.7, "create_ms": 1.821, "exec_ms": 2887.1, "solution_lines": 72, "solution_head": "def parse_duration(text: str) -> int:\n import re\n \n text = text.strip()\n if not text:\n raise ValueError(\"Empty string\")\n \n # Pattern to match integer followed by a unit\n # We need to ensure the whole string is consumed by these parts\n pattern = r'^(\\d+)([hms])'\n \n parts = []\n remaining = text\n \n while remaining:\n match = re.match(pattern, remain"}
bash$ node run.mjs# exit 0
The outputs this recipe publishes (the
publish.outputs
list in its recipe.json), with workspace identifiers redacted. The run's stdout, stderr and other outputs are not published.
Captured 2026-11-06 from commit
9fd4273e
, label
live-recorded
(recorded from production). Case
recipes/sandbox-model-writes-tested-code
.