Grant a sandbox infer:run and actions:run and the code inside it can call the model and the action catalog with no key: the sandbox gets OPENAI_BASE_URL, a placeholder OPENAI_API_KEY and B3OS_MODEL, and B3OS answers at http://127.0.0.1:7700. The agent (agent.mjs in the recipe) asks the model for Berlin's temperature, runs the tool call it gets back through the Open-Meteo action and returns the model's answer:

js
const first = await post(`${process.env.OPENAI_BASE_URL}/chat/completions`, { model: process.env.B3OS_MODEL, messages, tools, tool_choice: "auto", chat_template_kwargs: { enable_thinking: false },});const call = first.choices[0].message.tool_calls[0];const weather = await post("http://127.0.0.1:7700/v1/actions/call", { ref: "io.b3os/open-meteo/get-current-weather@1", input: JSON.parse(call.function.arguments),});
Check

Verified 2026-11-01: this recipe's last run passed against https://beta-api.b3os.org, label live-recorded (recorded from production), from commit 771a9508. The recipe harness runs it again, and a failed run takes this page out of the cookbook.

Run it

Each tab creates the sandbox with the grant, copies agent.mjs in, runs it and deletes the sandbox.

bash
SBX=$(curl -s https://beta-api.b3os.org/v1/sandboxes \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"template": "base", "timeout_s": 300, "api": {"scopes": ["infer:run", "actions:run"], "spend_cap_usd": 1}}' \ | jq -r .id)curl -s -X PUT "https://beta-api.b3os.org/v1/sandboxes/$SBX/files?path=/tmp/agent.mjs" \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H "Content-Type: application/octet-stream" \ --data-binary @agent.mjscurl -s "https://beta-api.b3os.org/v1/sandboxes/$SBX/exec" \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"cmd": "node /tmp/agent.mjs", "timeout_ms": 60000}' | jq -r .stdoutcurl -s -X DELETE "https://beta-api.b3os.org/v1/sandboxes/$SBX" -H "Authorization: Bearer $B3OS_API_KEY"

model_first_ms, action_ms and model_second_ms below are measured inside the sandbox, on the same machine as the model. A buffered exec waits at most 60 seconds; a longer agent streams its output or runs in the background.

Owner: Docs. Products: Docs, Sandboxes, Infer, Actions and triggers.

Output of the last green run

bash
$ node run.mjs# exit 0

The outputs this recipe publishes (its recipe.json publish.outputs), with workspace identifiers redacted. The run's stdout, stderr and other outputs are not published.

Captured 2026-11-01 from commit 771a9508 , label live-recorded (recorded from production). Case recipes/sandbox-agent-weather .

Ask a question... ⌘I