ADK has five built-in agent types. Most tutorials only show LlmAgent. Here is when each one is the right choice.
The Agent Type Confusion
Google ADK ships with five built-in agent types: LlmAgent, SequentialAgent, ParallelAgent, LoopAgent, and a generic BaseAgent for custom logic. Every tutorial starts with LlmAgent, which handles most single-agent use cases. But as soon as you need multi-step pipelines, parallel tasks, or iterative loops, you need one of the others -- and the docs are sparse on when to use which.
This article gives you the decision guide.
The Five Types at a Glance
| Agent type | What it does | Best for |
|---|---|---|
| LlmAgent | Calls an LLM, uses tools, reasons about the task | Most single-agent tasks; reasoning + tool use |
| SequentialAgent | Runs a list of sub-agents one after another, passing output forward | Linear pipelines: research -> write -> review |
| ParallelAgent | Runs multiple sub-agents simultaneously | Independent tasks that can run at the same time |
| LoopAgent | Runs a sub-agent in a loop until a condition is met | Iterative refinement, polling, retry patterns |
| BaseAgent | Custom orchestration logic in Python | Complex routing that none of the above handle |
LlmAgent: The Default
from google.adk.agents import LlmAgent
from google.adk.tools import google_search
# The standard single-agent setup
researcher = LlmAgent(
name="researcher",
model="gemini-2.0-flash",
description="Researches topics using web search",
instruction=(
"You are a research assistant. Use google_search to find accurate, "
"current information. Summarise your findings clearly with sources."
),
tools=[google_search],
)Use LlmAgent when: the task requires reasoning, tool selection, and dynamic decision-making. One LlmAgent with the right tools handles the majority of real-world tasks.
SequentialAgent: Linear Pipelines
SequentialAgent runs its sub-agents in order. Each agent's output is added to the session state and is available to subsequent agents. Use this for pipelines where order matters and each step depends on the previous one.
from google.adk.agents import SequentialAgent, LlmAgent
researcher = LlmAgent(
name="researcher",
model="gemini-2.0-flash",
instruction="Research the given topic. Output a structured summary with key facts.",
output_key="research_summary", # saves output to session state under this key
)
writer = LlmAgent(
name="writer",
model="gemini-2.0-flash",
instruction=(
"Write a 500-word blog post based on the research_summary in the session. "
"Use a clear structure: intro, 3 body sections, conclusion."
),
output_key="draft_post",
)
reviewer = LlmAgent(
name="reviewer",
model="gemini-2.0-flash",
instruction=(
"Review the draft_post in the session for accuracy, clarity, and tone. "
"Return either APPROVED or a list of specific changes needed."
),
output_key="review_result",
)
# Pipeline runs: researcher -> writer -> reviewer
content_pipeline = SequentialAgent(
name="content_pipeline",
sub_agents=[researcher, writer, reviewer],
)Use output_key on each sub-agent to save its output to named session state. Downstream agents reference these keys in their instructions. Without output_key, agents can still read previous outputs from the session history, but named keys make it explicit and reliable.ParallelAgent: Independent Tasks
ParallelAgent runs all its sub-agents at the same time. Use it when the tasks are independent of each other -- they do not need each other's output to run.
from google.adk.agents import ParallelAgent, LlmAgent
# These three tasks are independent -- run them at the same time
market_researcher = LlmAgent(
name="market_researcher",
model="gemini-2.0-flash",
instruction="Research current market trends for electric vehicles.",
output_key="market_trends",
)
competitor_analyst = LlmAgent(
name="competitor_analyst",
model="gemini-2.0-flash",
instruction="Research the top 5 EV competitors and their key differentiators.",
output_key="competitor_analysis",
)
regulatory_researcher = LlmAgent(
name="regulatory_researcher",
model="gemini-2.0-flash",
instruction="Research current and upcoming EV regulations in the US and EU.",
output_key="regulatory_landscape",
)
# All three run simultaneously -- total time = slowest agent, not sum of all
parallel_research = ParallelAgent(
name="parallel_research",
sub_agents=[market_researcher, competitor_analyst, regulatory_researcher],
)
# Follow with a SequentialAgent to synthesise the parallel results
synthesiser = LlmAgent(
name="synthesiser",
model="gemini-2.0-flash",
instruction=(
"Synthesise the market_trends, competitor_analysis, and regulatory_landscape "
"from the session into a unified strategic briefing."
),
)ParallelAgent agents cannot share state or depend on each other's outputs. If Agent B needs Agent A's output, use SequentialAgent. If they are truly independent, ParallelAgent is significantly faster.LoopAgent: Iterative Refinement
LoopAgent runs its sub-agent repeatedly until a condition is met. The most common use case: an agent refines its output iteratively until it meets a quality threshold.
from google.adk.agents import LoopAgent, LlmAgent
refiner = LlmAgent(
name="refiner",
model="gemini-2.0-flash",
instruction=(
"Review the current_draft in the session. "
"If it is high quality (clear, accurate, complete), output DONE. "
"Otherwise, improve it and output the improved version."
),
output_key="current_draft",
)
# Loop until the refiner outputs 'DONE' or max_iterations is reached
refinement_loop = LoopAgent(
name="refinement_loop",
sub_agents=[refiner],
max_iterations=5, # safety cap
# Stop condition: check if output contains 'DONE'
should_continue_condition=lambda ctx: "DONE" not in (
ctx.session.state.get("current_draft", "")
),
)Combining Types: Real-World Example
from google.adk.agents import SequentialAgent, ParallelAgent, LlmAgent
# Step 1: Parallel research on three dimensions
research = ParallelAgent(
name="research",
sub_agents=[market_researcher, competitor_analyst, regulatory_researcher],
)
# Step 2: Synthesise results (needs all three, so sequential after parallel)
synthesise = LlmAgent(
name="synthesise",
model="gemini-2.0-flash",
instruction="Synthesise all research from the session into a strategic briefing.",
output_key="briefing",
)
# Step 3: Write report from briefing
write = LlmAgent(
name="write",
model="gemini-2.0-flash",
instruction="Write a 10-page executive report based on the briefing.",
output_key="report",
)
# Full pipeline: parallel research -> sequential synthesis and writing
full_pipeline = SequentialAgent(
name="full_pipeline",
sub_agents=[research, synthesise, write],
)Quick Reference
- LlmAgent: reasoning + tool use, single or multi-turn -- the default choice
- SequentialAgent: ordered pipeline, each step sees previous outputs via output_key
- ParallelAgent: independent tasks running simultaneously -- total time = slowest, not sum
- LoopAgent: iterative refinement with a stop condition and safety max_iterations
- Use output_key on every sub-agent to make inter-agent data sharing explicit
- Combine types: ParallelAgent for research, SequentialAgent to process results