Skip to content

Commit b1a0592

Browse files
committed
Update ADK doc for TransferToAgentTool and unique sub-agent names
1 parent ede481a commit b1a0592

File tree

2 files changed

+36
-13
lines changed

2 files changed

+36
-13
lines changed

docs/agents/multi-agents.md

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ The foundation for structuring multi-agent systems is the parent-child relations
2929

3030
* **Establishing Hierarchy:** You create a tree structure by passing a list of agent instances to the `sub_agents` argument when initializing a parent agent. ADK automatically sets the `parent_agent` attribute on each child agent during initialization.
3131
* **Single Parent Rule:** An agent instance can only be added as a sub-agent once. Attempting to assign a second parent will result in a `ValueError`.
32+
* **Unique Sub-Agent Names:** All sub-agents of a parent agent must have unique names. The framework validates this, and will raise a `ValueError` if duplicate names are detected among sub-agents.
3233
* **Importance:** This hierarchy defines the scope for [Workflow Agents](#workflow-agents-as-orchestrators) and influences the potential targets for LLM-Driven Delegation. You can navigate the hierarchy using `agent.parent_agent` or find descendants using `agent.find_agent(name)`.
3334

3435
=== "Python"
@@ -348,29 +349,37 @@ Leverages an [`LlmAgent`](llm-agents.md)'s understanding to dynamically route ta
348349

349350
* **Mechanism:** The agent's LLM generates a specific function call: `transfer_to_agent(agent_name='target_agent_name')`.
350351
* **Handling:** The `AutoFlow`, used by default when sub-agents are present or transfer isn't disallowed, intercepts this call. It identifies the target agent using `root_agent.find_agent()` and updates the `InvocationContext` to switch execution focus.
352+
* **Robustness with `TransferToAgentTool`**: To make this process more reliable, ADK provides the `TransferToAgentTool`. This tool wraps the standard `transfer_to_agent` function and adds enum constraints to the `agent_name` parameter. This prevents the LLM from hallucinating or calling non-existent agent names by restricting its choices to a predefined list of valid sub-agents, significantly reducing runtime errors.
351353
* **Requires:** The calling `LlmAgent` needs clear `instructions` on when to transfer, and potential target agents need distinct `description`s for the LLM to make informed decisions. Transfer scope (parent, sub-agent, siblings) can be configured on the `LlmAgent`.
352354
* **Nature:** Dynamic, flexible routing based on LLM interpretation.
353355

354356
=== "Python"
355357

356358
```python
357-
# Conceptual Setup: LLM Transfer
359+
# Conceptual Setup: LLM Transfer with TransferToAgentTool
358360
from google.adk.agents import LlmAgent
361+
from google.adk.tools import TransferToAgentTool
359362

360363
booking_agent = LlmAgent(name="Booker", description="Handles flight and hotel bookings.")
361364
info_agent = LlmAgent(name="Info", description="Provides general information and answers questions.")
362365

366+
# The TransferToAgentTool is initialized with the names of the valid sub-agents
367+
transfer_tool = TransferToAgentTool(
368+
agent_names=[booking_agent.name, info_agent.name]
369+
)
370+
363371
coordinator = LlmAgent(
364372
name="Coordinator",
365373
model="gemini-2.0-flash",
366374
instruction="You are an assistant. Delegate booking tasks to Booker and info requests to Info.",
367375
description="Main coordinator.",
368-
# AutoFlow is typically used implicitly here
376+
tools=[transfer_tool], # Include the transfer tool
369377
sub_agents=[booking_agent, info_agent]
370378
)
371379
# If coordinator receives "Book a flight", its LLM should generate:
372380
# FunctionCall(name='transfer_to_agent', args={'agent_name': 'Booker'})
373381
# ADK framework then routes execution to booking_agent.
382+
# The enum constraint in TransferToAgentTool ensures the LLM can only pick 'Booker' or 'Info'.
374383
```
375384

376385
=== "Java"
@@ -483,7 +492,7 @@ Allows an [`LlmAgent`](llm-agents.md) to treat another `BaseAgent` instance as a
483492

484493
Event responseEvent = Event.builder()
485494
.author(this.name())
486-
.content(Content.fromParts(Part.fromText("\b...")))
495+
.content(Content.fromParts(Part.fromText("...")))
487496
.build();
488497

489498
return Flowable.just(responseEvent);
@@ -557,16 +566,21 @@ By combining ADK's composition primitives, you can implement various established
557566
```python
558567
# Conceptual Code: Coordinator using LLM Transfer
559568
from google.adk.agents import LlmAgent
569+
from google.adk.tools import TransferToAgentTool
560570

561571
billing_agent = LlmAgent(name="Billing", description="Handles billing inquiries.")
562572
support_agent = LlmAgent(name="Support", description="Handles technical support requests.")
573+
574+
transfer_tool = TransferToAgentTool(
575+
agent_names=[billing_agent.name, support_agent.name]
576+
)
563577

564578
coordinator = LlmAgent(
565579
name="HelpDeskCoordinator",
566580
model="gemini-2.0-flash",
567581
instruction="Route user requests: Use Billing agent for payment issues, Support agent for technical problems.",
568582
description="Main help desk router.",
569-
# allow_transfer=True is often implicit with sub_agents in AutoFlow
583+
tools=[transfer_tool],
570584
sub_agents=[billing_agent, support_agent]
571585
)
572586
# User asks "My payment failed" -> Coordinator's LLM should call transfer_to_agent(agent_name='Billing')

docs/tutorials/agent-team.md

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,7 @@ A more robust approach is to build an **Agent Team**. This involves:
667667
1. Define simple tools for handling greetings (`say_hello`) and farewells (`say_goodbye`).
668668
2. Create two new specialized sub-agents: `greeting_agent` and `farewell_agent`.
669669
3. Update our main weather agent (`weather_agent_v2`) to act as the **root agent**.
670-
4. Configure the root agent with its sub-agents, enabling **automatic delegation**.
670+
4. Configure the root agent with its sub-agents, enabling **automatic delegation** using the `TransferToAgentTool`.
671671
5. Test the delegation flow by sending different types of requests to the root agent.
672672

673673
---
@@ -727,6 +727,7 @@ Now, create the `Agent` instances for our specialists. Notice their highly focus
727727

728728
```python
729729
# @title Define Greeting and Farewell Sub-Agents
730+
from google.adk.tools import TransferToAgentTool
730731

731732
# If you want to use models other than Gemini, Ensure LiteLlm is imported and API keys are set (from Step 0/2)
732733
# from google.adk.models.lite_llm import LiteLlm
@@ -778,12 +779,13 @@ except Exception as e:
778779

779780
Now, we upgrade our `weather_agent`. The key changes are:
780781

781-
* Adding the `sub_agents` parameter: We pass a list containing the `greeting_agent` and `farewell_agent` instances we just created.
782-
* Updating the `instruction`: We explicitly tell the root agent *about* its sub-agents and *when* it should delegate tasks to them.
782+
* Adding the `sub_agents` parameter: We pass a list containing the `greeting_agent` and `farewell_agent` instances we just created.
783+
* Using the `TransferToAgentTool`: We create an instance of `TransferToAgentTool` with the names of our sub-agents and add it to the root agent's tools.
784+
* Updating the `instruction`: We explicitly tell the root agent *about* its sub-agents and instruct it to use the `transfer_to_agent` tool for delegation.
783785

784-
**Key Concept: Automatic Delegation (Auto Flow)** By providing the `sub_agents` list, ADK enables automatic delegation. When the root agent receives a user query, its LLM considers not only its own instructions and tools but also the `description` of each sub-agent. If the LLM determines that a query aligns better with a sub-agent's described capability (e.g., "Handles simple greetings"), it will automatically generate a special internal action to *transfer control* to that sub-agent for that turn. The sub-agent then processes the query using its own model, instructions, and tools.
786+
**Key Concept: Delegation with `TransferToAgentTool`** By providing the `sub_agents` list and the `TransferToAgentTool`, we set up a robust delegation system. When the root agent receives a user query, its LLM considers its own instructions and tools, including the `transfer_to_agent` tool. The `TransferToAgentTool` constrains the `agent_name` parameter to only the names of the sub-agents, preventing the LLM from hallucinating non-existent agents. If the LLM determines a query matches a sub-agent's `description`, it will call the `transfer_to_agent` tool with the correct agent name, and ADK will transfer control to that sub-agent.
785787

786-
**Best Practice:** Ensure the root agent's instructions clearly guide its delegation decisions. Mention the sub-agents by name and describe the conditions under which delegation should occur.
788+
**Best Practice:** Ensure the root agent's instructions clearly guide its delegation decisions. Mention the sub-agents by name and describe the conditions under which the `transfer_to_agent` tool should be used.
787789

788790

789791
```python
@@ -797,6 +799,11 @@ runner_root = None # Initialize runner
797799
if greeting_agent and farewell_agent and 'get_weather' in globals():
798800
# Let's use a capable Gemini model for the root agent to handle orchestration
799801
root_agent_model = MODEL_GEMINI_2_0_FLASH
802+
803+
# Create the TransferToAgentTool with the names of the sub-agents
804+
transfer_tool = TransferToAgentTool(
805+
agent_names=[greeting_agent.name, farewell_agent.name]
806+
)
800807

801808
weather_agent_team = Agent(
802809
name="weather_agent_v2", # Give it a new version name
@@ -808,9 +815,10 @@ if greeting_agent and farewell_agent and 'get_weather' in globals():
808815
"1. 'greeting_agent': Handles simple greetings like 'Hi', 'Hello'. Delegate to it for these. "
809816
"2. 'farewell_agent': Handles simple farewells like 'Bye', 'See you'. Delegate to it for these. "
810817
"Analyze the user's query. If it's a greeting, delegate to 'greeting_agent'. If it's a farewell, delegate to 'farewell_agent'. "
818+
"Use the 'transfer_to_agent' tool to delegate. "
811819
"If it's a weather request, handle it yourself using 'get_weather'. "
812820
"For anything else, respond appropriately or state you cannot handle it.",
813-
tools=[get_weather], # Root agent still needs the weather tool for its core task
821+
tools=[get_weather, transfer_tool], # Root agent has weather tool and transfer tool
814822
# Key change: Link the sub-agents here!
815823
sub_agents=[greeting_agent, farewell_agent]
816824
)
@@ -829,7 +837,7 @@ else:
829837

830838
**4\. Interact with the Agent Team**
831839

832-
Now that we've defined our root agent (`weather_agent_team` - *Note: Ensure this variable name matches the one defined in the previous code block, likely `# @title Define the Root Agent with Sub-Agents`, which might have named it `root_agent`*) with its specialized sub-agents, let's test the delegation mechanism.
840+
Now that we've defined our root agent (`weather_agent_team`) with its specialized sub-agents, let's test the delegation mechanism.
833841

834842
The following code block will:
835843

@@ -842,10 +850,11 @@ The following code block will:
842850
We expect the following flow:
843851

844852
1. The "Hello there!" query goes to `runner_agent_team`.
845-
2. The root agent (`weather_agent_team`) receives it and, based on its instructions and the `greeting_agent`'s description, delegates the task.
853+
2. The root agent (`weather_agent_team`) receives it and, based on its instructions, uses the `transfer_to_agent` tool to delegate the task to the `greeting_agent`.
846854
3. `greeting_agent` handles the query, calls its `say_hello` tool, and generates the response.
847855
4. The "What is the weather in New York?" query is *not* delegated and is handled directly by the root agent using its `get_weather` tool.
848-
5. The "Thanks, bye!" query is delegated to the `farewell_agent`, which uses its `say_goodbye` tool.
856+
5. The "Thanks, bye!" query is delegated to the `farewell_agent` using the `transfer_to_agent` tool, which then uses its `say_goodbye` tool.
857+
849858

850859

851860

0 commit comments

Comments
 (0)