# How to give an Agno agent a secure sandbox for code execution Pass Runtime's four sandbox functions to an Agno `Agent`; commands then run in a disposable microVM, with approval gates if you want them. **On Runtime an Agno agent gets a real machine that is not yours.** Agno's `PythonTools` and `ShellTools` run in the agent's own process and host, and Agno's logs say so: `PythonTools` "executes arbitrary Python in this process". Runtime's tools run each command in a Firecracker microVM with its own kernel, created in 351 ms at the median (24 September 2026), with network rules and a cost cap your application sets. agno 3.0.11 was the current PyPI release on 25 September 2026. ## Agno's code tools and where they run agno 3.0.11 ships these toolkits for running code: | Toolkit | Where code runs | Agno's own note | | -------------- | ---------------------------------- | --------------------------------------------------------------------- | | `PythonTools` | The agent's Python process | "safe_globals/safe_locals and restrict_to_base_dir are not a sandbox" | | `ShellTools` | The agent's host shell | "The command is executed directly on the host OS" | | `CodeMode` | An IPython kernel beside the agent | "It is not a sandbox and does not pretend to be one" | | `DockerTools` | Containers on your Docker daemon | Lets the agent run, exec into and build containers on the host | | `E2BTools` | An E2B sandbox | Needs an E2B account | | `DaytonaTools` | A Daytona sandbox | Needs a Daytona account | | Runtime tools | A Runtime Firecracker microVM | Plain functions; no Agno plugin needed | The quotes come from agno 3.0.11's source. ## Add the sandbox to an agent Agno's docs put it plainly: "Any Python function can be used as a tool by an Agent." `sandbox_tools(sbx)` returns four typed, documented functions, so they go into `tools` as they are: ```bash no-run pip install agno withruntime ``` ```python check from agno.agent import Agent from withruntime import Sandbox from withruntime.tools import sandbox_tools def 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: agent = Agent( model=model, tools=sandbox_tools(sbx), instructions="Use the Linux sandbox for any code. Check exit codes.", ) return str(agent.run(task).content) ``` `model` is any Agno model, such as `OpenAIChat(id=...)` from `agno.models.openai`. Agno reads the functions' docstrings into parameter descriptions: the LLM sees `runtime_exec` with a required `command` and optional `cwd` and `timeout_seconds`. ## Ask a person before each command Agno's `tool` decorator takes `requires_confirmation=True`. Wrap only `runtime_exec`, and the agent may read and write files freely but pauses before running anything: ```python check from agno.agent import Agent from agno.tools import tool from withruntime import Sandbox from withruntime.tools import sandbox_tools def supervised(model, task: str) -> str: with Sandbox.create(timeout_seconds=1800, on_lease_end="stop") as sbx: run, read, write, ls = sandbox_tools(sbx) agent = Agent(model=model, tools=[tool(requires_confirmation=True)(run), read, write, ls]) response = agent.run(task) while response.is_paused: for requirement in response.active_requirements: if requirement.needs_confirmation: command = requirement.tool_execution.tool_args["command"] if input(f"Run `{command}`? [y/N] ").lower() == "y": requirement.confirm() else: requirement.reject() response = agent.continue_run(response) return str(response.content) ``` This flow ran on 25 September 2026 against agno 3.0.11 with a scripted OpenAI-style endpoint: the run paused on `runtime_exec`, showed the command, and finished after the approval. The sandbox is the second line of defence: an approved command that turns out to be harmful still lands in a throwaway machine. ## Teams that share a workspace In an Agno `Team`, hand the same sandbox's tools to the members that build and test, and none to the member that plans or reviews. They then work on one `/workspace`, and every file one member writes is there for the next. For work that splits into independent attempts, create a sandbox per member; a paid account runs 100 sandboxes at once to start. ## Credentials and cost Three separate things need protecting. 1. **The Runtime key** lives in your application's environment (`RUNTIME_API_KEY`) or this machine's saved connection. The model never receives it; it only picks commands and paths. 2. **Keys the sandboxed code uses**, such as a GitHub token, go in as Runtime secrets bound to named hosts. The sandbox's environment holds a placeholder; the host's proxy puts the real value on HTTPS requests to those hosts only ([secrets](/docs/security#secrets-sandboxes-never-see)). 3. **Money.** Give the application's key a daily spending limit, which only a person can set or raise, and pass `max_cost_micros` on creates you want capped ([read-only keys and daily limits](/docs/python#read-only-keys-and-daily-limits)). What a sandbox costs: the default 2 vCPU, 4 GiB costs $0.03125 an hour while the agent waits on the model and $0.08 with both CPUs busy, because Runtime bills measured CPU at $0.025 per vCPU-hour and memory at $0.0075 per GiB-hour ([pricing](/docs/pricing)). ## Choosing Keep `PythonTools` and `CodeMode` for trusted, supervised sessions, as Agno itself advises. Use Runtime when the agent faces user input or web content, when you want a shell and package installs without exposing the host, or when a person should approve commands and a VM boundary should still stand behind the approval. Read on: [coding agent sandbox](/use-cases/coding-agent-sandbox), [egress control](/glossary/egress-control) and [the E2B alternatives](/compare/e2b-alternatives). New accounts get 50 free sandbox hours, no card: ```bash no-run npx withruntime sandbox run --trial -- python3 -c 'print(6 * 7)' ``` ## Sources - [Agno: Creating your own tools](https://docs.agno.com/tools/tool-decorator), read 25 September 2026 - [Agno: Confirmation required](https://docs.agno.com/examples/agents/human-in-the-loop/confirmation-required), read 25 September 2026 - [agno on PyPI](https://pypi.org/project/agno/), version 3.0.11; the toolkit list, the quoted warnings and `continue_run` were read from that release's source on 25 September 2026 Facts on this page were checked on 25 September 2026.