Google ADK code execution in a secure sandbox, with any model
Give an ADK agent Runtime's sandbox functions as tools; ADK wraps plain functions, and the code runs in a Firecracker microVM.
On Runtime code execution is one more set of tools, so it combines with the rest of your agent. ADK's documentation says its Gemini code execution tool "can only be used by itself within an agent instance", and it serves Gemini 2 and later models only. Runtime's four tools sit beside your search, database and custom tools on any model ADK can call, and each command runs in a microVM with its own Linux kernel. The median sandbox ran its first Python command 351 ms after the create request on 24 September 2026. google-adk 2.9.2 was the current PyPI release on 25 September 2026.
ADK's code executors compared
ADK attaches a code_executor to an LlmAgent, and runs code blocks the
model writes. google-adk 2.9.2 ships these:
| Executor | Where code runs | Fits |
|---|---|---|
BuiltInCodeExecutor |
Gemini's own code execution; Gemini models only | Gemini agents that need nothing else |
UnsafeLocalCodeExecutor |
Your own Python process | Trusted code in development |
ContainerCodeExecutor |
A Docker container, network off and capabilities dropped by default | A host with a Docker daemon |
GkeCodeExecutor |
A Kubernetes Job per run with gVisor, or an Agent Sandbox pod | Teams already operating GKE |
VertexAiCodeExecutor |
Vertex AI's Code Interpreter Extension | Google Cloud projects |
AgentEngineSandboxCodeExecutor |
An Agent Engine code execution sandbox | Vertex AI Agent Engine deployments |
| Runtime tools (this page) | A Runtime Firecracker microVM | Any model, any host, mixed with tools |
ContainerCodeExecutor's own docstring advises that "for stronger,
kernel-level isolation of untrusted code" you prefer the GKE or Vertex
executors. A Runtime sandbox gives that kernel-level boundary without a cluster
or a Google Cloud project: each sandbox is a virtual machine.
Add the tools
ADK wraps plain Python functions as FunctionTools, reading the name,
docstring and type hints, so sandbox_tools(sbx) goes straight into tools.
This is the agent from the framework guide:
Terminalpip install google-adk withruntimePythonfrom google.adk.agents import Agentfrom withruntime import Sandboxfrom withruntime.tools import sandbox_toolsdef coder(model: str, sbx: Sandbox) -> Agent: return Agent( name="coder", model=model, instruction="Run code in the sandbox to answer.", tools=sandbox_tools(sbx), )Run it end to end
ADK agents run through a Runner with a session service. InMemoryRunner
provides one, which is enough for a script or a request handler:
Pythonfrom google.adk.runners import InMemoryRunnerfrom google.genai import typesfrom withruntime import Sandboxasync def solve(model: str, task: str) -> str: with Sandbox.create(timeout_seconds=900, on_lease_end="stop") as sbx: runner = InMemoryRunner(agent=coder(model, sbx), app_name="coder") session = await runner.session_service.create_session(app_name="coder", user_id="me") message = types.Content(role="user", parts=[types.Part(text=task)]) answer = "" async for event in runner.run_async(user_id="me", session_id=session.id, new_message=message): if event.is_final_response() and event.content and event.content.parts: answer = event.content.parts[0].text or "" return answercoder is the function above. The model decides when to call
runtime_exec, reads the exit code and output, and can write a file with
runtime_write_file before running it. This loop was run on 25 September 2026
against google-adk 2.9.2 with a scripted model, to check that the tool call
reaches the sandbox and its result reaches the final answer.
Mixing tools, which the built-in executor cannot do
Because the sandbox tools are ordinary function tools, one agent can hold them next to anything else:
Pythonfrom google.adk.agents import Agentfrom withruntime import Sandboxfrom withruntime.tools import sandbox_toolsdef lookup_order(order_id: str) -> dict: """Fetch an order from the shop database. Args: order_id: The order's id. """ return {"order_id": order_id, "items": 3}def support_agent(model: str, sbx: Sandbox) -> Agent: return Agent( name="support", model=model, instruction="Look orders up, then compute refunds with Python in the sandbox.", tools=[lookup_order, *sandbox_tools(sbx)], )For the ADK multi-agent patterns, a SequentialAgent or a parent with
sub_agents can give only one child the sandbox tools, which keeps code
execution in the agent you intend.
Keys, network and spend
- Model keys stay in your process. The agent loop, and so the Gemini or other model key, runs in your application. The sandbox receives commands, not credentials.
- Tokens the code needs go in as Runtime secrets. The sandbox holds a placeholder; the host's proxy adds the real value only on HTTPS requests to the hosts the secret names.
- Outbound traffic follows the sandbox's rules:
network={"internet": False}for pure computation, or an allow-list such as["pypi.org", "*.pythonhosted.org"]for installs. Root inside the sandbox cannot change them. - Cost ceilings:
max_cost_microson each create, and a daily spending limit on the application's key that only a person can set (read-only keys and daily limits).
Cost of a run
Runtime bills the CPU the commands use, at $0.025 per vCPU-hour with a floor of a twentieth of a vCPU, plus $0.0075 per GiB-hour of memory. The default 2 vCPU, 4 GiB sandbox costs $0.03125 an hour while the agent waits on Gemini, and $0.08 with both CPUs busy. A thousand one-minute runs that each use 20 CPU-seconds cost $0.64 (pricing).
See also run untrusted LLM code and, for the runtime behind the GKE executor's job mode, Firecracker vs gVisor. New accounts get 50 free sandbox hours, no card:
Terminalnpx withruntime sandbox run --trial -- python3 -c 'print(6 * 7)'Related
Sources
- ADK: Gemini API code execution tool, supported models and the single-tool limitation, read 25 September 2026
- ADK: GKE code executor, read 25 September 2026
- google-adk on PyPI, version 2.9.2; the executor classes, their docstrings and
InMemoryRunnerwere read from that release's source on 25 September 2026
Facts on this page were checked on 25 September 2026.