chore: import upstream snapshot with attribution
Continuous Integration / Pre-commit Linter (push) Waiting to run
Continuous Integration / Mypy Check (Python 3.10) (push) Waiting to run
Continuous Integration / Mypy Check (Python 3.11) (push) Waiting to run
Continuous Integration / Mypy Check (Python 3.12) (push) Waiting to run
Continuous Integration / Mypy Check (Python 3.13) (push) Waiting to run
Continuous Integration / Unit Tests (Python 3.10) (push) Waiting to run
Continuous Integration / Unit Tests (Python 3.11) (push) Waiting to run
Continuous Integration / Unit Tests (Python 3.12) (push) Waiting to run
Continuous Integration / Unit Tests (Python 3.13) (push) Waiting to run
Continuous Integration / Unit Tests (Python 3.14) (push) Waiting to run
Continuous Integration / A2A v0.3 Tests (Python 3.10) (push) Waiting to run
Continuous Integration / A2A v0.3 Tests (Python 3.11) (push) Waiting to run
Continuous Integration / A2A v0.3 Tests (Python 3.12) (push) Waiting to run
Continuous Integration / A2A v0.3 Tests (Python 3.13) (push) Waiting to run
Continuous Integration / A2A v0.3 Tests (Python 3.14) (push) Waiting to run
Copybara PR Handler / close-imported-pr (push) Waiting to run

This commit is contained in:
wehub-resource-sync
2026-07-13 13:25:13 +08:00
commit ec2b666284
2231 changed files with 491535 additions and 0 deletions
+190
View File
@@ -0,0 +1,190 @@
# LlmAgent Single-Turn Mode
This guide explains the behavior of `LlmAgent` in `single_turn` mode, both when
executed as a workflow node and when defined as a sub-agent in a multi-agent
hierarchy. It covers default stateless execution, delegation mechanics, and how
to configure history visibility.
--------------------------------------------------------------------------------
## Introduction
In ADK, `mode="single_turn"` is designed for isolated, stateless tasks where the
agent only needs to process the immediate input without accumulating or
referencing prior conversation history.
Depending on how the agent is deployed—either as a step in a `Workflow` or as a
`sub_agent` of another LLM agent—its behavior and interaction patterns differ.
--------------------------------------------------------------------------------
## 1. Single-Turn Mode as a Workflow Node
When building a `Workflow` graph, any `LlmAgent` added to the graph defaults to
`mode="single_turn"` (unless explicitly configured otherwise).
### Behavior
- **Stateless by Default**: The node does not see previous conversation turns
in the workflow session. Its history visibility (`include_contents`)
automatically defaults to `'none'`.
- **Isolated Execution**: Each execution of the node is independent.
### Example
```python
from google.adk.agents import LlmAgent
from google.adk.workflow import Workflow, build_node
# Defaults to mode="single_turn" when run as a node
writer_agent = LlmAgent(
name="writer",
instruction="Write a short story about the input topic."
)
writer_node = build_node(writer_agent)
wf = Workflow(
name="story_generator",
edges=[
("START", writer_node),
(writer_node, "END")
]
)
```
--------------------------------------------------------------------------------
## 2. Single-Turn Mode as a Sub-Agent
You can define hierarchical agent structures by assigning agents to the
`sub_agents` list of a parent `LlmAgent`.
### Behavior
- **Exposed as a Tool**: A `single_turn` sub-agent is **not** a transfer
target. The parent agent cannot hand over control of the conversation to it.
Instead, the framework automatically exposes the sub-agent to the parent as
a **Tool** (function).
- **Functional Delegation**: The parent agent calls the sub-agent like a
function, passing arguments. The sub-agent executes, returns its output to
the parent, and the parent continues the conversation.
- **Isolated Sub-Branch**: When the parent calls the sub-agent tool, the
framework executes the sub-agent in an isolated sub-branch (derived from the
parent's branch, e.g., `parent_branch.sub_agent@run_id`).
- **Stateless by Default**: Like the workflow node, a `single_turn` sub-agent
defaults to `include_contents="none"` and only sees the inputs passed to it
in the tool call.
### Example
```python
from google.adk.agents import LlmAgent
# Define a specialized single-turn sub-agent
translator_agent = LlmAgent(
name="translator",
instruction="Translate the input text to Spanish.",
mode="single_turn" # Must be explicit if not auto-wrapped in workflow
)
# Define the parent agent and assign the sub-agent
bilingual_writer = LlmAgent(
name="bilingual_writer",
instruction="Write a poem about the topic, then use the translator tool to translate it.",
sub_agents=[translator_agent] # Exposes 'translator' as a tool to bilingual_writer
)
```
### Non-LlmAgent single-turn sub-agents
`single_turn` composition is not limited to `LlmAgent`. A `ManagedAgent`
(server-backed) can also be a single-turn sub-agent by setting
`mode='single_turn'`; ADK auto-exposes it to the parent as an inline tool, and
its internal events are preserved in the shared session. Each single-turn managed
call is stateless (isolated per call), so pass a self-contained request.
```python
from google.adk.agents import LlmAgent, ManagedAgent
specialist = ManagedAgent(
name="search_specialist",
mode="single_turn",
agent_id="...",
environment={"type": "remote"},
description="Answers questions needing fresh, grounded web facts.",
)
coordinator = LlmAgent(name="coordinator", sub_agents=[specialist])
```
--------------------------------------------------------------------------------
## How Context Isolation Works
ADK manages history visibility using **branches** and the `include_contents`
configuration:
1. **Branch Hierarchy**: When a sub-agent runs, it executes in a sub-branch
(e.g., `main.translator@1`).
- A sub-branch is allowed to read events from its parent branch (one-way
visibility).
- The parent branch cannot read events from the sub-branch (protecting the
parent from sub-agent internal reasoning chatter).
2. **History Filtering**:
- **`include_contents="none"`** (Default): The agent bypasses history
loading entirely. It only sees the immediate input (the workflow node
input or the tool call arguments).
- **`include_contents="default"`**: The agent loads conversation history.
Because of the branch hierarchy, a sub-agent with this setting can see
the parent agent's conversation history leading up to the tool call.
--------------------------------------------------------------------------------
## Configuration Options
Parameter | Type | Default | Description
:----------------- | :--------------------------------------- | :------------------------------------ | :----------
`mode` | `Literal['single_turn', 'task', 'chat']` | `'single_turn'` (when run as node) | The execution mode. `single_turn` isolates execution; `task` supports delegation; `chat` preserves full history.
`include_contents` | `Literal['default', 'none']` | `'none'` (for `single_turn` if unset) | Controls history visibility. For `single_turn` mode, it defaults to `'none'` (stateless), but can be explicitly set to `'default'` to make the agent context-aware.
--------------------------------------------------------------------------------
## Advanced Applications: Context-Aware Execution
If you want a single-turn agent (node or sub-agent) to have access to the
conversation history, you must explicitly set `include_contents="default"`.
### Context-Aware Sub-Agent Example
In this setup, the `verifier` sub-agent needs to see the history of the
conversation to verify the parent's draft against previous user constraints:
```python
verifier_agent = LlmAgent(
name="verifier",
instruction="Verify that the draft meets all constraints discussed in the chat.",
mode="single_turn",
include_contents="default" # Allows the sub-agent to see the parent's conversation history
)
editor_agent = LlmAgent(
name="editor",
instruction="Discuss the draft with the user and use verifier to check constraints.",
sub_agents=[verifier_agent]
)
```
--------------------------------------------------------------------------------
## Limitations
- **Difference from Standalone Behavior**: A standalone `LlmAgent` defaults to
`include_contents="default"`. When used in a workflow or as a sub-agent, it
defaults to `include_contents="none"`.
- **No Direct Transfer**: You cannot use `transfer_to_agent` to target a
`single_turn` agent. They must be invoked via tool calls.
## Related samples
- [Single-Turn Sub-Agent Sample](../../../../contributing/samples/multi_agent/single_turn_sub_agent/README.md) - A complete sample demonstrating how to define a single-turn sub-agent and use it as a tool.
+138
View File
@@ -0,0 +1,138 @@
# LlmAgent Task Mode
This guide explains the behavior of `LlmAgent` in `task` mode. It covers how
task agents are used for delegated, goal-oriented execution, how they signal
completion using the `finish_task` tool, and how they enforce structured inputs
and outputs.
--------------------------------------------------------------------------------
## Introduction
In ADK, `mode="task"` is designed for agents that are assigned a specific,
self-contained task. Unlike `chat` mode (which supports ongoing back-and-forth
conversation and peer transfers) or `single_turn` mode (which is stateless and
immediate), a `task` agent:
1. **Runs until completion**: It executes a thought loop, calling tools as
needed, until it decides the task is finished.
2. **Converses with the User**: It can interact with the user to ask questions
or seek clarification. The framework manages pausing and resuming the task
agent across turns.
3. **Signals completion**: It must explicitly call the built-in `finish_task`
tool to end its execution.
4. **Returns structured output**: It validates its final output against a
defined `output_schema` before returning it to the caller.
When used as a sub-agent, a task agent is exposed to its parent as a tool.
Calling this tool suspends the parent agent and runs the task agent to
completion.
--------------------------------------------------------------------------------
## 1. Task Mode as a Sub-Agent
The primary use case for task agents is delegation in a multi-agent hierarchy.
### Behavior
- **Exposed as a Tool**: Similar to `single_turn` agents, a `task` agent is
exposed to its parent as a tool, not a transfer target.
- **Deferred Response**: When the parent calls the task agent's tool, the
parent's execution is suspended. The framework runs the task agent in a
sub-branch.
- **Execution Loop**: The task agent runs its own loop, using its own tools,
until it calls `finish_task`.
- **Structured Return**: The output passed to `finish_task` is validated and
returned to the parent agent as the tool result.
### Example
Here is how to define a task agent with structured inputs and outputs and
delegate to it.
```python
from google.adk.agents import LlmAgent
from pydantic import BaseModel, Field
# 1. Define schemas for Input and Output
class ResearchInput(BaseModel):
topic: str = Field(description="The topic to research.")
depth: str = Field(default="brief", description="Depth of research: brief or detailed.")
class ResearchOutput(BaseModel):
summary: str = Field(description="A summary of the findings.")
sources: list[str] = Field(description="List of sources used.")
# 2. Define the Task Agent
researcher_agent = LlmAgent(
name="researcher",
instruction="Research the given topic and provide a structured summary.",
mode="task",
input_schema=ResearchInput,
output_schema=ResearchOutput,
# Add tools needed for the task
tools=[...]
)
# 3. Define the Parent Agent
writer_agent = LlmAgent(
name="writer",
instruction="Write a blog post. Use the researcher agent to get info on the topic.",
sub_agents=[researcher_agent] # Exposes 'researcher' agent to writer
)
```
### User Interaction & Resumption
A task agent is not limited to one-shot execution. If the task is unclear or
requires user input, the agent can converse with the user:
1. **Asking a question**: The task agent outputs text directed to the user
*instead* of calling `finish_task`.
2. **Pausing**: The framework detects that the agent has returned control
without finishing the task, pauses execution, and delivers the message to
the user.
3. **Resuming**: When the user replies, the framework automatically routes the
reply back to the task agent, resuming its execution loop.
4. **Completing**: The agent continues this interaction until it eventually
calls `finish_task` with the final result.
--------------------------------------------------------------------------------
## 2. The `finish_task` Tool
Every agent configured with `mode="task"` automatically receives the
`finish_task` tool.
### How it works
- **System Instruction**: The framework appends instructions to the agent's
prompt, telling it to use `finish_task` only when the task is fully
complete.
- **Validation**: When the agent calls `finish_task(output=...)`, the
framework validates the `output` against the agent's `output_schema`.
- **Retry on Failure**: If validation fails, the framework returns the
validation error to the agent, allowing it to correct its output and try
again.
- **Default Schema**: If no `output_schema` is specified, the agent defaults
to returning a simple string (`result`).
--------------------------------------------------------------------------------
## Task Mode in Workflows
Task mode is fully supported in workflows. You can use task-mode agents as static nodes in a workflow graph. The workflow runner will automatically manage the task lifecycle, including pausing for human input and resuming with the correct context.
## Limitations
- **No Direct Transfer**: You cannot transition to a task agent using
`transfer_to_agent`. They must be invoked as tools.
- **Must Call `finish_task`**: If a task agent fails to call `finish_task`
(e.g., due to a bug or limit reach), the task will not complete
successfully.
## Related samples
- [Task Sub-Agent Sample](../../../../contributing/samples/multi_agent/task_sub_agent/README.md) - A complete sample demonstrating how to define a task-mode sub-agent with custom input/output schemas and delegate tasks to it.
+156
View File
@@ -0,0 +1,156 @@
# ManagedAgent
## Introduction
`ManagedAgent` allows you to leverage managed agents backed by the Managed
Agents API (`interactions.create`) via either the
[Gemini Enterprise Agents Platform (GEAP, formerly Vertex)](https://docs.cloud.google.com/gemini-enterprise-agent-platform/build/managed-agents)
or the [Gemini API](https://ai.google.dev/gemini-api/docs/agents) from within
your ADK flows. It is particularly useful when you want to utilize Google's
powerful first-party, out-of-the-box agents (like the Antigravity agent) that
have specialized server-side execution environments built-in without requiring
client-side function declarations.
This solves the developer problem of needing a robust, server-hosted environment
for agents that require specialized built-in capabilities, rather than managing
sandbox environments and Python code execution locally. `ManagedAgent` can be
used as a standalone agent, integrated directly into a workflow, or encapsulated
as a tool via `AgentTool` so that a coordinating `LlmAgent` can delegate
specialized tasks to it.
## Prerequisites
The `ManagedAgent` supports two distinct backends: the Gemini API backend and
the Gemini Enterprise Agents Platform (GEAP) backend. Depending on which backend
you intend to use, you must satisfy the corresponding prerequisites for
authentication and obtaining an Agent ID.
### Option 1: Gemini API Backend
* **Authentication**: You must obtain a Gemini API key. Set this as the
`GEMINI_API_KEY` environment variable.
* **Agent ID**: You need an `agent_id` to connect to. You can either:
* Create a new agent by following the
[Gemini API Agents documentation](https://ai.google.dev/gemini-api/docs/agents).
* Use an out-of-the-box agent ID, such as `antigravity-preview-05-2026`,
which is commonly used in our examples.
### Option 2: Gemini Enterprise Agents Platform (GEAP) Backend
* **Authentication**: GEAP (formerly Vertex) requires Google Cloud
credentials. Follow the
[GEAP setup instructions](https://docs.cloud.google.com/gemini-enterprise-agent-platform/build/managed-agents/create-manage#before-you-begin)
to authenticate your local environment (e.g., using `gcloud auth
application-default login`).
* **Agent ID**: Similar to the Gemini API, you need an `agent_id`. You can
either:
* Create a new agent via the
[GEAP Managed Agents guide](https://docs.cloud.google.com/gemini-enterprise-agent-platform/build/managed-agents).
* Use an out-of-the-box agent ID if available to your project.
## Get started
Here is a minimal implementation of `ManagedAgent` demonstrating its use.
```python
import os
from google.adk.agents import ManagedAgent
from google.adk.tools import google_search
from google.genai import types
# Ensure you have the MANAGED_AGENT_ID and the proper environment config
_AGENT_ID = os.environ.get('MANAGED_AGENT_ID', 'antigravity-preview-05-2026')
managed_search_agent = ManagedAgent(
name='managed_search_agent',
description='Answers questions that need fresh, grounded information from the web.',
agent_id=_AGENT_ID,
environment={'type': 'remote'},
tools=[google_search],
)
# A managed code execution agent using raw types.Tool
managed_code_execution_agent = ManagedAgent(
name='managed_code_execution_agent',
description='Solves computational questions by running code server-side.',
agent_id=_AGENT_ID,
environment={'type': 'remote'},
tools=[types.Tool(code_execution=types.ToolCodeExecution())],
)
```
To see an orchestrator pattern using this code, you could wrap them using
`AgentTool`:
```python
from google.adk.agents import LlmAgent
from google.adk.tools.agent_tool import AgentTool
# The local coordinator delegates tasks to the server-backed agents
root_agent = LlmAgent(
name='managed_tool_coordinator',
description='Calls managed specialists as tools and composes the answer.',
tools=[
AgentTool(agent=managed_search_agent),
AgentTool(agent=managed_code_execution_agent),
],
)
```
## How it works
The `ManagedAgent` implements the `BaseAgent` contract but bypasses standard
`generate_content` calls, instead sending interactions via
`_create_interactions` with `background=True`. It natively streams partial
events and terminal events in real-time back to the ADK `Runner` or parent flow.
When using the GEAP backend, it enforces a connection to the `global` location
since the Managed Agents API is solely available globally. Because it runs
remotely, tools are translated into standard `ToolParam` formats for
interactions; any raw `google.genai.types.Tool` configs are passed through to
the backend, enabling server-side code execution or remote google search
seamlessly.
### State: local session vs. remote
`ManagedAgent` keeps almost no state locally. The ADK session only persists two
values on the events it emits: the `previous_interaction_id` and the sandbox
`environment_id`. On each new turn the agent recovers both by scanning prior
session events, then reuses them so the conversation and its sandbox continue.
Everything else lives server-side. The Managed Agents API owns the sandbox
environment and the full interaction history, and that remote interaction — not
the local session — is the source of truth for continuing a conversation.
Response text appears in both places (the local ADK events and the remote
interaction history), but ADK stores only the ids it needs to recover and reuse
the remote state; it never re-sends prior turns.
## Advanced applications
### Tool encapsulation for orchestration
* **Problem solved**: Sometimes a single LLM request needs to compose results
from multiple independent, robust specialists without losing control of the
execution turn.
* **Implementation**: Encapsulate each `ManagedAgent` instance within its own
separate `AgentTool` and provide them as a list of tools to an `LlmAgent`
coordinator. The coordinator will invoke the managed agents (which run their
sandboxed logic server-side), collect the results, and then compose the
final synthesized response natively.
## Limitations
* **Location pinned (GEAP only)**: For the GEAP backend, the Managed Agents
API is currently only served from the `global` location. Enterprise clients
using regional endpoints will raise an error.
* **Server-side tools only**: Client-executed tools (Python functions,
callables) and MCP tools are not supported. Providing these will raise a
`NotImplementedError`.
* **Streaming only**: The agent only supports streaming interactions.
Background-polling execution or strictly non-streaming connections are not
yet fully supported (it natively uses `stream=True` and yields events).
## Related samples
* [Managed Agent Basic](../../../../contributing/samples/managed_agent/basic)
* [Managed Agent Code Execution](../../../../contributing/samples/managed_agent/code_execution)