Skip to main content

Agent2Agent Protocol (A2A)

A reference for the Agent2Agent protocol, covering Agent Cards and discovery, tasks, messages and artifacts, the JSON-RPC, gRPC and HTTP+JSON bindings, streaming and push notifications, and how A2A differs from MCP.

Current version1.0
Specificationa2a-protocol.org
Updated2026-10-14

What is A2A?

The Agent2Agent protocol (A2A) is an open protocol for one AI agent to discover another, hand it a task, and follow that task to completion. The agent on the other side is opaque: the caller does not see its tools, its prompts or its model, only the skills it advertises and the results it returns. A2A was created by Google, donated to the Linux Foundation in June 2025, and accepted as a project of the Agentic AI Foundation (AAIF) in August 2026. Version 1.0 is the first stable release.

A2A builds on existing standards rather than inventing transport: HTTP, JSON-RPC 2.0, gRPC and Server-Sent Events.


1. A2A and MCP

The two protocols are often mentioned together and solve different problems. The A2A specification itself calls them complementary.

MCP A2A
Connects An AI application to tools and data An agent to another agent
The far side is A capability: a function, a resource, a prompt A peer: an autonomous agent with its own reasoning
Unit of work A tool call, usually short-lived A task with a lifecycle that can run for hours and pause for input
Visibility The model sees every tool’s schema The caller sees advertised skills, not internals

A typical deployment uses both: a client agent delegates a job to a remote agent over A2A, and that remote agent uses MCP to reach the tools and data it needs. Choose A2A when the thing you are calling decides how to do the work; choose MCP when you are exposing a specific operation and the caller decides when to invoke it. Wrapping a plain CRUD API as an “agent” just to speak A2A adds a task lifecycle that nothing needs.


2. The Agent Card

Discovery starts with an Agent Card, a JSON document describing the agent. The specification defines a well-known URI on the agent’s domain for it:

GET /.well-known/agent-card.json HTTP/1.1
Host: planner.example.com
{
"name": "Trip Planner Agent",
"description": "Plans multi-day travel itineraries.",
"version": "1.0.0",
"supportedInterfaces": [
{
"url": "https://planner.example.com/a2a/v1",
"protocolBinding": "HTTP+JSON",
"protocolVersion": "1.0"
}
],
"capabilities": { "streaming": true, "pushNotifications": false },
"defaultInputModes": ["text/plain"],
"defaultOutputModes": ["text/plain", "application/json"],
"skills": [
{
"id": "itinerary-planning",
"name": "Itinerary planning",
"description": "Builds a day-by-day plan from dates, budget and interests.",
"tags": ["travel"]
}
]
}

The required members are name, description, supportedInterfaces, version, capabilities, defaultInputModes, defaultOutputModes and skills. securitySchemes declares how to authenticate, modeled on the OpenAPI 3.2 Security Scheme Object: API key, HTTP auth, OAuth 2.0, OpenID Connect and mutual TLS. A card can carry signatures so a consumer can verify it really belongs to the domain that serves it, and an agent can expose a richer extended Agent Card to authenticated callers.

Write skill descriptions for a model, not for a marketing page. A client agent decides whether to delegate based on that text alone.


3. Tasks, Messages and Artifacts

  • Message: one turn of communication, with a role (ROLE_USER or ROLE_AGENT), a messageId and an array of parts.
  • Part: a unit of content holding exactly one of text, raw bytes, a url or structured data, optionally with a mediaType.
  • Task: the stateful unit of work, with an id, a contextId grouping related tasks, a status, a history and artifacts.
  • Artifact: an output the agent produced, itself made of parts.

A task moves through these states:

State Kind
TASK_STATE_SUBMITTED, TASK_STATE_WORKING Active
TASK_STATE_INPUT_REQUIRED, TASK_STATE_AUTH_REQUIRED Interrupted: the agent is waiting on the caller
TASK_STATE_COMPLETED, TASK_STATE_FAILED, TASK_STATE_CANCELED, TASK_STATE_REJECTED Terminal

An agent can answer a simple request with a direct message instead of creating a task. Clients must handle both.


4. Protocol Bindings

The operations (Send Message, Send Streaming Message, Get Task, List Tasks, Cancel Task, Subscribe to Task, plus push notification configuration) are defined abstractly and mapped onto three official bindings, named in the Agent Card’s protocolBinding:

Binding Shape
JSONRPC JSON-RPC 2.0 over HTTP, methods such as SendMessage and GetTask
GRPC Protocol Buffers service definitions
HTTP+JSON Resource-style endpoints such as POST /message:send and GET /tasks/{id}
POST /a2a/v1/message:send HTTP/1.1
Host: planner.example.com
Content-Type: application/a2a+json
A2A-Version: 1.0
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
{
"message": {
"role": "ROLE_USER",
"messageId": "0b6f2c1e-6a43-4c3e-9d0a-2f1d4c8e7a51",
"parts": [{ "text": "Plan three days in Lisbon in May, mid-range budget." }]
}
}

Clients send the version they speak in the A2A-Version header (major and minor only). A server that does not support it returns 400 Bad Request with a problem details body listing the versions it does support.


5. Long-Running Work

A2A gives three ways to follow a task, and the right one depends on how long it runs:

  • Polling with Get Task. Fine for short tasks and the simplest to make reliable.
  • Streaming over Server-Sent Events, via Send Streaming Message or Subscribe to Task. The stream carries status and artifact updates and closes when the task reaches a terminal state. The agent must advertise capabilities.streaming.
  • Push notifications: the client registers a webhook URL and the agent POSTs updates to it. The agent sends the credentials named in the push configuration’s authentication field in an Authorization header. Use this for tasks that outlive any reasonable connection, and treat the receiving endpoint like any other webhook: reject unauthenticated calls, and fetch the task with Get Task rather than trusting the payload alone.

Treat a remote agent’s output with the same suspicion as any third-party API response. It came from a model you do not control.

On this page (6 sections)