A2A — Agent-to-Agent Protocol
MCP connects an agent to tools. A2A (Agent2Agent) connects an agent to other agents, including ones built on different frameworks that you can't see inside. Google released it in April 2025 and donated it to the Linux Foundation that June. It absorbed IBM's ACP, added the AP2 payments extension, and reached v1.0 in April 2026 with 150+ supporters including AWS, Cisco, Microsoft, Salesforce, SAP, and ServiceNow. This lesson walks the Agent Card, the Task lifecycle, and the two transport bindings.
Learning Objectives
- Distinguish agent-to-tool (MCP) from agent-to-agent (A2A) use cases.
- Publish an Agent Card at `/.well-known/agent.json` with skills and endpoint metadata.
- Walk the Task lifecycle (submitted → working → input-required → completed / failed / canceled / rejected).
- Use Messages with Parts (text, file, data) and Artifacts as outputs.
The Problem
A customer-service agent needs to hand report-writing to a specialized writer agent. Before A2A you had three options:
- A custom REST API. It works, but every pairing is a one-off.
- A shared codebase. Both agents have to run the same framework.
- MCP. It doesn't fit, because MCP is for calling tools. It isn't built for two agents collaborating while each keeps its reasoning private.
A2A fills that gap. One agent sends a Task to another, and the interaction has a lifecycle, messages, and artifacts. The called agent's internal state stays opaque, so the caller sees only task state transitions and the eventual outputs.
A2A is the protocol for agents across frameworks to talk to each other. It doesn't replace MCP. The two sit side by side.
The Concept
Agent Card
Every A2A-compliant agent publishes a card at /.well-known/agent.json:
{
"schemaVersion": "1.0",
"name": "research-agent",
"description": "Summarizes academic papers and drafts citations.",
"url": "https://research.example.com/a2a",
"version": "1.2.0",
"skills": [
{
"id": "summarize_paper",
"name": "Summarize a paper",
"description": "Read a paper PDF and produce a 3-paragraph summary.",
"inputModes": ["text", "file"],
"outputModes": ["text", "artifact"]
}
],
"capabilities": {"streaming": true, "pushNotifications": true}
}Discovery is URL-based: fetch the card, learn the URL of the A2A endpoint, enumerate skills.
Signed Agent Cards (AP2)
The AP2 extension (September 2025) adds cryptographic signatures to Agent Cards. A publisher signs its own card with a JWT; consumers verify. This prevents impersonation.
Task lifecycle
submitted -> working -> completed | failed | canceled | rejected
-> input_required -> working (loop via message)
Clients initiate with tasks/send. The called agent transitions through states; clients subscribe to state updates via SSE or poll.
Messages and Parts
A message carries one or more Parts:
text: plain content.file: base64 blob with mimeType.data: typed JSON payload, used as structured input for the called agent.
Example:
{
"role": "user",
"parts": [
{"type": "text", "text": "Summarize this paper."},
{"type": "file", "file": {"name": "paper.pdf", "mimeType": "application/pdf", "bytes": "..."}},
{"type": "data", "data": {"targetLength": "3 paragraphs"}}
]
}Artifacts
Outputs are Artifacts, not raw strings. An Artifact is a named, typed output:
{
"name": "summary",
"parts": [{"type": "text", "text": "..."}],
"mimeType": "text/markdown"
}Artifacts can be streamed as chunks. The caller accumulates.
Two transport bindings
- JSON-RPC over HTTP.
/a2aendpoint, POST for requests, optional SSE for streaming. Default binding. - gRPC. For enterprise environments where gRPC is native.
Both bindings carry the same logical message shape.
Opacity preservation
A key design principle: the called agent's internal state is opaque. The caller sees task state and artifacts. The called agent's chain-of-thought, its tool calls, and its sub-agent delegation are all invisible. MCP is the opposite: tool calls there are transparent.
The reason is that competitors can collaborate without revealing internals. "Call this customer-service agent" works without the caller learning how that agent implements the service.
Timeline
- 2025-04-09. Google announces A2A.
- 2025-06-23. Donated to Linux Foundation.
- 2025-08. Absorbs IBM's ACP.
- 2025-09. AP2 extension (Agent Payments) ships.
- 2026-04. v1.0 released with 150+ supporting organizations.
Relationship to MCP
| Dimension | MCP | A2A |
|---|---|---|
| Use case | Agent-to-tool | Agent-to-agent |
| Opacity | Transparent tool calls | Opaque inner reasoning |
| Typical caller | Agent runtime | Another agent |
| State | Tool-call result | Task with lifecycle |
| Authorization | OAuth 2.1 (Phase 13 · 16) | JWT-signed Agent Cards (AP2) |
| Transport | Stdio / Streamable HTTP | JSON-RPC over HTTP / gRPC |
Use MCP when you want to invoke a specific tool. Use A2A when you want to delegate a whole task to another agent. Many production systems use both: an agent uses MCP for its tool layer and A2A for its collaboration layer.
Use It
code/main.py is a minimal A2A harness. A writer agent publishes its card, and a research agent fetches it and sends a task with a text part and a PDF file part. The writer pauses in input_required because the message has no data part with targetLength. The research agent replies with one, the task goes back to working, and it finishes with a text artifact. It's all stdlib and uses an in-process transport, so the focus stays on message shapes.
What to look at:
- The Agent Card JSON shape.
- Task id assignment and state transitions.
- Messages with mixed-type parts.
- The input-required branch mid-task.
- The artifact returned on completion.
Ship It
This lesson produces outputs/skill-a2a-agent-spec.md. Given a new agent that should be callable by other agents, the skill produces the Agent Card JSON, skills schema, and endpoint blueprint.
I'd run main.py first and read the output top to bottom. It prints the writer's card, sends a message with no data part, and shows the task stopping in input_required until the research agent follows up with targetLength. The final line counts the messages on the task, so you can see that the clarification lived in the same task instead of starting a new one.
The part I'd spend time on is how little the caller learns. It gets a state string and an artifact back, and nothing about how the writer produced the summary. That's the opacity argument from the body made concrete. The cost is that the research agent can't inspect or correct the writer's reasoning, only answer the question it's asked.
Keep the toy in proportion. The transport is a function call, the writer's finish just formats a string, and nothing is signed or streamed. The card declares streaming: True, but the code never uses it. The signing and SSE parts are the two exercises I'd do before trusting this shape in anything real.
Exercises
-
Run
code/main.py. Trace the full Task lifecycle, including the input-required pause where the called agent asks for a clarification. -
Add a signed Agent Card. Sign with HMAC over the card's canonical JSON. Write a verifier and confirm it fails on a mutated card.
-
Implement task streaming: the writer agent emits three incremental artifact chunks over SSE and the caller accumulates them.
-
Design an A2A agent that wraps an MCP server. Map each MCP tool to an A2A skill. Note the trade-offs. What opacity is lost?
-
Read the A2A v1.0 announcement and identify the one feature that is not yet implemented by any framework as of April 2026. (Hint: it relates to multi-hop task delegation.)
Key Terms
| Term | What people say | What it actually means |
|---|---|---|
| A2A | "Agent-to-Agent protocol" | Open protocol for opaque agent collaboration |
| Agent Card | ".well-known/agent.json" | Published metadata describing an agent's skills and endpoint |
| Skill | "A callable unit" | A named operation the agent supports (analog to MCP tool) |
| Task | "Unit of delegation" | A work item with a lifecycle and final artifact |
| Message | "Task input" | Carries Parts (text, file, data) |
| Part | "Typed chunk" | text / file / data element of a message |
| Artifact | "Task output" | Named, typed output returned on completion |
| AP2 | "Agent Payments Protocol" | Signed Agent Cards extension for trust and payments |
| Opacity | "Black-box collaboration" | Called agent's internals are hidden from caller |
| Input-required | "Task pause" | Lifecycle state when the agent needs more info |
Further Reading
- a2a-protocol.org: canonical A2A specification
- a2aproject/A2A: GitHub: reference implementations and SDKs
- Linux Foundation: A2A launch press release: June 2025 governance transfer
- Google Cloud: A2A protocol upgrade: roadmap and partner momentum
- Google Dev: A2A 1.0 milestone: v1.0 release notes and backward-compat guidance