The Goal

You will end up with three independently deployed services, each one a Cloud Run URL you can hit on its own:

  • Researcher — a specialist that searches the web via Gemini's built-in google_search tool and returns raw findings.
  • Writer — a specialist that takes a pile of raw research and shapes it into a clean executive brief.
  • Orchestrator — the front door. It accepts the user's question, calls the Researcher first, hands the result to the Writer, and returns the final brief.

You will send a single request to the orchestrator like:

"Brief me on the state of agentic web browsing in 2026."

…and behind the scenes three Cloud Run services will talk to each other over A2A to produce the answer.

Why A2A vs Just Sub-Agents

ADK supports in-process sub-agents — a single Python program with multiple Agent objects calling each other in memory. That works great when the agents share a codebase and a deployment.

A2A is what you reach for when those three things stop being true:

  • Each agent has its own deploy cadence (the Writer ships hourly, the Researcher ships weekly)
  • Each agent has its own scale profile (Researcher fans out wide, Writer is light)
  • Different teams own each agent, possibly in different languages (ADK now ships in Python, Go, Java, and TypeScript)

A2A is the wire format. It says: "given any agent that publishes an Agent Card at a public URL, any other A2A-aware agent can call it." It is the HTTP between agents.

The protocol is now governed by the Linux Foundation, with v1.0 released in early 2026. Signed Agent Cards, multi-tenancy, and JSON-RPC + gRPC bindings shipped in that release.

Architecture

Three separate services. One protocol. Each one minds its own business.

The Agent Card

Every A2A agent publishes an Agent Card at https://<host>/.well-known/agent-card.json. It is a tiny JSON document that says:

  • What the agent is called
  • What it can do (a description, optionally a list of skills)
  • Where to send messages
  • Which auth schemes it accepts

When the Orchestrator wants to call the Researcher, it fetches that URL once, caches the card, and routes messages accordingly. The card is the discovery layer; the rest of A2A is the message envelope.

In v1.0 the card can be signed with the domain owner's key. The receiving agent verifies the signature before trusting the card. That is the difference between "I think this is the Researcher" and "I know this card was issued by the domain that runs the Researcher."

Why This Stack

ChoiceWhy
Google ADK 1.0GA across Python/Go/Java/TypeScript. First-class A2A support via to_a2a() and RemoteA2aAgent.
A2A v1.0Open standard, Linux Foundation. Signed cards + multi-tenancy means it is safe in production.
Gemini Flash LatestFast, affordable, and the default for ADK agents. Built-in google_search tool.
Cloud RunEach agent gets its own service, its own URL, its own scale. One deploy command per agent.
uvFast Python package manager. Drop-in for pip + venv.

Project Structure

We will end up with one repo containing three agent packages — but each one is deployed independently:

agent-team/
├── researcher/
│   ├── __init__.py
│   └── agent.py           # Web search specialist
├── writer/
│   ├── __init__.py
│   └── agent.py           # Brief formatter
├── orchestrator/
│   ├── __init__.py
│   └── agent.py           # Root agent, talks to the other two over A2A
├── .env                   # Local Gemini API key
└── pyproject.toml         # uv-managed dependencies

You can split this into three repos when teams diverge. For now, one repo keeps the wiring obvious.


Reference: A2A Protocol v1.0 spec · ADK A2A docs · Google ADK 1.0 announcement