docs/guides/code_executors/code_executor/index.md
BaseCodeExecutor is the interface ADK uses to execute model-generated code blocks and incorporate execution results into the conversation. It supports model-delegated execution, isolated local processes, Docker containers, Kubernetes/GKE sandboxes, and managed Vertex AI / Agent Engine backends.
Language models excel at generating code to perform mathematical calculations, data transformations, and chart rendering, but they cannot execute code directly without an execution runtime. Running untrusted model-generated code on an application server introduces security and reliability risks, including resource exhaustion, privilege escalation, and credential exposure.
The code executor subsystem resolves this by abstracting code execution behind BaseCodeExecutor. An LlmAgent delegates code block extraction, execution isolation, and result formatting to the configured executor. Six implementations ship with ADK covering development, containerized isolation, Kubernetes orchestration, and Google Cloud managed environments.
The code executor is configured on an LlmAgent through the code_executor parameter. The example below configures UnsafeLocalCodeExecutor to run Python code generated by the agent in a local subprocess:
agent = LlmAgent(
name="calculator_agent",
instruction="When asked a math problem, write Python code to compute the exact result.",
code_executor=UnsafeLocalCodeExecutor(timeout_seconds=30),
)
When the model produces a code block enclosed in Python delimiters, the agent intercepts the block, runs it through execute_code, and feeds the standard output or error back to the model before returning the final answer.
The execution lifecycle coordinates between LlmAgent, the _code_execution flow processor, CodeExecutionUtils, and the executor:
sequenceDiagram
autonumber
participant Model as LLM / Model Response
participant Flow as _code_execution Processor
participant Utils as CodeExecutionUtils
participant Exec as BaseCodeExecutor
Model->>Flow: Generates response with code block
Flow->>Utils: extract_code_and_truncate_content()
Utils-->>Flow: Returns extracted ExecutableCode Part
Flow->>Exec: execute_code(InvocationContext, CodeExecutionInput)
Exec-->>Flow: Returns CodeExecutionResult (stdout/stderr/files)
Flow->>Utils: build_code_execution_result_part()
Utils-->>Flow: Returns CodeExecutionResult Part
alt Execution Failed (stderr) & retries remaining
Flow->>Model: Re-send error in conversation for correction
else Success or max retries reached
Flow->>Model: Pass execution result for final synthesis
end
CodeExecutionUtils.extract_code_and_truncate_content scans the response text for delimiters configured in code_block_delimiters (e.g. ```python or ```tool_code). The first detected code block is extracted into a types.Part.from_executable_code.CodeExecutionInput and invokes code_executor.execute_code(invocation_context, code_execution_input).CodeExecutionResult captures stdout, stderr, and generated output_files. CodeExecutionUtils.build_code_execution_result_part converts this into a types.Part.from_code_execution_result with status OUTCOME_OK or OUTCOME_FAILED.stderr, the agent increments the invocation error count via CodeExecutorContext. If error_retry_attempts has not been exceeded, the error is appended to the conversation context and sent back to the model for correction.CodeExecutionUtils.convert_code_execution_parts converts prior executable code and result parts to text representations so standard chat models without native code-execution tool calling can parse previous turns.The base class defines the following configuration options:
| Option | Type | Default | Description |
|---|---|---|---|
optimize_data_file | bool | False | Extract and process CSV data files from the model request and attach them to the executor. |
stateful | bool | False | Whether state and variables persist across multiple code executions within a session. |
error_retry_attempts | int | 2 | Number of consecutive execution error retries before giving up. |
code_block_delimiters | list[tuple[str, str]] | [('```tool_code\n', '\n```'), ('```python\n', '\n```')] | Delimiter pairs used to locate code blocks in model output. |
execution_result_delimiters | tuple[str, str] | ('```tool_output\n', '\n```') | Delimiters used when formatting execution output for text-based model turns. |
timeout_seconds | int | None | None | Wall-clock execution timeout in seconds. |
optimize_data_file instructs the flow to inspect user prompt parts for text/csv payloads, parsing them and placing them into CodeExecutionInput.input_files so the executed code can load datasets without manual upload plumbing.
stateful declares whether variables, functions, and imports defined in one turn remain accessible in subsequent code executions. Stateless executors recreate fresh processes for every snippet.
error_retry_attempts limits the self-correction loop when generated code raises an exception or syntax error. Once exhausted, the agent stops re-prompting the model and surfaces the error.
code_block_delimiters and execution_result_delimiters control the syntactic markup for identifying code blocks in model output and presenting results back to models that do not support native executable code parts.
timeout_seconds sets a hard cutoff for code execution. Subclasses implement timeouts via supervisor processes, container alarms, or Kubernetes watch intervals.
All concrete code executor implementations are imported from google.adk.code_executors.
| Implementation | Environment / Use Case | Isolation Level |
|---|---|---|
BuiltInCodeExecutor | Gemini native server-side execution. | Model provider sandbox |
UnsafeLocalCodeExecutor | Local dev and unit tests. Runs via multiprocessing.Process. | None (runs on host machine) |
ContainerCodeExecutor | Local or self-hosted Docker container with network disabled and dropped capabilities. | Container isolation |
GkeCodeExecutor | Kubernetes cluster using gVisor-sandboxed Pods or Agent Sandbox client. | Kernel sandbox (gVisor) |
VertexAiCodeExecutor | Google Cloud Vertex AI Code Interpreter Extension. | Managed cloud sandbox |
AgentEngineSandboxCodeExecutor | Vertex AI Reasoning Engine / Agent Engine sandbox environments. | Managed cloud sandbox |
For self-hosted production workloads, ContainerCodeExecutor provides isolated Docker execution with non-root security defaults:
from google.adk.agents import LlmAgent
from google.adk.code_executors import ContainerCodeExecutor
agent = LlmAgent(
name="data_analyst",
instruction="Analyze data using Python scripts.",
code_executor=ContainerCodeExecutor(
image="python:3.11-slim",
network_enabled=False,
timeout_seconds=60,
),
)
In Kubernetes environments, GkeCodeExecutor provisions ephemeral Jobs with gVisor (runsc) runtime isolation:
from google.adk.agents import LlmAgent
from google.adk.code_executors import GkeCodeExecutor
agent = LlmAgent(
name="k8s_code_agent",
code_executor=GkeCodeExecutor(
namespace="agent-sandboxes",
image="python:3.11-slim",
cpu_limit="1000m",
mem_limit="1Gi",
timeout_seconds=120,
),
)
UnsafeLocalCodeExecutor: UnsafeLocalCodeExecutor executes code on the local host. It must never be used with untrusted user input in production.UnsafeLocalCodeExecutor and ContainerCodeExecutor do not support stateful=True or optimize_data_file=True. Setting either parameter raises ValueError.VertexAiCodeExecutor, ContainerCodeExecutor, GkeCodeExecutor, and AgentEngineSandboxCodeExecutor require extra packages installed via pip install "google-adk[extensions]".BuiltInCodeExecutor.GkeCodeExecutor.VertexAiCodeExecutor.AgentEngineSandboxCodeExecutor.