Google ADK
Google ADK (Agent Development Kit) adapter for Flyte.
Bring your own google-adk agent and run it durably on Flyte. ADK’s Runner
owns the loop; Flyte is the runtime underneath: the tools you expose are Flyte tasks
(durable child actions), each model turn is recorded for replay (durable=True),
the run timeline renders into the task report, and memory_key gives cross-run
conversation memory.
flyteplugins.agents.google.tool— turn an@env.taskinto a Google ADK tool.flyteplugins.agents.google.run_agent— run the ADK agent loop inside your task and return the answer.flyteplugins.agents.google.durable_model— wrap a model so its turns are durable, for hand-built agent trees (e.g. sub-agent transfers) passed torun_agentviaagent=.
Set the model provider’s API key in the environment (e.g. GOOGLE_API_KEY for
Gemini) — wire it as a Flyte secret.
Directory
Classes
| Class | Description |
|---|---|
FlyteLlm |
A BaseLlm that records each model turn via durable_step for replay. |
Methods
| Method | Description |
|---|---|
durable_model() |
Wrap model (a name string or BaseLlm) so its turns are durable. |
run_agent() |
Run a Google ADK agent with the given tools and prompt; return the final text. |
run_agent_sync() |
Synchronous variant of run_agent for use in sync tasks; runs the async implementation on a dedicated event loop. |
tool() |
Wrap a Flyte @env.task as a plain async tool function — the generic default. |
Methods
durable_model()
def durable_model(
model: typing.Any,
) -> typing.AnyWrap model (a name string or BaseLlm) so its turns are durable.
Returns a flyteplugins.agents.google.FlyteLlm over the resolved inner model, or model unchanged
when it can’t be wrapped (durability is best-effort, never fatal).
| Parameter | Type | Description |
|---|---|---|
model |
typing.Any |
run_agent()
def run_agent(
input: str,
agent: typing.Any = None,
tools: typing.Sequence[typing.Any] = (),
model: str = 'gemini-2.0-flash',
instructions: str | None = None,
name: str = 'assistant',
max_llm_calls: int | None = None,
durable: bool = True,
observability: bool = True,
memory_key: str | None = None,
app_name: str = 'flyte-agent',
user_id: str = 'flyte-user',
) -> strRun a Google ADK agent with the given tools and prompt; return the final text.
Await this from an async task as await run_agent(...); from a sync task
use flyteplugins.agents.google.run_agent_sync instead.
Call this from inside an @env.task — that task is the durable parent, and each
tool the agent calls runs as a durable Flyte child action. Provide either a
pre-built agent (an ADK LlmAgent/BaseAgent) or tools + model +
instructions to have one built.
| Parameter | Type | Description |
|---|---|---|
input |
str |
The user prompt. |
agent |
typing.Any |
A pre-built ADK agent. Mutually exclusive with tools. |
tools |
typing.Sequence[typing.Any] |
tool-wrapped tools or bare @env.task templates. |
model |
str |
Model name for the built agent (e.g. gemini-2.0-flash). |
instructions |
str | None |
System instruction for the built agent. |
name |
str |
Agent name (a valid Python identifier). ADK injects this into the system prompt as the model’s “internal name”, so it can surface in replies — keep it natural (defaults to "assistant"; avoid a brand-y/internal label). |
max_llm_calls |
int | None |
Cap on model (LLM) calls before ADK raises LlmCallsLimitExceededError (its runaway-loop guard, via RunConfig.max_llm_calls); None uses ADK’s default of 500. Counts LLM calls, not conversational turns (a tool round is ~2 calls). For a wall-clock bound on the whole run, set timeout= on the enclosing @env.task. |
durable |
bool |
Wrap the model so each turn is recorded/replayed via flyte.trace. |
observability |
bool |
Render the run timeline into the Flyte task report. |
memory_key |
str | None |
Stable id (user/thread) for cross-run memory. When set, the session transcript is persisted and restored so a later run continues the conversation. |
app_name |
str |
ADK app name (namespacing). |
user_id |
str |
ADK user id. |
run_agent_sync()
def run_agent_sync(
input: str,
agent: typing.Any = None,
tools: typing.Sequence[typing.Any] = (),
model: str = 'gemini-2.0-flash',
instructions: str | None = None,
name: str = 'assistant',
max_llm_calls: int | None = None,
durable: bool = True,
observability: bool = True,
memory_key: str | None = None,
app_name: str = 'flyte-agent',
user_id: str = 'flyte-user',
) -> strSynchronous variant of run_agent for use in sync tasks; runs the async implementation on a dedicated event loop.
Run a Google ADK agent with the given tools and prompt; return the final text.
Await this from an async task as await run_agent(...); from a sync task
use flyteplugins.agents.google.run_agent_sync instead.
Call this from inside an @env.task — that task is the durable parent, and each
tool the agent calls runs as a durable Flyte child action. Provide either a
pre-built agent (an ADK LlmAgent/BaseAgent) or tools + model +
instructions to have one built.
| Parameter | Type | Description |
|---|---|---|
input |
str |
The user prompt. |
agent |
typing.Any |
A pre-built ADK agent. Mutually exclusive with tools. |
tools |
typing.Sequence[typing.Any] |
tool-wrapped tools or bare @env.task templates. |
model |
str |
Model name for the built agent (e.g. gemini-2.0-flash). |
instructions |
str | None |
System instruction for the built agent. |
name |
str |
Agent name (a valid Python identifier). ADK injects this into the system prompt as the model’s “internal name”, so it can surface in replies — keep it natural (defaults to "assistant"; avoid a brand-y/internal label). |
max_llm_calls |
int | None |
Cap on model (LLM) calls before ADK raises LlmCallsLimitExceededError (its runaway-loop guard, via RunConfig.max_llm_calls); None uses ADK’s default of 500. Counts LLM calls, not conversational turns (a tool round is ~2 calls). For a wall-clock bound on the whole run, set timeout= on the enclosing @env.task. |
durable |
bool |
Wrap the model so each turn is recorded/replayed via flyte.trace. |
observability |
bool |
Render the run timeline into the Flyte task report. |
memory_key |
str | None |
Stable id (user/thread) for cross-run memory. When set, the session transcript is persisted and restored so a later run continues the conversation. |
app_name |
str |
ADK app name (namespacing). |
user_id |
str |
ADK user id. |
tool()
def tool(
func: AsyncFunctionTaskTemplate | typing.Callable | None = None,
name: str | None = None,
description: str | None = None,
) -> typing.CallableWrap a Flyte @env.task as a plain async tool function — the generic default.
For SDKs that accept plain Python callables as tools (deriving the schema from the
signature + docstring), this is the whole adapter tool: the returned
function carries the task’s signature (functools.wraps), dispatches to
task.aio() (so each call is a durable Flyte child action), exposes
__wrapped_task__, and wires the backing task to flyteplugins.agents.core.ToolTaskResolver.
Adapters whose SDK needs a native tool type (e.g. OpenAI’s
FunctionTool, Claude’s MCP SdkMcpTool) provide their own instead.
Also accepts any other callable — a plain function or an instance of a callable
class defining __call__ — and returns it usable as a tool as-is, since the
plain-callable SDKs derive the schema by inspecting the callable (a class instance
is inspected through its __call__). A name or description override is
applied to the callable best-effort.
Usable bare, parametrized or as a direct call:
@tool
@env.task
async def get_weather(city: str) -> str: ...| Parameter | Type | Description |
|---|---|---|
func |
AsyncFunctionTaskTemplate | typing.Callable | None |
|
name |
str | None |
|
description |
str | None |