Google ADKgoogle-adk 2.8 · Python 3.10+
Dashboard
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
28 small wins to finish your pathNext lesson →

ParallelAgent: two things at once

When two steps do not need each other's answers, running them one after the other only adds time.

python
account = LlmAgent(
    name="account",
    model=PretendModel(replies=[say("active")]),
    instruction="Report the account status.",
    output_key="account",
)

payments = LlmAgent(
    name="payments",
    model=PretendModel(replies=[say("two charges on 3 March")]),
    instruction="Report recent payments.",
    output_key="payments",
)

Two independent lookups. Neither reads the other's key, which is the condition for running them together.

python
checks = ParallelAgent(name="checks", sub_agents=[account, payments])
Example
session = await run(checks, "Look up this customer")
print("state:", dict(session.state))

Both ran and both left their result in state under their own key. Nothing was shared between them while they worked.

Separate branches, one state

Concurrent does not mean isolated. Each sub-agent runs on a branch of its own, so their events do not mix:

Example
runner = InMemoryRunner(agent=checks, app_name="demo")
session = await runner.session_service.create_session(app_name="demo", user_id="u1")
message = types.Content(role="user", parts=[types.Part(text="Look up this customer")])

async for event in runner.run_async(user_id="u1", session_id=session.id, new_message=message):
    print(f"{event.author:<9} branch {event.branch}")

The branch is the path of agent names, so nothing either agent says appears in the other's history. The session they write into is not branched, though: there is one session.state dictionary, and both of them write into it. That is what output_key puts a value in.

So two agents in the same parallel group must not share an output_key. Give them the same one and only one value survives:

Example
same_key = ParallelAgent(name="checks", sub_agents=[
    LlmAgent(name="account", model=PretendModel(replies=[say("active")]),
             instruction="Report the account status.", output_key="finding"),
    LlmAgent(name="payments", model=PretendModel(replies=[say("two charges on 3 March")]),
             instruction="Report recent payments.", output_key="finding"),
])

session = await run(same_key, "Look up this customer")
print("keys in state:", sorted(session.state))

One key, not two. Which of the two answers is in it depends on which agent finished last, so a program written this way gives a different result on a different day. The fix is the one above: a key per agent, and a step afterwards that reads both.

Running this prints a deprecation warning: as of ADK 2.x the three template workflow agents are deprecated in favour of a newer Workflow API. They still work, they are still what most existing code uses, and there is one thing only they can do. Lesson 20 covers the newer way and when each is right.

The rule for using it

Every agent in a parallel group must be able to do its job without the others' output. If one needs what another produces, they belong in a sequence.

Mixing the two is normal: a parallel group inside a sequence, so the slow independent work happens at once and a final step reads both results.

python
gather = ParallelAgent(name="gather", sub_agents=[account, payments])
summarise = LlmAgent(
    name="summarise",
    model="gemini-flash-latest",
    instruction="Summarise for an agent: account {account}, payments {payments}.",
)

desk = SequentialAgent(name="desk", sub_agents=[gather, summarise])

That shape is the common one in real projects: fan out for the lookups, then one agent to write the answer. It reads exactly as it runs.

Fan out for the lookups, then one agent writes
SequentialAgent · deskParallelAgent · gatherthenwriteswrites{account}, {payments}accountoutput_key=accountpaymentsoutput_key=paymentssummarisereads both keyssession.stateaccount, payments
Hover or tap a piece to see what it is and which lesson built it.
Trace a request

Pick one to watch it run, step by step.

One key each
The state is shared even though the branches are not, so two agents writing to the same key in parallel is a race, and the result depends on which finished last. Give every parallel agent its own key.
Try it yourself
  • Add a third agent to the group and print its branch.
  • Wrap the parallel group in a sequence with a summarising step.

Slow is fine. Stopping is the only problem.