Multi-Agent Orchestration¶
The ADK allows developers to build robust systems by delegating tasks to multiple specialized sub-agents rather than relying on a single monolith prompt. This hierarchical strategy prevents context dilution and improves accuracy.
1. The AgentTool Pattern (Delegation)¶
The simplest form of orchestration is turning an agent into a tool using AgentTool. When the root LLM identifies an intent matching the sub-agent's description, it calls the AgentTool, transferring execution context to the sub-agent.
using GoogleAdk.Core.Agents;
using GoogleAdk.Core.Tools;
var searchAgent = new LlmAgent(new LlmAgentConfig
{
Name = "researcher",
Instruction = "Research requested topics deeply."
});
var rootAgent = new LlmAgent(new LlmAgentConfig
{
Name = "coordinator",
Instruction = "Delegate research tasks to the 'researcher' tool.",
Tools = [new AgentTool(searchAgent)]
});
2. SequentialAgent (Pipelines)¶
A SequentialAgent executes a series of sub-agents in order. The output of the first agent is fed directly into the context of the second agent, forming a data pipeline.
Example: Research → Analyze → Write
var researchAgent = new LlmAgent(new LlmAgentConfig { Name = "researcher", Instruction = "..." });
var analystAgent = new LlmAgent(new LlmAgentConfig { Name = "analyst", Instruction = "..." });
var writerAgent = new LlmAgent(new LlmAgentConfig { Name = "writer", Instruction = "..." });
var pipeline = new SequentialAgent(new SequentialAgentConfig
{
Name = "research_pipeline",
Description = "A pipeline that researches, analyzes, and writes a report.",
SubAgents = [ researchAgent, analystAgent, writerAgent ]
});
// The pipeline executes the agents precisely in the order defined above.
3. ParallelAgent (Concurrency)¶
A ParallelAgent takes the current conversational context and broadcasts it to multiple sub-agents simultaneously. The runner waits until all branches complete their generation, then aggregates their independent conclusions.
This is exceptionally useful when you want multiple unique perspectives on identical data (e.g., an optimist, pessimist, and pragmatist).
var optimist = new LlmAgent(new LlmAgentConfig { Name = "optimist", Instruction = "..." });
var pessimist = new LlmAgent(new LlmAgentConfig { Name = "pessimist", Instruction = "..." });
var pragmatist = new LlmAgent(new LlmAgentConfig { Name = "pragmatist", Instruction = "..." });
var parallelAnalysis = new ParallelAgent(new ParallelAgentConfig
{
Name = "parallel_analysis",
Description = "Runs optimist, pessimist, and pragmatist analyses in parallel.",
SubAgents = [ optimist, pessimist, pragmatist ]
});
When you iterate over the events generated by parallelAnalysis, the evt.Author property will specify which of the sub-agents generated that specific output branch.
4. LoopAgent (Iterative Refinement)¶
A LoopAgent recursively runs its sub-agents until a specific completion criteria is met or a MaxIterations limit is hit.
A common use case is an Actor-Critic model: Agent A generates a draft, Agent B critiques the draft and returns feedback. Agent A generates a new draft based on the feedback. The loop terminates when Agent B explicitly triggers an "Escalate" action indicating approval.
using GoogleAdk.Core.Agents;
var drafter = new LlmAgent(new LlmAgentConfig { Name = "drafter", Instruction = "Write a draft based on feedback." });
var critic = new LlmAgent(new LlmAgentConfig
{
Name = "critic",
Instruction = "Score the draft. If it scores >= 8, call the escalate tool to end the loop.",
// The LoopTools.EscalateTool triggers the loop termination
Tools = [ GoogleAdk.Samples.LoopAgent.LoopTools.EscalateTool ]
});
var refinementLoop = new LoopAgent(new LoopAgentConfig
{
Name = "refinement_loop",
Description = "Iteratively refines content through drafting and critique.",
MaxIterations = 5, // Failsafe to prevent infinite loops
SubAgents = [ drafter, critic ]
});