Runtime

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 withruntime
Pythonfrom 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 answer

coder 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_micros on 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)'

Sources

Facts on this page were checked on 25 September 2026.