# 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". That tool 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. Each command runs in a microVM with its own Linux kernel. google-adk 2.13.0 was the current PyPI release on 25 October 2026. ## ADK's code executors compared ADK attaches a `code_executor` to an `LlmAgent`. The executor runs the code blocks that the model writes. google-adk 2.13.0 ships these executors: | 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 provides 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 `FunctionTool`s. It reads the name, docstring and type hints. So `sandbox_tools(sbx)` goes straight into `tools`. This is the agent from the [framework guide](/docs/frameworks#google-adk): ```bash no-run pip install google-adk withruntime ``` ```python check from google.adk.agents import Agent from withruntime import Sandbox from withruntime.tools import sandbox_tools def 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. It is enough for a script or a request handler: ```python check from google.adk.runners import InMemoryRunner from google.genai import types from withruntime import Sandbox async 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 answer ``` `coder` is the function above. The model decides when to call `runtime_exec`. It reads the exit code and output. It can also write a file with `runtime_write_file` before running it. On 25 September 2026, this loop ran against google-adk 2.9.2 with a scripted model. The check confirmed that the tool call reaches the sandbox and that 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: ```python check from google.adk.agents import Agent from withruntime import Sandbox from withruntime.tools import sandbox_tools def 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 the sandbox tools to only one child. This 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](/docs/security#secrets-sandboxes-never-see). The sandbox holds a placeholder. The host's proxy adds the real value only to HTTPS requests to the hosts that 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:** set `max_total_cost_micros` on each sandbox. Set a daily spending limit on the application's key, which only a person can set ([read-only keys and daily limits](/docs/security#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. It also bills $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. With both CPUs busy, it costs $0.08 an hour. A thousand one-minute runs that each use 20 CPU-seconds cost $0.64 ([pricing](/docs/pricing)). See also [run untrusted LLM code](/use-cases/run-untrusted-llm-code). For the runtime behind the GKE executor's job mode, see [Firecracker vs gVisor](/compare/firecracker-vs-gvisor). A new account gets 100 free hours of a 1 GB machine in its first 30 days, without a card: ```bash no-run printf '%s\n' 'print(sum([125, 250, 375]))' > invoice.py npx withruntime sandboxes run -- python3 - < invoice.py ``` ## Related - [LLM tool use in a sandbox](/use-cases/llm-tool-use-sandbox) - [Gemini API code execution in a sandbox](/integrations/gemini-api) - [What is tool calling?](/glossary/tool-calling) ## Sources - [ADK: Gemini API code execution tool](https://adk.dev/integrations/code-execution/), supported models and the single-tool limitation, read 25 October 2026 - [ADK: GKE code executor](https://adk.dev/integrations/gke-code-executor/), read 25 October 2026 - [google-adk on PyPI](https://pypi.org/project/google-adk/), version 2.13.0; the executor classes, their docstrings and `InMemoryRunner` were read from that release's source on 25 October 2026 Facts on this page were checked on 25 October 2026.