# 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 on its host. 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. Your application sets the network rules and the cost cap. agno 3.1.10 was the current PyPI release on 25 October 2026. ## Agno's code tools and where they run agno 3.1.10 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.1.10's source. ## Add the sandbox to an agent Agno's docs state that "Any Python function can be used as a tool by an Agent." `sandbox_tools(sbx)` returns four typed, documented functions. Pass them to `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 each function's docstring into its 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`. The agent can then read and write files without asking, but it pauses before it runs any command: ```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` and showed the command. It finished after the approval. The sandbox is the second line of defense. An approved command that turns out to be harmful still runs in a disposable machine. ## Teams that share a workspace In an Agno `Team`, give the tools of one sandbox to the members that build and test. Give none to the member that plans or reviews. They then work in one `/workspace`, and every file one member writes is there for the next. For work that splits into independent attempts, create a sandbox for each member. A paid account runs 100 sandboxes at the same time. ## Credentials and cost Three separate things need protection. 1. **The Runtime key** lives in your application's environment (`RUNTIME_API_KEY`) or in this machine's saved connection. The model never receives it. The model only chooses 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. Only a person can set or raise that limit. Pass `max_total_cost_micros` on any sandbox you want capped ([read-only keys and daily limits](/docs/python#read-only-keys-and-daily-limits)). The default 2 vCPU, 4 GiB sandbox costs $0.03125 an hour while the agent waits on the model. It costs $0.08 an hour with both CPUs busy. 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 sessions that a person supervises. Agno's own documentation advises this. Use Runtime when the agent handles user input or web content. Use it when you want a shell and package installs without exposing the host. Use it when a person should approve commands, and a VM boundary should still stand behind that approval. Read on: [coding agent sandbox](/use-cases/coding-agent-sandbox), [egress control](/glossary/egress-control) and [the E2B alternatives](/compare/e2b-alternatives). A new account gets 100 free hours of a 1 GB machine in its first 30 days. No card is needed: ```bash no-run printf '%s\n' 'print(sum([125, 250, 375]))' > invoice.py npx withruntime sandboxes run -- python3 - < invoice.py ``` ## Sources - [Agno: Creating your own tools](https://docs.agno.com/tools/tool-decorator), read 25 October 2026 - [Agno: Confirmation required](https://docs.agno.com/examples/agents/human-in-the-loop/confirmation-required), read 25 October 2026 - [agno on PyPI](https://pypi.org/project/agno/), version 3.1.10. The toolkit list, the quoted warnings and `continue_run` were read from that release's source on 25 October 2026 Facts on this page were checked on 25 October 2026.