Blog/AI agents
The A2A protocol explained: agent cards, tasks, and where it fits next to MCP
What the Agent2Agent protocol standardizes in v1.0: agent cards, tasks, bindings, security, how it differs from MCP, and when it is worth using.
Balázs Csorba··12 min read
- A2A
- AI agents
- MCP
- Interoperability
- Agent security

Key takeaways
- A2A connects agents to each other; MCP connects an agent to its tools. Most real systems that need A2A also use MCP.
- An agent card at /.well-known/agent-card.json declares identity, interfaces, skills and the security schemes a caller must use.
- Work is a task with a server-generated id and a state machine, so long-running and multi-turn jobs are first-class, not bolted on.
- Version 1.0 is the first stable spec, with JSON-RPC, gRPC and HTTP+JSON bindings and optional signed agent cards.
- A remote agent is untrusted input: authorize every operation, validate webhook URLs, and confirm sensitive actions out of band.
Most agent tooling so far has been about one agent and its tools. The next problem appears as soon as two agents built by different teams need to work together: a purchasing agent in your shop that wants to ask a supplier's availability agent, or an internal support agent that hands a case to the logistics team's agent. Each side has its own framework, model and deployment. Without a shared protocol, every such pairing is a custom integration.
Agent2Agent (A2A) is the open protocol for that problem. This article explains what version 1.0 of the specification actually standardizes, agent cards, tasks, messages, transports and security, how it relates to MCP, the trust problems it does not solve for you, and when I would use it.
What is the A2A protocol?
Google announced A2A on 9 April 2025 with more than 50 technology partners, built on existing standards including HTTP, SSE and JSON-RPC. Its five design principles were to embrace agentic capabilities, build on existing standards, be secure by default, support long-running tasks and be modality agnostic. On 23 June 2025 the Linux Foundation launched the Agent2Agent project at Open Source Summit North America, with more than 100 companies supporting it, which moved governance out of a single vendor.
The current specification is version 1.0.0, after 0.1.0, 0.2.6 and 0.3.0. Compatibility is tracked by major and minor version, and clients send an A2A-Version header. In its one-year update of 9 April 2026, the Linux Foundation described 1.0 as the first stable specification and reported more than 150 supporting organizations, SDKs in five languages (Python, JavaScript, Java, Go and .NET), and support in Azure AI Foundry, Copilot Studio and Amazon Bedrock AgentCore Runtime.
How does A2A relate to MCP?
The A2A documentation frames the two as complementary layers. MCP is vertical: it gives one agent structured access to tools and resources, which are typically well-defined and often stateless. A2A is horizontal: it lets independent, often opaque agents collaborate as peers, with reasoning, state and multi-turn dialogue on both sides. In the docs' own words, "A2A connects the agents to each other; MCP connects each agent to its own tools."
| Question | MCP | A2A |
|---|---|---|
| Who is on the other end? | A tool or data server | Another agent that reasons and plans |
| Unit of work | A tool call with arguments and a result | A task with an id, states, messages and artifacts |
| Visibility of internals | Tool schemas are exposed to the model | The remote agent stays opaque |
| Typical boundary | Inside one agent's deployment | Between teams, services or companies |
The overlap is real: an A2A agent with a few stateless skills could be wrapped as an MCP server, and the docs say as much. My rule of thumb is that if the other side behaves like a function, use MCP; if it needs to ask clarifying questions, work for minutes or hours, or keep its reasoning private, use A2A. For the MCP side, see the MCP security checklist.
What is in an agent card?
An agent card is a JSON document in which an A2A server describes itself. The normative data model is a2a.proto; the required fields of AgentCard are name, description, supported interfaces, version, capabilities, default input and output modes, and skills. Each interface names a URL, a protocol binding (JSONRPC, GRPC or HTTP+JSON) and a protocol version. Each skill has an id, name, description and tags, plus optional examples and its own input and output modes and security requirements.
// https://agents.supplier.example/.well-known/agent-card.json (illustrative)
{
"name": "Parts Availability Agent",
"description": "Answers stock and lead-time questions for industrial spare parts.",
"version": "2.3.0",
"provider": { "organization": "Example Supplier GmbH", "url": "https://supplier.example" },
"supportedInterfaces": [
{ "url": "https://agents.supplier.example/a2a", "protocolBinding": "JSONRPC", "protocolVersion": "1.0" },
{ "url": "https://agents.supplier.example/a2a/rest", "protocolBinding": "HTTP+JSON", "protocolVersion": "1.0" }
],
"capabilities": { "streaming": true, "pushNotifications": true, "extendedAgentCard": true },
"securitySchemes": {
"oidc": { "openIdConnectSecurityScheme": { "openIdConnectUrl": "https://login.supplier.example/.well-known/openid-configuration" } }
},
"securityRequirements": [ { "schemes": { "oidc": { "list": ["parts.read"] } } } ],
"defaultInputModes": ["text/plain", "application/json"],
"defaultOutputModes": ["text/plain", "application/json"],
"skills": [
{
"id": "check-availability",
"name": "Check availability",
"description": "Stock level and lead time for a part number at a given warehouse.",
"tags": ["inventory", "spare-parts"],
"examples": ["Is ART-10001 in stock in Vienna?"]
}
]
}Discovery has three options in the docs: the well-known URI https://{server_domain}/.well-known/agent-card.json, curated registries (for which the spec defines no standard API), and direct configuration. The card endpoint should send Cache-Control with max-age and an ETag, and clients should use conditional requests. Cards may be signed with JSON Web Signature (RFC 7515) over a JSON Canonicalization Scheme (RFC 8785) form, and clients should verify at least one signature before trusting a signed card.
A public card should not leak internals. If you need to show more skills or internal URLs to trusted partners, set capabilities.extendedAgentCard and serve the full card through GetExtendedAgentCard, which must require authentication. Keep static secrets out of every card.
Write skill descriptions for a model, not for a marketing page. On the client side, an LLM often reads the card to decide which remote agent and which skill fit a request, so a description plays the same role as a tool description in MCP: say what the skill does, what input it expects and what it will not do. Bump version whenever skills change, so cached cards and ETags stay meaningful.
How do tasks, messages and artifacts work?
A message is one turn of communication, with a messageId, a role (ROLE_USER for the client, ROLE_AGENT for the server) and a list of parts. A part is the smallest content unit: text, raw bytes, a URL or structured data, with optional mediaType and filename. When the server takes on work, it creates a task with a server-generated id, a contextId that groups related tasks and messages, a status, a history and artifacts, the outputs such as documents or structured data, themselves built from parts.
The TASK_STATE_AUTH_REQUIRED state is worth noting: an agent can pause mid-task because it needs the user to grant access to something, which is exactly the kind of approval step I argue for in human in the loop for AI agents. To continue a multi-turn exchange, the client sends a new message with the same contextId and the taskId of the existing task; mismatched ids are rejected.
Which transports and update modes are there?
Version 1.0 defines three standard bindings, JSON-RPC, gRPC and HTTP+JSON (REST), and allows custom ones. All bindings must behave equivalently, and the proto file is the source of truth for the data objects. The core operations map like this:
| Operation | JSON-RPC and gRPC method | HTTP+JSON |
|---|---|---|
| Send a message | SendMessage | POST /message:send |
| Send and stream updates | SendStreamingMessage | POST /message:stream |
| Read a task | GetTask | GET /tasks/{id} |
| Cancel a task | CancelTask | POST /tasks/{id}:cancel |
| Register a webhook | CreateTaskPushNotificationConfig | POST /tasks/{id}/pushNotificationConfigs |
| Other operations | ListTasks, SubscribeToTask, GetExtendedAgentCard | equivalent endpoints |
SendMessage blocks by default; with returnImmediately it returns at once and the client follows the task in one of three ways: polling with GetTask, streaming with SendStreamingMessage or SubscribeToTask, or push notifications, where the server POSTs updates to a webhook the client registered. Push is the right choice for tasks that take hours, because nobody wants to hold a stream open that long. A JSON-RPC call looks like this:
// POST https://agents.supplier.example/a2a (JSON-RPC binding, illustrative)
{
"jsonrpc": "2.0",
"id": "req-42",
"method": "SendMessage",
"params": {
"message": {
"messageId": "9b0c7e7a-2f1d-4c55-9f0e-1f6a2d0c3e11",
"role": "ROLE_USER",
"parts": [{ "text": "Is ART-10001 in stock in Vienna, and what is the lead time for 40 units?" }]
}
}
}Which binding to pick is mostly a question of what your services already speak. JSON-RPC is the most common in examples and SDKs, HTTP+JSON fits teams that run REST gateways and want readable URLs in their logs, and gRPC suits internal service meshes that already use protobuf. A card can list several interfaces, so a server can offer two bindings while clients choose one.
What does A2A security involve?
Authentication is declared, not invented: the agent card lists securitySchemes, which can be API key, HTTP auth, OAuth 2.0 (authorization code, client credentials or device code flows), OpenID Connect or mutual TLS, and says which are required. Credentials travel in the transport layer, as in any HTTP API. For agent-to-agent calls between companies, OAuth client credentials or mTLS are the natural fit, and the calling agent should have its own identity with narrow scopes, as discussed in AI agents are identities.
The security section of the specification adds obligations that matter in practice:
- Authorization on every operation, with results scoped to the caller even when no filter is given, and checks before any lookup that could reveal that out-of-scope resources exist.
- Webhook validation against SSRF: reject private ranges such as 10.0.0.0/8 and 192.168.0.0/16, localhost and link-local addresses, and use allowlists where possible; time out webhook requests after 10 to 30 seconds.
- Input validation and limits on message sizes, file sizes and request complexity, plus rate limiting on all operations.
- Webhook receivers confirm that each notification refers to a task they actually started, and tolerate duplicate deliveries.
Why is a remote agent untrusted input?
Authentication tells you who the other agent is, not whether what it says is safe. On 31 October 2025, Unit 42 published agent session smuggling: a malicious remote agent exploits an established session to send covert instructions to the client agent. In their proof of concept, built with Google's Agent Development Kit, the remote agent got a financial assistant to reveal its configuration and session history, and to call a buy_stock tool the user had not asked for. Unit 42 states clearly that this is not a vulnerability in A2A itself; it exploits the implicit trust between agents in any stateful, multi-turn protocol.
When should you use A2A, and when not?
A protocol costs something: an agent card to maintain, a task store, auth between services, versioning. It pays off at boundaries, not inside one codebase. My decision guide:
| Situation | What I would use |
|---|---|
| One team, one codebase, several specialised agents | Sub-agents or function calls in your framework; no protocol |
| An agent needs a database, API or file system | MCP |
| Agents owned by different teams, deployed and versioned separately | A2A, with OAuth or mTLS between services |
| A partner or vendor exposes an agent, not an API | A2A client; treat output as untrusted |
| The remote side has a stable, well-defined API | Call the API directly or wrap it as an MCP tool |
If you are weighing whether you need several agents at all, multi-agent systems: when they are worth it covers the token cost and failure modes. For commerce, the Agent Payments Protocol (AP2) sits in the A2A ecosystem; I compare it with UCP and ACP in agentic commerce protocols.
How do you start with A2A?
- Pick one boundary where two agents already talk through a bespoke integration, and model the exchange as tasks with explicit states.
- Write the agent card first: skills with clear descriptions and examples, one binding to start with, and the security scheme you will actually enforce.
- Use an official SDK in your language rather than hand-writing the protocol, and pin the protocol version.
- Persist tasks in a store that survives restarts, because tasks can outlive a process; use push notifications for anything slow.
- Trace across the boundary with the task id and context id in every log line, so a failure can be followed from one agent into the other.
Sources
- A2A Protocol Specification (latest, v1.0)
- A2A: a2a.proto, the normative data model (GitHub)
- A2A docs: A2A and MCP
- A2A docs: Agent discovery
- Google Developers Blog: Announcing the Agent2Agent Protocol (Apr 2025)
- Linux Foundation: Launch of the Agent2Agent Protocol Project (Jun 2025)
- Linux Foundation: A2A surpasses 150 organizations in its first year (Apr 2026)
- Unit 42: Agent Session Smuggling in Agent2Agent Systems (Oct 2025)
Frequently asked questions
What is the A2A protocol?
Agent2Agent (A2A) is an open protocol for AI agents built by different teams or vendors to discover each other, exchange messages and hand off tasks. Google announced it in April 2025 and donated it to the Linux Foundation in June 2025; version 1.0 is the first stable specification.
What is the difference between A2A and MCP?
MCP standardizes how an agent uses tools and resources, typically well-defined functions. A2A standardizes how independent, often opaque agents collaborate as peers on tasks that can be stateful, multi-turn and long-running. The A2A docs call them complementary: A2A connects the agents to each other, MCP connects each agent to its own tools.
Where is an A2A agent card published?
The specification defines a well-known URI, https://{server_domain}/.well-known/agent-card.json, fetched with a plain HTTP GET. Agents can also be discovered through curated registries or configured directly. More detailed cards can be served only to authenticated callers through the extended agent card operation.
Is A2A secure?
The protocol defines the hooks: security schemes in the agent card (API key, HTTP auth, OAuth 2.0, OpenID Connect, mutual TLS), mandatory authorization on every operation and optional signed cards. Whether a deployment is secure depends on implementing them, and on treating messages from remote agents as untrusted input.
Do I need A2A for a multi-agent system inside one application?
Usually not. If you own all the agents and they run in one codebase, sub-agents or function calls are simpler. A2A pays off at boundaries: between teams, services or companies, where agents are deployed and versioned independently.