Default runtime
The ADK runtime is the default and needs no extra configuration:Switch the execution backend
Useruntime to select the inner-loop execution backend:
Use the Codex runtime
The Codex runtime requires the optionalcodex dependency group, which is not
installed with VeADK by default. Install the required dependencies before using
it:
codex extra includes the OpenAI Codex SDK and the Codex CLI binary.
The model name, API endpoint, and API key still come from the agent’s model
configuration:
Agent configuration; the Codex runtime does
not require a separate registration path:
- function tools in
toolsare exposed as callable tools to the model; - an MCPToolset in
toolssupports tool discovery and invocation; - skills loaded through
SkillToolsetor VeADK’s legacy entry are made available through the Codex skill mechanism.
Codex security configuration
The Codex runtime defaults to least-privilege settings suited to a multi-tenant service: each invocation uses a session-isolated workspace, theworkspace_write sandbox, no network access, and denial of escalated
operations. Broader access must be enabled explicitly.
Pass a CodexRuntimeConfig through the Agent codex_runtime_config
parameter:
agent.py
CodexRuntimeConfig parameters:
The following environment variables override the corresponding
CodexRuntimeConfig field without changing code, and take precedence over codex_runtime_config:
Codex observability
Codex-native lifecycle notifications and ADK Function/MCP tool calls are converted into standard ADK Events, so tool calls, results, state changes, confirmations, and authentication surface in Session, Trace, and the UI. Runtime logs use stablecodex_* event names and attribution fields such as invocation_id, call_id, tool, status, and duration_ms. Tool arguments, tool results, API tokens, credentials, and backend addresses are not logged. Token usage is exposed through codex_event_type=token_usage events and the corresponding log entry.
Configure transient-error retries
When the Codex runtime calls the model backend, it retries transient failures such as rate limits, server errors, overloads, and timeouts. It retries at most twice by default. Use these environment variables to change the behavior:Use PiAgent
- the executable referenced by
PIAGENT_BINARY; - the managed cache under
PIAGENT_INSTALL_DIR, which defaults to~/.cache/veadk/piagent; - if the cache is missing, a downloaded and verified PiAgent release.
Automatic installation requires access to the PiAgent release host. In offline or restricted networks, install the binary in advance and set
PIAGENT_BINARY.Output persistence
Agent inherits from Google ADK’s LlmAgent and supports persisting the
agent’s final text response to session state through the output_key parameter.
Other agents that run later in the same session can read that state, making it
useful for passing results between agents in a multi-agent workflow.
output_key works across all runtimes, including the default ADK runtime
and external runtimes such as codex and piagent. With an external runtime,
the final response is still written to session state.SequentialAgent to chain two agents: the planner’s
output is written to session state via output_key="plan", and the writer reads
that state in the same session:
pipeline.py
plan and draft hold the final
responses from the planner and the writer respectively.
Model callbacks
Agent inherits from Google ADK’s LlmAgent, so you can use
before_model_callback, after_model_callback, and
on_model_error_callback to inject custom logic before and after the model
call and on errors. These callbacks, together with the same-named methods on
ADK plugins (subclasses of BasePlugin), run in every runtime — the default
ADK runtime and external runtimes such as codex and piagent. In external
runtimes, callbacks run in ADK order: plugin callbacks first, then agent
callbacks.
The
LlmRequest built by an external runtime exposes only the stable fields
callbacks need (conversation contents, system instruction, output schema,
tools, and generation config); it does not run ADK’s full preprocessing
pipeline. Callback behavior that depends on ADK-internal preprocessing stages
may therefore differ in external runtimes.async def). The following
example uses before_model_callback in the Codex runtime to render PDF
attachments into images so a vision-capable model can read the document:
agent.py
on_model_error_callback to return a fallback response when the model call
fails, instead of letting the exception propagate to the caller:
agent.py
Choose where each tool runs
Whereas a runtime replaces an agent’s entire inner loop, aRuntimeProvider
operates at a narrower layer: it decides where each individual tool call
executes while the model reasoning loop remains unchanged. It works as an ADK
plugin — by intercepting before_tool_callback, it takes over the call before
Google ADK invokes the tool implementation, so the local implementation is not
executed a second time.
VeADK exposes the following public classes:
Usage example
The following example dispatches every non-MCP tool to a remote runtime; MCP tools retain their original ADK implementation:agent.py
dispatch_task and
its local function is not invoked a second time. Pass a set of tool names to
dispatch only those non-MCP tools. The dispatch function may be synchronous or
asynchronous.
To register directly on an Agent instead of through the Runner plugins
parameter, pass the DispatchRuntimeProvider’s before_tool_callback to the
Agent’s before_tool_callback parameter:
agent.py
DispatchRuntimeProvider parameters
ToolCall fields
MCP tools always retain their original ADK implementation and are not affected
by the
dispatchable_tools configuration, because MCP tool invocation must go
through its own MCP session manager.Request processing
Without touching business logic, you can inject shared cross-cutting processing into each run. Pass a processor torun_processor, for example to enforce login
via identity authentication:
AuthRequestProcessor as a ready-made implementation for identity authentication.
Custom processors
Every processor subclasses the abstract baseBaseRunProcessor and implements
its process_run(runner, message) method. That method returns a decorator
wrapping the run’s event stream, letting you:
- inject logic before and after the whole run (auth, logging, monitoring);
- intercept, rewrite, or inject events produced during the run;
- build control logic such as retries on top of that.