flowchart TD
O["Orchestrator Agent"]
L["Logistics Agent"]
B["Billing Agent"]
S["Shipping API, DB"]
P["Ledger, Payments API"]
O -->|"A2A (horizontal)"| L
O -->|"A2A (horizontal)"| B
L -->|"MCP (vertical)"| S
B -->|"MCP (vertical)"| P
230 The Agent2Agent (A2A) Protocol: Cross-Vendor Agent Interoperability
230.1 1. Introduction and Motivation
The Model Context Protocol, treated in the previous chapter, solved one half of the agent integration problem: how a single agent reaches the tools, data, and resources it needs to act. It says nothing, however, about how one agent collaborates with another. As organizations moved from single assistants to fleets of specialized agents in 2025, a billing agent, a logistics agent, a customer-history agent, each built by a different team on a different framework, often hosted by a different vendor, a second integration problem emerged with the same combinatorial shape as the one MCP addressed for tools.
Consider an enterprise running \(N\) agents that must cooperate. Without a shared standard, every pair that needs to collaborate requires a bespoke integration: a custom API contract, a custom authentication handshake, a custom message format. If every agent may in principle talk to every other, the number of distinct pairwise integrations is the number of unordered pairs,
\[ \binom{N}{2} = \frac{N(N-1)}{2} = \Theta(N^2), \]
so the integration burden grows quadratically in the fleet size. Adding the \((N{+}1)\)-th agent forces up to \(N\) new one-off connectors, each of which must be built, secured, tested, and maintained. A shared protocol collapses this to a hub-and-spoke shape: each agent implements the standard exactly once, against the protocol rather than against its peers, so onboarding the \((N{+}1)\)-th agent is \(O(1)\) work and the total integration surface is \(\Theta(N)\). This is the same combinatorial argument that justifies any interoperability standard, from USB to HTTP, and it is precisely the argument the Model Context Protocol made for the agent-to-tool axis.
Worse than the count, each bespoke integration leaks implementation details across organizational and trust boundaries that should remain opaque. A logistics agent should be able to ask a customer-history agent “is this customer eligible for expedited shipping?” without either side exposing its prompts, its model, its private tools, or its internal reasoning.
The Agent2Agent (A2A) Protocol is an open standard for exactly this: discovery, capability advertisement, task delegation, and result streaming between autonomous agents, across vendor and framework boundaries. Google Cloud announced A2A on April 9, 2025, with more than fifty launch partners, and donated it to the Linux Foundation on June 23, 2025, where it became the vendor-neutral, community-governed Agent2Agent Protocol Project. By its one-year mark the protocol counted over 150 supporting organizations and had reached enterprise production use across the major cloud platforms.
This chapter develops A2A from its design principles through its wire protocol to a working implementation. The exposition assumes familiarity with HTTP, JSON-RPC (covered in the MCP chapter), and distributed-systems concepts such as asynchronous task execution and webhooks.
230.2 2. Positioning: A2A Complements MCP
The single most important conceptual point, repeated verbatim in Google’s launch material and worth internalizing before any technical detail, is that A2A complements MCP rather than competing with it. The community shorthand is “A2A ❤️ MCP.” The two protocols address orthogonal axes of the agentic architecture:
- MCP is vertical: agent ↔︎ tools and data. It standardizes how a single agent plugs into external capabilities, databases, APIs, file systems, code execution. It is the agent’s connection downward to the resources it uses.
- A2A is horizontal: agent ↔︎ agent. It standardizes how peer agents discover one another, delegate work, and coordinate. It is the agent’s connection sideways to collaborators.
The two compose naturally: an orchestrator uses A2A to delegate a subtask to a specialist agent, and that specialist internally uses MCP to reach its own private tools. Neither side of an A2A conversation can see the other’s MCP servers. This layering, A2A above, MCP below, is the foundation of the broader “agent stack” examined in the interoperability-landscape chapter.
230.3 3. Design Principles
A2A’s specification rests on five stated design principles. They are not marketing slogans; each one drives concrete protocol decisions, and understanding them makes the rest of the protocol predictable.
- Embrace agentic capabilities. A2A lets agents collaborate in their natural, unstructured modalities even when they share no memory, tools, or context. It deliberately does not model a remote agent as a “tool” to be called, agents are autonomous peers, not functions.
- Build on existing standards. The protocol uses HTTP, JSON-RPC 2.0, and Server-Sent Events rather than inventing new primitives. This eases adoption into existing enterprise stacks and reuses decades of tooling, proxies, and security infrastructure.
- Secure by default. Enterprise-grade authentication and authorization are part of the design from the start, expressed through the same schemes (OAuth 2.0, OpenID Connect, API keys, mTLS) that secure conventional web APIs.
- Support for long-running tasks. A2A handles the full spectrum from sub-second calls to tasks that run for hours or days and require human-in-the-loop input, with first-class mechanisms for live status and asynchronous notification.
- Modality agnostic. Agents are not limited to text. The protocol carries files, structured data, and streaming audio/video, and supports negotiation of how content should be rendered to a user.
A sixth, feature-oriented principle, preserve opacity, appears prominently in the current specification: agents collaborate without revealing their internal state, memory, reasoning, or proprietary logic. Opacity is simultaneously a usability property (you can integrate an agent you do not control) and a security property (a compromised peer’s blast radius is bounded).
230.4 4. Architecture and Core Concepts
230.4.1 4.1 Client and Remote Agents
An A2A interaction has two roles. The client agent (also “A2A client”) initiates a request, it has work it wants done. The remote agent (also “A2A server”) exposes an A2A endpoint and fulfills tasks. A single agent is frequently both: an orchestrator is a client to its specialists and a server to the user-facing application above it. Roles are per-connection, not global identities.
The defining property of the remote agent is opacity. It advertises what it can do, never how. The client sees declared skills and capabilities; it never sees the remote agent’s system prompt, model choice, MCP servers, or chain of thought.
230.4.2 4.2 The Agent Card
Discovery is driven by the Agent Card: a JSON metadata document that an A2A server publishes to describe its identity, capabilities, and how to interact with it. Following RFC 8615 (well-known URIs), the recommended discovery location is:
https://{domain}/.well-known/agent-card.json
(Readers will encounter the older path /.well-known/agent.json in early drafts and third-party writing; the current specification standardized on agent-card.json.) A representative Agent Card:
{
"name": "Invoice Processing Agent",
"description": "Extracts, validates, and reconciles invoice data.",
"version": "1.2.0",
"url": "https://agents.example.com/invoice",
"preferredTransport": "JSONRPC",
"additionalInterfaces": [
{ "transport": "GRPC", "url": "https://agents.example.com/invoice/grpc" }
],
"capabilities": {
"streaming": true,
"pushNotifications": true
},
"defaultInputModes": ["text", "file"],
"defaultOutputModes": ["text", "data"],
"securitySchemes": {
"bearerAuth": { "type": "http", "scheme": "bearer" }
},
"security": [{ "bearerAuth": [] }],
"skills": [
{
"id": "extract-invoice",
"name": "Extract invoice fields",
"description": "Returns vendor, total, and line items as structured JSON.",
"inputModes": ["file"],
"outputModes": ["data"]
}
]
}The card declares: human-readable identity (name, description, version); the service url and any additionalInterfaces for alternative transports; coarse capabilities (streaming, push notifications); default input/output modalities; the security schemes a client must satisfy; and a list of skills, each a named unit of work with its own input/output modes. The card is the contract: a client reads it, decides whether the agent can help, and learns how to authenticate and connect.
230.4.3 4.3 Tasks and the Lifecycle
The unit of collaboration is the Task, a stateful object representing a single piece of delegated work. Every task carries an ID and moves through a defined lifecycle. The current specification enumerates nine states:
stateDiagram-v2
[*] --> submitted
submitted --> working
working --> input_required : agent needs more info from client
input_required --> working
working --> auth_required : needs credentials
auth_required --> working
working --> completed
working --> failed
working --> canceled
working --> rejected
completed --> [*]
failed --> [*]
canceled --> [*]
rejected --> [*]
note right of rejected
Terminal states.
unknown means state could not be determined.
end note
The core six states, submitted, working, input-required, completed, failed, canceled, describe the common path. The current spec adds rejected (the agent declines the task outright), auth-required (the agent needs additional credentials before proceeding), and unknown. The input-required state is what makes A2A suitable for human-in-the-loop and multi-turn workflows: a remote agent can pause, request clarification, and resume.
It is useful to state the lifecycle precisely as a finite state machine. Let the task be a tuple \((Q, q_0, F, \delta)\) where \(Q\) is the set of states above, \(q_0 = \texttt{submitted}\) is the unique initial state, and
\[ F = \{\,\texttt{completed},\ \texttt{failed},\ \texttt{canceled},\ \texttt{rejected}\,\} \]
is the set of terminal states. The transition relation \(\delta\) encodes the edges in the diagram. Two properties matter for implementers.
- Terminality (absorption). For every \(f \in F\) there is no outgoing transition, \(\delta(f, \cdot) = \varnothing\). A task that has reached a terminal state cannot be restarted or mutated; it can only be superseded by a new task with a fresh ID. This makes a terminal
Taskobject safe to cache, log, and forward as an immutable record. - Progress is monotone toward termination, with bounded back-edges. The only cycles are the explicit handshake loops,
working\(\leftrightarrow\)input-requiredandworking\(\leftrightarrow\)auth-required, which a client closes by supplying the requested input or credentials. Every other path moves strictly closer to a terminal state. A well-behaved client therefore models a task as a future that is guaranteed to resolve, provided it answers the back-edge requests; an unansweredinput-requiredis the canonical way a task stalls, so production clients set a timeout on it.
The unknown state is not a phase of the lifecycle but a reporting value: it is what a server returns when it cannot determine a task’s state, for example after a restart that lost in-memory state for a task whose ID it no longer recognizes. Clients should treat unknown as non-terminal and re-query rather than assume failure.
230.4.4 4.4 Messages, Parts, and Artifacts
Communication within a task uses Message objects. Each message carries a role, either "user" (the client agent’s side) or "agent" (the remote agent’s side), and a parts array. Parts are a union type, which is how A2A achieves modality-agnosticism:
TextPart, natural-language text.FilePart, a file, by URI reference or inline base64 bytes.DataPart, structured JSON (forms, parameters, machine-readable results).
The remote agent’s outputs are returned as Artifacts: named, typed results (themselves composed of parts) that represent the tangible product of the task, an extracted dataset, a generated document, a rendered chart. Parts also drive user-experience negotiation: an agent can indicate that a result is best rendered as an iframe, a video, or a web form, letting a client surface rich output appropriately.
230.5 5. Transport Mechanisms
A2A defines three transport bindings, all over HTTPS. An agent must support at least one and advertises its preference in the Agent Card via preferredTransport and additionalInterfaces.
- JSON-RPC 2.0 (
application/json), the original and most common binding. Method names follow a{category}/{action}convention, e.g.message/send,tasks/get,tasks/cancel. - gRPC, a normative Protocol Buffers definition (
a2a.proto) over HTTP/2 with TLS, for high-throughput, strongly-typed deployments. - HTTP+JSON / REST, resource-oriented URLs with conventional verbs and status codes, for teams that prefer plain REST.
For incremental results, A2A streams via Server-Sent Events (SSE): the remote agent holds an open text/event-stream connection and pushes JSON-RPC response frames as the task progresses (status changes, partial artifacts). For genuinely long-running work, holding a connection open is impractical, so A2A supports push notifications: the client supplies a webhook URL, disconnects, and the remote agent calls back when the task changes state. This combination, SSE for active interactions, webhooks for background tasks, covers both the conversational and the batch regimes.
230.5.1 5.1 A Worked Interaction
The following sequence shows a client discovering an agent and delegating a task with streaming updates.
sequenceDiagram
participant C as Client
participant R as "Remote Agent"
C->>R: GET /.well-known/agent-card.json
R-->>C: 200 OK { Agent Card }
C->>R: POST message/send (Bearer token)
R-->>C: 200 OK { task: submitted }
Note over C,R: SSE stream (status updates, artifacts)
R-->>C: working
R-->>C: working (partial artifact)
R-->>C: completed (final artifact)
A message/send request in the JSON-RPC binding:
{
"jsonrpc": "2.0",
"id": "req-1",
"method": "message/send",
"params": {
"message": {
"role": "user",
"parts": [
{ "kind": "text", "text": "Extract the fields from the attached invoice." },
{ "kind": "file", "file": { "uri": "https://files.example.com/inv-8841.pdf" } }
]
}
}
}The remote agent responds with a task in submitted state, then, because the Agent Card advertised "streaming": true, the client opens an SSE stream and receives working updates followed by a completed status carrying the result artifact (here, a DataPart with the extracted fields).
230.6 6. Security and Trust
A2A is designed to be secure by default and treats authentication exactly as a conventional enterprise web API would. The Agent Card’s securitySchemes declare what the client must present, API key, HTTP Bearer token, OAuth 2.0, OpenID Connect, or mutual TLS, using the same vocabulary as OpenAPI. Critically, credentials travel in HTTP headers, never inside A2A message payloads. A client authenticates the transport (Authorization: Bearer …); the protocol body carries only task content. This separation keeps secrets out of logs, traces, and the artifacts that may be forwarded to other agents.
Opacity reinforces the trust model. Because a remote agent never exposes its internal tools or reasoning, granting another organization’s agent access to yours does not hand it your data sources or prompts, only the declared skills, mediated by your authentication and authorization. Trust is established at the connection boundary and scoped to advertised capabilities.
It is worth stating opacity precisely, because it is the property that makes cross-vendor delegation tractable. Let a remote agent have internal state \(I\) (its system prompt, model identity, memory, MCP servers, intermediate reasoning) and a declared interface consisting of its Agent Card \(C\) and the artifacts \(A\) it returns. Opacity is the requirement that the information a client observes is a function of the interface alone,
\[ \mathrm{view}_{\text{client}} \subseteq \sigma(C, A), \]
where \(\sigma(C, A)\) is the information generated by the declared card and the returned artifacts, and never of \(I\) directly. Two consequences follow. First, a client can integrate an agent it does not control and cannot inspect, which is what makes the standard usable across organizations. Second, the blast radius of a compromised or malicious peer is bounded by what the interface exposes: it can return bad artifacts, but it cannot read your prompts or reach your tools, because those were never in its view. Opacity is thus simultaneously a usability property and a containment property. The practical caveat is that opacity constrains only the protocol surface, not the application logic above it: if your agent copies a private value into an outbound artifact, opacity will not stop the leak. Treat artifacts as the declassification boundary and review what flows into them.
230.7 7. Implementation with the Python SDK
A2A ships official SDKs for Python (a2a-sdk), JavaScript/TypeScript (@a2a-js/sdk), Java, .NET (A2A), Go, and Rust. The following sketches a minimal server and client in Python. (The SDK surface evolves; treat the shapes below as illustrative of the model rather than a frozen API, and consult the current a2a-sdk documentation for exact signatures.)
A minimal remote agent exposes an Agent Card and a handler that produces task artifacts:
from a2a.server import A2AServer, AgentExecutor
from a2a.types import AgentCard, AgentSkill, Message, TextPart
card = AgentCard(
name="Invoice Processing Agent",
description="Extracts and validates invoice data.",
version="1.2.0",
url="https://agents.example.com/invoice",
capabilities={"streaming": True, "pushNotifications": True},
default_input_modes=["text", "file"],
default_output_modes=["text", "data"],
skills=[AgentSkill(
id="extract-invoice",
name="Extract invoice fields",
description="Returns vendor, total, line items as JSON.",
input_modes=["file"],
output_modes=["data"],
)],
)
class InvoiceExecutor(AgentExecutor):
async def execute(self, context, event_queue):
# Stream progress, then emit the final artifact.
await event_queue.update_status("working")
fields = await self.parse_invoice(context.message) # internal logic (may use MCP)
await event_queue.add_artifact(name="invoice", data=fields)
await event_queue.update_status("completed")
server = A2AServer(agent_card=card, executor=InvoiceExecutor())
server.run(host="0.0.0.0", port=8080)A client discovers the agent from its card and delegates a task:
from a2a.client import A2AClient
client = await A2AClient.from_agent_card_url(
"https://agents.example.com/invoice/.well-known/agent-card.json",
auth_token=TOKEN,
)
task = await client.send_message(parts=[
{"kind": "text", "text": "Extract fields from this invoice."},
{"kind": "file", "file": {"uri": "https://files.example.com/inv-8841.pdf"}},
])
async for update in client.stream(task.id): # SSE updates
if update.status == "completed":
print(update.artifacts[0].data)The key architectural point is in InvoiceExecutor.parse_invoice: whatever tools, models, or MCP servers it uses are entirely invisible to the client. The client sees only the declared skill and the returned artifact, opacity in practice.
230.8 8. Governance and Ecosystem
A2A’s move to the Linux Foundation is central to its credibility as a neutral standard. At the June 2025 donation, the project launched with seven founding members, Amazon Web Services, Cisco, Google, Microsoft, Salesforce, SAP, and ServiceNow, and more than a hundred supporting companies. Placing the specification under foundation governance, rather than leaving it under a single vendor, is what allows competitors to adopt it without ceding strategic control; the Linux Foundation’s executive director framed the donation as ensuring “long-term neutrality, collaboration and governance.”
The ecosystem spans framework integrations (LangGraph/LangChain, CrewAI, Google’s Agent Development Kit, Microsoft Semantic Kernel) and a broad adopter list drawn from the original launch: Atlassian, Box, Cohere, Intuit, MongoDB, PayPal, Salesforce, SAP, ServiceNow, UKG, Workday, UiPath, and many others, alongside the major systems integrators. Notably, IBM’s competing Agent Communication Protocol merged into A2A in September 2025, a consolidation discussed in the landscape chapter and a strong signal that A2A had become the de facto agent-to-agent standard.
230.9 9. When to Use A2A, and Common Pitfalls
A2A is not the right hammer for every nail. The choice among a plain in-process function call, an MCP tool call, and an A2A delegation turns on who owns the work and what boundary it crosses.
- Use a direct function or library call when the capability lives inside your own agent’s process and trust domain. There is no boundary to cross, so adding a protocol only adds latency and serialization cost.
- Use MCP when your single agent needs a tool, data source, or resource: a database, a code interpreter, a search index. MCP models the callee as a capability the agent invokes and is responsible for. The vertical axis.
- Use A2A when the work belongs to another autonomous agent, typically owned by a different team or vendor, that you should not model as a function and whose internals you neither see nor control. The horizontal axis. The tell is opacity: if you genuinely cannot (and should not) know how the other side does the work, it is a peer, not a tool.
A useful rule of thumb: if the answer to “could I reasonably reimplement this myself if I had the source?” is yes, it is probably a tool (MCP); if it is “no, that is someone else’s agent with its own judgment and private context,” it is a peer (A2A).
Common pitfalls in practice:
- Putting credentials in the message body. Secrets belong in HTTP headers, never in a
TextPartorDataPart. Payloads get logged, traced, and forwarded to downstream agents; headers do not. - Polling instead of streaming or webhooks. For active tasks subscribe to the SSE stream; for long-running tasks register a push-notification webhook. Tight polling of
tasks/getwastes both sides’ resources and still adds latency. - Ignoring the back-edge states. A client that does not handle
input-requiredandauth-requiredwill hang on any task that needs clarification or step-up authentication. Always set a timeout on these states. - Assuming a single transport. An agent advertises a
preferredTransportand may listadditionalInterfaces; a robust client reads the card and negotiates rather than hard-coding JSON-RPC. - Treating a remote agent as deterministic. Peers are autonomous and may be non-deterministic, rate-limited, or temporarily degraded. Delegation should be idempotent where possible and defensive about partial or
unknownresults. - Leaking private state through artifacts. As noted in the security section, opacity protects the protocol surface, not your own application logic. Review what your executor writes into outbound artifacts.
230.10 10. Limitations and Open Questions
A2A is young, and several aspects remain in motion. The specification’s version numbering advanced quickly across late 2025 and early 2026 (the detailed multi-transport behavior was specified in the v0.3 line, with a subsequent 1.0 milestone); implementers should pin to a specific spec version and verify the current tag. The gRPC and REST bindings, and the Go and Rust SDKs, are post-launch additions not present in the original announcement. Deeper questions are inherently harder: how to establish trust and reputation among agents that have never interacted, how to attribute responsibility when a chain of delegated tasks produces a bad outcome, and how to bill and meter cross-organizational agent work. The payments dimension of that last question is precisely what the next chapter, on the Agent Payments Protocol, addresses.
230.11 11. Conclusion
A2A is the horizontal counterpart to MCP’s vertical integration: where MCP connects an agent to its tools, A2A connects agents to one another. Its core machinery is deliberately conventional, Agent Cards for discovery, a stateful Task lifecycle, modality-agnostic Messages and Artifacts, JSON-RPC/gRPC/REST transports over HTTPS, SSE and webhooks for long-running work, precisely so that it can ride on existing enterprise infrastructure. Its opacity principle makes cross-vendor collaboration tractable by bounding what any peer can see. And its donation to the Linux Foundation, together with the absorption of competing standards, established it as the neutral substrate on which the multi-agent web is being built. The protocols that layer above it for commerce, and the broader landscape of standards that surround it, are the subjects of the following chapters.
230.12 References
- Google. “Announcing the Agent2Agent Protocol (A2A): A new era of agent interoperability.” Google Developers Blog, April 9, 2025. https://developers.googleblog.com/en/a2a-a-new-era-of-agent-interoperability/
- Google. “Google Cloud donates A2A to the Linux Foundation.” Google Developers Blog, June 23, 2025. https://developers.googleblog.com/en/google-cloud-donates-a2a-to-linux-foundation/
- Linux Foundation. “Linux Foundation Launches the Agent2Agent Protocol Project.” June 23, 2025. https://www.linuxfoundation.org/press/linux-foundation-launches-the-agent2agent-protocol-project-to-enable-secure-intelligent-communication-between-ai-agents
- A2A Protocol Specification (v0.3.0). https://a2a-protocol.org/v0.3.0/specification/
- A2A Protocol, official site and key concepts. https://a2a-protocol.org/latest/
- A2A Project on GitHub (SDKs, samples, proto). https://github.com/a2aproject/A2A
- Linux Foundation. “A2A Protocol Surpasses 150 Organizations… in First Year.” https://www.linuxfoundation.org/press/a2a-protocol-surpasses-150-organizations-lands-in-major-cloud-platforms-and-sees-enterprise-production-use-in-first-year
- RFC 8615. “Well-Known Uniform Resource Identifiers (URIs).” IETF.