Skip to content

A2A Protocol in Google ADK: real implementation in an IDP

A2A Protocol defines how agents communicate. The protocol itself is an open Linux Foundation standard — framework and model agnostic. But there are different ways to implement it depending on the use case.

This system (IDP)Agent Skills
CommunicationFile system artifactsHTTP via RemoteA2aAgent
DiscoveryN/A — fixed sequenceagent.json (AgentCard)
CoordinationSequentialAgent (deterministic)Orchestrator with RemoteA2aAgent
CouplingLow — each agent finds what it needsLow — each agent is an HTTP server
Ideal forSequential pipelines with disk outputsDistributed systems with dynamic discovery

In this system, agents don’t call each other — they communicate through files they write and read in a shared directory.

Agent 1 (Platform Architect)
└── writes → platform-config.yaml
Agent 2 (Infrastructure)
│ finds and reads → platform-config.yaml
└── writes → docker-compose/app-stack.yml
Agent 3 (Security)
│ finds and reads → docker-compose/app-stack.yml
└── writes → security-report.json
[... and so on]

Nobody passes data to anyone. Each agent is responsible for finding what it needs.

Each agent has two types of Python tools — one to write its output, another to read the previous agent’s output:

# Write tool — the agent leaves its artifact
def save_platform_config(stack_summary: str) -> dict:
"""
Saves architecture decisions as a shared artifact.
Args:
stack_summary: "Runtime: Python 3.11 | Framework: FastAPI | DB: PostgreSQL..."
"""
# parses the string and writes platform-config.yaml
return {"status": "success", "path": "platform-config.yaml"}
# Read tool — the next agent finds the previous artifact
def get_platform_config() -> dict:
"""Reads platform-config.yaml from the previous agent."""
# reads and parses platform-config.yaml
return {"runtime": "python", "framework": "fastapi", "database": "postgresql"}

What happens when the artifact doesn’t exist

Section titled “What happens when the artifact doesn’t exist”

When an agent tries to read an artifact that hasn’t been generated yet — for example, if you call the Security Agent before the Infrastructure Agent — the agent recognizes the situation and stops its own execution:

Security Agent:
"I have tried to read the infrastructure agent's decisions,
but the file docker-compose/app-stack.yml was not found.
The Infrastructure agent must run first so that
I can analyze the generated infrastructure.
I cannot proceed without that context."

This is A2A in action: the agent knows the system state through available artifacts, not through information someone passed to it. No fictional data, no improvisation.

Each agent writes a structured execution report. The Orchestrator aggregates them in orchestration-report.json:

{
"agent_id": "infrastructure-agent",
"timestamp": "2026-01-29T10:30:15Z",
"status": "success",
"result": {
"files_generated": [
"docker-compose/app-stack.yml"
],
"decisions": {
"database": "PostgreSQL 15 — robust and compatible with FastAPI",
"cache": "Redis Alpine — minimal image for local scope"
}
}
}

In the Agent Skills repo, agents run as separate HTTP servers and discover each other dynamically via agent.json. Here we use disk artifacts because:

  • It’s a sequential pipeline — order is fixed, no dynamic discovery needed
  • Outputs are files — Docker Compose, YAML, JSON, Bash scripts. It makes sense for communication to also be through files
  • Simpler debugging — you can inspect the system state at any point by reading the generated files
  • No network infrastructure — no HTTP servers needed for local communication
  • Localized debugging — if the CI/CD Agent fails, the Architect, Infrastructure and Security artifacts are already on disk. You restart just that agent.
  • Real independence — you can run the Security Agent in isolation against any docker-compose.yml, not just the one generated by this system.
  • Complete traceability — every decision of every agent is recorded in a human-readable file.
  • No temporal coupling — agents don’t need to be running at the same time. You write the artifact, the next one reads it when its turn comes.