What This Agent Does
The Orchestrator is the front door. It accepts a user's request, decides which specialists to involve, calls them over A2A, and stitches the result back to the user.
The trick: the Orchestrator does not have hardcoded routing logic. Gemini decides whether to call the Researcher, the Writer, both, or neither — based on the user's request and the descriptions on each specialist's Agent Card.
How RemoteA2aAgent Works
ADK ships RemoteA2aAgent — a client-side proxy that looks and feels like a regular sub-agent, but every call goes over HTTP to a remote A2A endpoint.
You give it the URL of the remote Agent Card, and it does the rest:
- Fetches and caches the card on startup
- Routes messages to the right method and endpoint
- Streams responses back into the parent's context
From the orchestrator's point of view, calling a remote A2A specialist is identical to calling a local sub-agent.
Write the Orchestrator
Open orchestrator/agent.py:
# orchestrator/agent.py
# ==========================================
# Root agent — delegates to Researcher and Writer over A2A
# ==========================================
import os
from google.adk import Agent
from google.adk.agents.remote_a2a_agent import (
RemoteA2aAgent,
AGENT_CARD_WELL_KNOWN_PATH,
)
# Where to find the specialists. Local dev defaults; in production each
# of these points at a Cloud Run URL (set as env vars in Step 6).
RESEARCHER_URL = os.getenv("RESEARCHER_URL", "http://localhost:8001")
WRITER_URL = os.getenv("WRITER_URL", "http://localhost:8002")
researcher = RemoteA2aAgent(
name="researcher",
description="Searches the web and returns raw research findings on a topic.",
agent_card=f"{RESEARCHER_URL}{AGENT_CARD_WELL_KNOWN_PATH}",
)
writer = RemoteA2aAgent(
name="writer",
description="Turns raw research findings into a concise, cited executive brief.",
agent_card=f"{WRITER_URL}{AGENT_CARD_WELL_KNOWN_PATH}",
)
INSTRUCTION = """You coordinate a research team.
When a user asks for a brief on a topic:
1. Send the topic to the `researcher` sub-agent. It returns raw findings.
2. Send those findings to the `writer` sub-agent. It returns a polished brief.
3. Return the polished brief to the user.
Do not write your own briefs. Do not skip the researcher. Always call both
agents in order: researcher first, then writer.
If the user is just chatting and not asking for a brief, respond normally
without calling either sub-agent.
"""
root_agent = Agent(
model="gemini-flash-latest",
name="orchestrator",
description="Coordinates a researcher and writer to produce briefs on any topic.",
instruction=INSTRUCTION,
sub_agents=[researcher, writer],
)A few things worth pointing at:
AGENT_CARD_WELL_KNOWN_PATHis the constant for/.well-known/agent-card.json. Always concatenate it onto the host URL — never hand-write the path.- The remote agents land in
sub_agents=[…], exactly the same slot you would use for local sub-agents. - The instruction explicitly forbids the orchestrator from doing the work itself. Without that, Gemini will sometimes try to answer directly and skip the specialists.
Run the Whole Stack Locally
You should now have three terminals open. If not:
# Terminal 1: Researcher
uv run uvicorn researcher.agent:a2a_app --host localhost --port 8001
# Terminal 2: Writer
uv run uvicorn writer.agent:a2a_app --host localhost --port 8002
# Terminal 3: Orchestrator with the ADK web UI
uv run adk webadk web starts the ADK developer UI on http://localhost:8000. It auto-discovers any agent package in the current directory, so you should see orchestrator in the dropdown.
Try It
Open the ADK web UI in your browser. Pick orchestrator from the agent dropdown. Send:
Brief me on the state of agentic web browsing in 2026.
What you should see in the trace panel:
- Orchestrator receives the message.
- It calls the
researchersub-agent (HTTP POST tolocalhost:8001). - The Researcher's terminal shows incoming A2A requests and
google_searchtool calls. - The findings come back.
- Orchestrator calls the
writersub-agent with the findings (HTTP POST tolocalhost:8002). - The Writer's terminal shows the incoming request, no tool calls.
- The polished brief comes back.
- Orchestrator returns it to you.
If steps 2 and 5 are missing — the orchestrator answered on its own — sharpen the instruction. Tell it explicitly: "You must always call the researcher first, then the writer. You do not have web access or writing skills of your own."
Sanity-Check the A2A Traffic
Add --verbose to the uvicorn commands and you will see each request in the specialist's logs:
INFO: localhost:54321 - "POST / HTTP/1.1" 200 OKEach one of those POSTs is an inter-agent A2A message. If you want to inspect the body, swap in uvicorn --log-level debug for the noisy version.
Key Takeaways
RemoteA2aAgentis a drop-in replacement for a local sub-agent — samesub_agents=[…]slot.AGENT_CARD_WELL_KNOWN_PATHis the constant; never hand-write the well-known URL.- Gemini does the routing; your job is to describe each specialist clearly so it picks the right one.
- The Orchestrator's instruction should explicitly forbid it from doing the specialists' work — otherwise it cheats.
Reference: ADK A2A Quickstart: Consuming · RemoteA2aAgent API reference