Building a Multi-Agent System with Google ADK
Move from single-prompt chatbots to a team of collaborating agents. Use Google ADK hierarchy, workflow agents, and session state to orchestrate a research-and-write pipeline.
Published on • August 8, 2026
AI Assistant

One complex prompt asks one model to do everything at once. A multi-agent system divides the job between several specialized agents, each doing what it is good at while sharing state through a pipeline. Google’s Agent Development Kit (ADK) makes this composition explicit — and dramatically easier to debug — than a single mega-prompt.
The problem multi-agent design solves
Single-prompt agents fail at compound tasks. Ask one agent to “research a topic, write a pitch, sanity-check it, and save it” and it will do a one-pass job: no verification, no revision, and no clean hand-off between stages. The same task split across a researcher, a writer, and a critic produces verifiably better output because each agent has a narrow job and a validation step in the loop.
ADK building blocks
ADK (Python 3.10+) organizes agents into a tree:
Agent(LlmAgent) — the reasoning primitive: a system prompt, tools, a model. It decides what to call and what to return.SequentialAgent— runs sub-agents one after another, each writing to the shared state.LoopAgent— repeats a sequence (withmax_iterations) until a condition or anexit_looptool call stops it.ParallelAgent— runs independent sub-agents concurrently, each writing to a uniqueoutput_key.
All agents share a Session with a session.state dictionary — the “whiteboard” that carries results between agents via output_key and key templating like {outline?}.
Prerequisites
- Python 3.10+,
pip install google-adk - A Gemini API key (
GOOGLE_API_KEY) from Google AI Studio — no billing account needed - A directory structure ADK expects: each agent project has an
__init__.pyexposing aroot_agent
Build a research → write → critique team
Put this in team_agent/agent.py:
from google.adk.agents import Agent, LoopAgent, SequentialAgent
MODEL = "gemini-2.5-flash"
researcher = Agent(
name="researcher",
model=MODEL,
description="Gathers verified facts about a topic.",
instruction=(
"Research the topic from the user. "
"Return a compact list of verifiable facts and save them "
"to state key 'facts'."
),
output_key="facts",
)
writer = Agent(
name="writer",
model=MODEL,
description="Writes a short technical post from the facts.",
instruction=(
"Write a 300-word technical post using {facts}. "
"Save the draft to 'draft'."
),
output_key="draft",
)
critic = Agent(
name="critic",
model=MODEL,
description="Reviews the draft and decides if it is ready.",
instruction=(
"Review {draft}. If it is accurate, well-structured, and "
"concise, reply exactly 'ok'. Otherwise reply 'revise' "
"plus one concrete improvement required."
),
)
writer_room = LoopAgent(
name="writer_room",
description="Loop writer + critic until the critic says ok.",
sub_agents=[writer, critic],
max_iterations=3,
)
pipeline = SequentialAgent(
name="pipeline",
sub_agents=[researcher, writer_room],
)
root_agent = Agent(
name="team",
model=MODEL,
description="Coordinator that delegates to the pipeline.",
sub_agents=[pipeline],
)
Key mechanics:
output_key="facts"automatically stores the agent’s response intostate["facts"]so the writer can reference{facts}.- The
criticgating the loop means bad drafts loop internally up to 3 times before the pipeline proceeds — a self-correcting writer’s room. - The root agent delegates; it doesn’t do the reasoning itself.
Run and inspect
From the package root (the directory containing team_agent/):
adk web # open http://127.0.0.1:8000, pick the agent
# or
adk run team_agent
adk web shows real-time traces: which agent is active, what each sub-agent wrote to state, and which tools fired. This is why ADK beats a single prompt for debugging — step-by-step visibility instead of a black box.
Fan out with ParallelAgent
Independent research jobs run concurrently with a ParallelAgent, each writing a unique key:
box_office = Agent(name="box_office", ... output_key="box_office_report")
casting = Agent(name="casting", ... output_key="casting_report")
preproduction = ParallelAgent(
name="preproduction",
sub_agents=[box_office, casting],
)
Unique output_keys avoid the race condition where the last-finishing agent overwrites everyone else’s result.
Conclusion & Next Steps
You turned a monolithic prompt into a team with an explicit hierarchy, shared state, and an iterative quality gate. Next: add a real tool (a requests-based fetch) to the researcher, wire session state from a previous turn into the loop, and deploy the same agent to Vertex AI Agent Engine with a single CLI command when you need managed scaling.
References / Sources
- Google ADK on GitHub. https://github.com/google/adk-python
- Build Multi-Agent Systems with ADK (Google Codelab). https://codelabs.developers.google.com/codelabs/production-ready-ai-with-gc/3-developing-agents/build-a-multi-agent-system-with-adk
- ADK docs and agent team tutorial. https://google.github.io/adk-docs/