Why architecture matters here
Single-agent degradation is measurable and sharp. Instruction-following accuracy falls as instructions grow; tool-selection accuracy falls as the tool list grows; and every turn re-sends the whole overgrown context, so cost rises even as quality drops. Decomposition attacks all three at once: a billing agent with six tools and a one-paragraph charter selects tools near-perfectly and can be tested like a unit. The architecture question is never whether to decompose but where the seams go and who decides the routing.
ADK's core insight is that routing decisions have two fundamentally different kinds. Some are judgment calls — 'is this message about a refund, a shipping problem, or a scam attempt?' — where you want an LLM deciding, and the transfer mechanism exists for exactly that. Most are not judgment calls — 'after research, write; after writing, review; do these three lookups simultaneously; retry until the validator passes' — and burning model calls to rediscover a fixed pipeline on every request is pure waste: slower, costlier, and nondeterministic where determinism was free. Workflow agents encode those decisions structurally. Teams that put judgment in LLM transfer and structure in workflow agents get systems that are debuggable (the pipeline is code) exactly where they can be, and flexible exactly where they must be.
The second architectural axis is control flow vs data flow. Transfer moves control: the specialist now owns the conversation. AgentTool moves data: the parent delegates a subtask and keeps the conversation. Confusing them produces the two classic bugs — the summarizer that 'captures' a conversation it should have returned from, and the triage agent that laboriously relays a specialist's every answer because it never actually handed over. Getting these two axes right is 80% of multi-agent design; everything else is plumbing.
The architecture: every piece explained
Top row: control flow. The root agent is the entry point and usually a router: short instruction, descriptions of each sub-agent (the model routes on those descriptions — write them like API docs), and little else. LLM transfer is enabled by declaring sub_agents; the framework injects a transfer function, and when the model calls it, the Runner re-roots the conversation at the target agent — subsequent turns go straight to the specialist until it transfers back or up. SequentialAgent runs children in declared order, each seeing the session as left by its predecessor — the pipeline primitive. ParallelAgent runs children concurrently in separate invocation branches; LoopAgent repeats its children until a max iteration count or until one escalates — the retry/refine primitive.
Middle row: data flow. Specialist agents hold the narrow charters and small toolsets. AgentTool wraps any agent as a function tool: the parent's model emits a function call, the wrapped agent runs to completion in a nested invocation, and its final answer returns as the function result — control never leaves the parent. Shared state is the bus: an agent configured with output_key='research_notes' has its final text written into session state under that key; a downstream agent's instruction templates it in with {research_notes}. These key contracts are the interfaces of your system — name them, document them, and treat changing one like changing a function signature.
Bottom rows: the boundaries. Escalation — an event action a child can set — terminates the enclosing loop or bubbles control upward; it is also the idiom for human handoff ('confidence below threshold → escalate with a summary in state'). A2A exposure turns any agent in the tree into a remote service speaking the Agent2Agent protocol, so another team's orchestrator can delegate to your billing specialist without importing your code — the same composition logic, stretched across organizational boundaries. The ops strip is where multi-agent systems live or die: trajectory evals that assert the route taken, routing-accuracy dashboards, and cost-per-completed-task tracking, because a wrong architecture shows up first as a cost curve.
End-to-end flow
Anatomy of a content-research system that uses every primitive honestly. The root is a SequentialAgent pipeline: plan → gather → synthesize → review-loop → publish-gate. A user asks for a competitive analysis of three products.
Plan: an LlmAgent decomposes the request into research questions, writing them to state as research_plan. Gather is a ParallelAgent with three children — one per product — each an LlmAgent with search and scraping tools, each writing to its own namespaced key (findings_a, findings_b, findings_c; parallel children never share output keys — that is the race-condition rule). Wall-clock for the gather phase is the slowest child, not the sum. Synthesize reads all three via instruction templating and drafts the analysis to draft.
Review-loop is a LoopAgent (max 3 iterations) containing a critic and a reviser. The critic scores the draft against a rubric; if it passes, the critic sets the escalate action — terminating the loop early — otherwise its critique lands in critique and the reviser rewrites draft. This is deterministic iteration around stochastic content: the loop structure guarantees termination; the models supply the judgment.
Publish-gate is the judgment boundary done with transfer: a compliance agent reviews the final draft; its instruction says to transfer to the human_handoff agent when claims lack sources — a real routing decision that depends on content. In the happy path it approves and the pipeline returns the analysis.
Two composition details make this production-grade rather than demo-grade. First, the critic is also wrapped as an AgentTool and used by a completely different customer-support tree — same agent, two composition modes, no code duplication. Second, the whole research pipeline is exposed via A2A, so the marketing department's own orchestrator calls it as a remote capability with a task envelope, and your team versions the pipeline behind that contract. Every event along the way — transfers, parallel branches, loop iterations, state deltas — is in the session log, which is what makes the trajectory testable: the eval suite asserts 'gather ran three branches in parallel, the loop exited by escalation within two iterations, and no draft reached publish without a passing critique'.