How to run smolagents code in a secure sandbox
Wrap Runtime's four sandbox functions with smolagents' @tool, and every command the agent runs executes in a disposable microVM.
On Runtime the sandbox is a whole Linux machine, not a Python snippet runner.
smolagents' remote executors send the agent's Python snippets away and return
their output. A Runtime sandbox is a Firecracker microVM with its own kernel,
Ubuntu 24.04, Python 3.12, pip and sudo, so the agent can install packages,
run test suites and keep files between steps. The median sandbox answered its
first Python command 351 ms after the create request on 24 September 2026, and
a 2 vCPU, 4 GiB sandbox costs $0.03125 an hour while the model is thinking.
smolagents 1.26.0 was the current PyPI release on 25 September 2026.
Where smolagents runs code today
A CodeAgent writes Python and hands it to an executor. The executor is chosen
with executor_type, and smolagents 1.26.0 accepts five values:
executor_type |
Where the snippet runs | What you set up |
|---|---|---|
local (default) |
Your own process, in smolagents' AST-walking LocalPythonExecutor |
Nothing; imports need an allow-list |
docker |
A Docker container on your machine | Docker installed, smolagents[docker] |
e2b |
An E2B sandbox | An E2B account, smolagents[e2b] |
modal |
A Modal sandbox | A Modal account, smolagents[modal] |
blaxel |
A Blaxel sandbox | A Blaxel account, smolagents[blaxel] |
| Runtime tools | A Runtime microVM, through tool calls | withruntime; one browser approval to start |
The smolagents guide is direct about the default: "no local python sandbox can ever be completely secure", and "the only way to run LLM-generated code with truly robust security isolation is to use remote execution options". It also notes that the remote executors do not support managed agents (multi-agent setups) yet.
Give a ToolCallingAgent the sandbox
sandbox_tools(sbx) returns runtime_exec, runtime_read_file,
runtime_write_file and runtime_list_files as typed functions whose
docstrings carry an Args: section. That is exactly what smolagents' tool
decorator needs to build a tool's name, inputs and output type, so wrapping
them is one line.
Terminalpip install smolagents withruntimePythonfrom smolagents import ToolCallingAgent, toolfrom withruntime import Sandboxfrom withruntime.tools import sandbox_toolsdef solve(model, task: str) -> str: with Sandbox.create( network={"internet": True, "allow": ["pypi.org", "*.pythonhosted.org"]}, timeout_seconds=900, on_lease_end="stop", ) as sbx: tools = [tool(f) for f in sandbox_tools(sbx)] agent = ToolCallingAgent(tools=tools, model=model, max_steps=15) return str(agent.run(task))model is any smolagents model, such as InferenceClientModel() or
OpenAIModel(...). The sandbox exists for the length of the with block, so a
package installed in step two is still there in step nine, and it stops when the
block ends, error or not.
Prefer ToolCallingAgent here. A CodeAgent accepts the same tools and can
call them from its code, but the snippets it writes still run in whichever
executor executor_type names, which is your own process by default.
Check the tools before paying for a model
Each wrapped tool is callable on its own, so a smoke test needs no model:
Pythonfrom smolagents import toolfrom withruntime import Sandboxfrom withruntime.tools import sandbox_toolswith Sandbox.create() as sbx: run, read, write, ls = (tool(f) for f in sandbox_tools(sbx)) print(run.inputs) # command, cwd, timeout_seconds print(write(path="fib.py", content="a, b = 0, 1\nfor _ in range(90): a, b = b, a + b\nprint(a)\n")) print(run(command="python3 fib.py")) # {'exit_code': 0, 'stdout': '...', ...}runtime_exec returns the exit code, stdout, stderr and a timed_out flag, so
the model sees a failure as a failure. Relative paths land in /workspace.
Run the whole agent in the sandbox
smolagents' guide describes a second pattern for multi-agent systems: put the agent, its model calls and its tools all inside the sandbox. Its drawback, in the guide's words, is that it "may require transferring sensitive API keys to the sandbox environment". Runtime removes that step. Store the model key once as a secret bound to the provider's host:
Terminalprintf %s "$OPENAI_API_KEY" | npx withruntime secrets set OPENAI_API_KEY --host api.openai.comEvery sandbox of the account then has OPENAI_API_KEY set to a placeholder. The
host's proxy swaps in the real key only on HTTPS requests to api.openai.com,
so managed agents inside the sandbox can call the model while nothing in the
machine can read the key
(secrets sandboxes never see).
Pythonimport sysfrom withruntime import Sandboxtask = "What's the 20th Fibonacci number?"with Sandbox.create( network={"internet": True, "allow": ["api.openai.com", "pypi.org", "*.pythonhosted.org"]}, timeout_seconds=1800, on_lease_end="stop",) as sbx: sbx.files.upload("./my_agents", "/workspace/my_agents") sbx.exec("pip install 'smolagents[openai]'", check=True, timeout_ms=300_000) run = sbx.exec( ["python3", "manager.py", task], cwd="/workspace/my_agents", timeout_ms=1_200_000, on_stdout=sys.stdout.write, ) print(run.exit_code)manager.py is your own smolagents program; it uses OpenAIModel as it would
on your laptop. The allow-list keeps the sandbox to the model's API and the
package index.
Keep keys and spending in check
- The model never holds your Runtime key. Your code creates the sandbox and binds the tools; the model only chooses commands and paths.
- Cap each agent run.
timeout_secondswithon_lease_end="stop"ends a forgotten sandbox.max_cost_microsrefuses a create whose first lease would cost more than you set. - Cap the key. Give the application a key with a daily spending limit; past
it, creates fail with
spending_limit_reachedand nothing is charged (read-only keys and daily limits).
Which executor fits
Choose local only for trusted demos. Choose Docker when everything stays on
one machine you control. Choose Runtime when the agent needs a real shell, many
agents run at once, or managed agents need a model key without holding it. A
paid account runs 100 sandboxes at once to start, billed on the CPU they use:
$0.08 an hour for a 2 vCPU, 4 GiB sandbox with both CPUs busy
(pricing).
For the other Python frameworks see any other framework; for the risks being contained, see run untrusted LLM code; for container isolation compared with a microVM, see microVM vs container. New accounts get 50 free sandbox hours, no card:
Terminalnpx withruntime sandbox run --trial -- python3 -c 'print(6 * 7)'Related
Sources
- smolagents: Secure code execution, read 25 September 2026
- smolagents on PyPI, version 1.26.0, read 25 September 2026;
CodeAgent'sexecutor_typevalues and the@toolschema were read from that release's source
Facts on this page were checked on 25 September 2026.