Agent-to-Agent Communication and A2A
A tool is a function your agent controls. Another agent is a colleague with its own mind, memory, and schedule. This module covers how agents talk to each other as peers: the A2A protocol, how it models work, how agents find and trust one another, and how to build an agent that plays well with others.
Why agents need to talk to agents
In the previous module, your agent reached out to the world through tools, usually exposed over MCP. A tool is predictable: you send arguments, it runs some code, it returns a result. The agent decides everything; the tool just executes.
Now picture a travel-booking agent that needs a visa check. Another company has already built a visa agent. It reasons about edge cases, asks follow-up questions, keeps its own case history, and sometimes takes hours because a human reviewer is involved. Wrapping that as a "tool" breaks down quickly. It isn't a function. It's an opaque agent: it has its own reasoning, its own state, its own tools and data you never see, and its own timeline.
| Calling a tool (MCP) | Delegating to an agent (A2A) | |
|---|---|---|
| Who decides how | Your agent | The remote agent |
| What you see inside | A schema for inputs and outputs | Only a public description of skills; internals stay private |
| Duration | Usually one request and one response | Can run for minutes, hours or days, with pauses |
| Conversation | Rarely; mostly one-shot | Multi-turn: the remote agent can ask for more input |
| State | Mostly stateless from the caller's view | A stateful task with a lifecycle |
| Shared memory or tools | Not applicable | None. Agents exchange messages and artifacts only |
A common mental model in 2026: MCP is vertical (an agent reaching down to its tools and data) and A2A is horizontal (an agent reaching sideways to another agent). Most serious systems use both. Your agent uses MCP to read your calendar, and A2A to hand a sub-problem to a specialist agent run by another team or company.
Why opacity is a feature
Agents that don't share memory or internals can be built by different vendors, on different frameworks and models, and still cooperate. The remote agent keeps its proprietary prompts, data and tools private. You get its results without needing to trust or understand its implementation, which is how most human businesses work with each other too.
A short history of A2A
The Agent2Agent (A2A) protocol moved quickly from one company's proposal to a neutrally governed standard. Knowing the timeline helps you read older tutorials, which often describe pre-1.0 field names.
- 1
April 2025: Google announces A2A
Launched with more than 50 partners as an open protocol for agents to collaborate across vendors and frameworks.
- 2
June 2025: moved to the Linux Foundation
Google transferred the spec and SDKs to the Linux Foundation, so no single company controls the protocol.
- 3
Late summer 2025: IBM's ACP merges in
IBM Research's Agent Communication Protocol (ACP, from the BeeAI project) merged into A2A rather than competing with it. ACP users got a migration path: an Agent Card replaces the ACP manifest, and A2A task methods replace ACP endpoints. Sources differ on whether this was August or September.
- 4
Early 2026: v1.0, the first stable spec
After 0.1, 0.2.x and 0.3, the spec reached 1.0.0, adding signed Agent Cards, multi-tenancy, a Protocol Buffers type system and three official bindings. In April 2026 the Linux Foundation reported 150+ supporting organizations and native support in Azure AI Foundry, Copilot Studio, Amazon Bedrock AgentCore and Google Cloud.
- 5
August 27, 2026: A2A joins the Agentic AI Foundation
A2A became a Growth Stage project of the Linux Foundation's Agentic AI Foundation (AAIF), which already hosted MCP, goose and AGENTS.md. A2A keeps its own Technical Steering Committee. The protocols sit under one roof but were not merged.
Two different ACPs
IBM's Agent Communication Protocol (merged into A2A) is unrelated to the Agentic Commerce Protocol from OpenAI and Stripe, which you'll meet in Module 7. Same acronym, different jobs.
The Agent Card: an agent's business card
Before two agents can work together, the client agent needs to know what the remote agent can do, where to reach it, and how to authenticate. A2A puts all of this in one JSON document called the Agent Card. By convention it is published at https://{domain}/.well-known/agent-card.json.
Identity
name, description, version, and an optional provider with the organization behind the agent.
Interfaces
supportedInterfaces lists each endpoint URL with its protocolBinding and protocolVersion, in order of preference.
Capabilities
Flags such as streaming, pushNotifications and extendedAgentCard, plus any declared extensions.
Skills
What the agent is good at: each skill has an id, name, description, tags, example prompts, and accepted input and output media types.
Security
securitySchemes describes how to authenticate, and securityRequirements says which schemes and scopes are needed.
Signatures
New in v1.0: optional JWS signatures let a client verify that the card really comes from the claimed provider and hasn't been altered.
{
"name": "Visa Requirements Agent",
"description": "Checks entry and visa requirements for a traveler's itinerary and asks follow-up questions when details are missing.",
"supportedInterfaces": [
{ "url": "https://visa.example.com/a2a/v1", "protocolBinding": "JSONRPC", "protocolVersion": "1.0" },
{ "url": "https://visa.example.com/a2a/json", "protocolBinding": "HTTP+JSON", "protocolVersion": "1.0" }
],
"provider": {
"organization": "Example Travel Compliance Inc.",
"url": "https://www.example.com"
},
"version": "2.1.0",
"capabilities": {
"streaming": true,
"pushNotifications": true,
"extendedAgentCard": true
},
"securitySchemes": {
"corpOidc": {
"openIdConnectSecurityScheme": {
"openIdConnectUrl": "https://login.example.com/.well-known/openid-configuration"
}
}
},
"securityRequirements": [{ "schemes": { "corpOidc": { "list": ["openid", "visa.read"] } } }],
"defaultInputModes": ["text/plain", "application/json"],
"defaultOutputModes": ["text/plain", "application/json"],
"skills": [
{
"id": "visa-check",
"name": "Visa requirement check",
"description": "Given a passport country and an itinerary, reports which visas or entry permits are required.",
"tags": ["travel", "visa", "compliance"],
"examples": ["Do I need a visa to visit Japan for 10 days on a Canadian passport?"],
"inputModes": ["text/plain", "application/json"],
"outputModes": ["application/json"]
}
],
"signatures": [
{ "protected": "eyJhbGciOiJFUzI1NiIs...", "signature": "QFdkNLNszlGj3z3u..." }
]
}Notice what the card doesn't contain: no system prompt, no list of internal tools, no model name. It is a public contract, not a description of internals. Agents can also offer an extended Agent Card that is only returned to authenticated clients (the GetExtendedAgentCard operation), for example to reveal premium skills to paying customers.
Write skills for a model to read
The client deciding whether to call your agent is often an LLM reading your card. Clear skill descriptions and realistic examples matter as much as a good tool description does in MCP. Vague skills lead to wrong delegations.
Tasks, messages, parts and artifacts
A2A models work with four core objects. Once you understand how they fit together, the rest of the protocol is mostly plumbing.
Task
A stateful unit of work with a server-generated id, a current status, any output artifacts, and optional history. Tasks are how A2A handles long-running work.
Message
One turn of communication, with a role (ROLE_USER from the client, ROLE_AGENT from the server), a messageId, and one or more parts. Messages carry instructions, questions and status updates.
Part
The content inside a message or artifact. A part holds text, a file (inline bytes as raw, or a url), or structured data (any JSON value), with an optional mediaType and filename.
Artifact
A task's output, made of parts and identified by an artifactId. Reports, images and JSON results go here, separate from the conversation.
The split between messages and artifacts is deliberate. The spec says results should be returned as artifacts, not messages. Messages are for talking about the work ("Which dates?", "Still working, 60% done"), and artifacts are the work. This lets a client store deliverables reliably while treating chatter as disposable.
Related tasks and messages share a contextId, which groups a whole conversation. A client can continue a specific task by sending its taskId, or start a new task in the same conversation by sending only the contextId.
| State | Kind | What it means |
|---|---|---|
TASK_STATE_SUBMITTED | Active | The agent has received and acknowledged the task. |
TASK_STATE_WORKING | Active | The agent is processing it. |
TASK_STATE_INPUT_REQUIRED | Interrupted | The agent needs more information from the client before it can continue. |
TASK_STATE_AUTH_REQUIRED | Interrupted | The agent needs an authorization (for example an OAuth token or a human approval) that the client must supply. |
TASK_STATE_COMPLETED | Terminal | Finished successfully; artifacts hold the results. |
TASK_STATE_FAILED | Terminal | Finished with an error. |
TASK_STATE_CANCELED | Terminal | Canceled before completion, usually by the client. |
TASK_STATE_REJECTED | Terminal | The agent declined to do the task at all. |
input-required.The two interrupted states are what make A2A feel like working with a colleague. A tool either succeeds or fails. An agent can stop and say "I need your departure city" or "I need you to authorize access to your calendar," then pick up where it left off once you answer.
A task exchange, step by step
Here is a multi-turn exchange using the HTTP+JSON binding. The travel agent (the client) asks the visa agent (the server) a question, and the visa agent needs one more detail.
POST /a2a/json/message:send HTTP/1.1
Host: visa.example.com
Content-Type: application/a2a+json
A2A-Version: 1.0
Authorization: Bearer <token>
{
"message": {
"role": "ROLE_USER",
"messageId": "msg-1",
"parts": [{ "text": "Does my traveler need a visa for a 10-day trip to Japan?" }]
}
}
HTTP/1.1 200 OK
Content-Type: application/a2a+json
{
"task": {
"id": "task-42",
"contextId": "ctx-7",
"status": {
"state": "TASK_STATE_INPUT_REQUIRED",
"message": {
"role": "ROLE_AGENT",
"messageId": "msg-2",
"parts": [{ "text": "Which passport does the traveler hold?" }]
}
}
}
}POST /a2a/json/message:send HTTP/1.1
Host: visa.example.com
Content-Type: application/a2a+json
A2A-Version: 1.0
Authorization: Bearer <token>
{
"message": {
"taskId": "task-42",
"role": "ROLE_USER",
"messageId": "msg-3",
"parts": [{ "data": { "passportCountry": "CA", "durationDays": 10 } }]
}
}
HTTP/1.1 200 OK
Content-Type: application/a2a+json
{
"task": {
"id": "task-42",
"contextId": "ctx-7",
"status": { "state": "TASK_STATE_COMPLETED" },
"artifacts": [{
"artifactId": "art-1",
"name": "Visa assessment",
"parts": [{ "data": { "visaRequired": false, "notes": "Illustrative output only" } }]
}]
}
}taskId, this time with a structured data part, and the task completes with an artifact. The artifact content is illustrative, not real visa guidance.The same operations exist in every binding. In JSON-RPC, you'd POST {"jsonrpc": "2.0", "method": "SendMessage", "params": {...}} to the JSON-RPC URL from the card instead.
| Operation | What it does | HTTP+JSON route |
|---|---|---|
SendMessage | Start or continue a task; returns a Task or a direct Message | POST /message:send |
SendStreamingMessage | Same, but streams updates as they happen | POST /message:stream |
GetTask | Fetch a task's current state and artifacts (polling) | GET /tasks/{id} |
ListTasks | List tasks, filterable by context or state | GET /tasks |
CancelTask | Ask the agent to stop work | POST /tasks/{id}:cancel |
SubscribeToTask | Re-attach a stream to an existing task | POST /tasks/{id}:subscribe |
| Push notification config | Create, get, list and delete webhook configs | /tasks/{id}/pushNotificationConfigs |
GetExtendedAgentCard | Fetch the authenticated, more detailed card | GET /extendedAgentCard |
Note that a remote agent may also reply with a plain Message instead of a Task, for quick answers that don't need tracking. Your client should handle both.
Streaming, push notifications and bindings
Because agent work can take a long time, A2A gives clients three ways to follow a task. Pick based on how long the work runs and whether the client can stay connected.
Polling
Call GetTask periodically. Simplest to build and works everywhere, but adds latency and wasted requests.
Streaming (SSE)
SendStreamingMessage or SubscribeToTask returns Server-Sent Events: the task first, then status and artifact updates in order. Best for interactive UIs. Requires capabilities.streaming.
Push notifications
The client registers a webhook URL, and the agent POSTs updates there. Best for server-to-server work that runs for hours. Requires capabilities.pushNotifications.
HTTP/1.1 200 OK
Content-Type: text/event-stream
data: {"task": {"id": "task-77", "contextId": "ctx-9", "status": {"state": "TASK_STATE_WORKING"}}}
data: {"artifactUpdate": {"taskId": "task-77", "contextId": "ctx-9", "artifact": {"artifactId": "a1", "parts": [{"text": "## Visa summary\n"}]}}}
data: {"statusUpdate": {"taskId": "task-77", "contextId": "ctx-9", "status": {"state": "TASK_STATE_COMPLETED"}}}Streams are independent of the task. If a connection drops, the task keeps running, and the client can reconnect with SubscribeToTask. Several clients can watch the same task at once. One caveat from the spec: a reconnecting client may miss some status messages, so anything important should end up in artifacts or task history, not only in transient updates.
Bindings are how the abstract operations map to wire formats. v1.0 defines three official ones, all functionally equivalent, plus rules for custom bindings:
| Binding | Card value | Good fit |
|---|---|---|
| JSON-RPC 2.0 over HTTP | JSONRPC | The original style; easy to proxy and debug |
| gRPC | GRPC | High-throughput internal services, strong typing from the .proto files |
| HTTP+JSON (REST) | HTTP+JSON | Familiar resource-style URLs, plays well with API gateways |
A server lists the bindings it supports in supportedInterfaces, in preference order. The client picks the first one it also supports. Clients send an A2A-Version header so the server can reject versions it doesn't speak.
Security schemes and what v1.0 changed
A2A doesn't invent its own auth. It reuses standard web security, declared in the Agent Card using an OpenAPI-like structure. The supported security schemes are:
- API key, sent in a header, query parameter or cookie.
- HTTP authentication, such as Basic or Bearer tokens.
- OAuth 2.0, including authorization code, client credentials and device code flows.
- OpenID Connect, pointing at a provider's discovery document.
- Mutual TLS, where both sides present certificates.
Credentials are obtained out of band (for example, through a normal OAuth flow) and sent with each request. Inside a task, an agent can ask for more authorization by moving to TASK_STATE_AUTH_REQUIRED, which hands the job of getting a token or human approval back to the client.
If you learned A2A from 2025 tutorials, these are the v1.0 changes to watch for:
| Change | Why it matters |
|---|---|
| Signed Agent Cards using JWS (RFC 7515) over a JCS-canonicalized card (RFC 8785) | A client can cryptographically check that a card came from the claimed provider and wasn't tampered with in transit or in a registry. |
Native tenant field on each interface | One endpoint can host many agents or customers. Clients copy the tenant value from the card into every request. |
| Protocol Buffers as the source of truth, with ProtoJSON as the canonical JSON | One schema generates JSON-RPC, gRPC and REST types consistently. Enums look like TASK_STATE_COMPLETED, and JSON fields are camelCase. |
The kind discriminator was removed | Polymorphism now uses oneof-style fields: a part simply has text, raw, url or data; a response has task or message. |
TaskSubscription renamed to SubscribeToTask; extended card RPC is GetExtendedAgentCard | Update method names when migrating. |
The final flag was removed from status update events, and the task must be the first event in a stream | Clients decide a stream is done by looking at the task state. |
| Modernized OAuth flows | Brings the OAuth options in line with current practice. |
How card signing works
The provider removes the signatures field and default values, canonicalizes the JSON with JCS so every implementation produces identical bytes, then signs it. The protected header carries alg, kid and optionally a jku URL for the public key set. The client repeats the canonicalization and verifies. Canonicalization is the subtle part: without it, harmless differences such as key order or whitespace would break signatures.
Discovery and trust
How does an agent find another agent in the first place? The spec describes three mechanisms:
Well-known URI
Fetch /.well-known/agent-card.json from a domain you already know. Simple and decentralized, and it ties the agent to a domain.
Registries and catalogs
Query a curated directory, often run inside a company or by a platform, to search agents by skill or tag.
Direct configuration
Hard-code the card URL or content. Common for tightly controlled partnerships and internal systems.
Finding an agent is the easy part. Trusting it is harder. A card is a claim, and a remote agent is an opaque system whose output your agent will read and act on. Think about trust in layers:
- 1
Is this card authentic?
Fetch over HTTPS and verify card signatures where present. Pin or allow-list the keys and providers you expect.
- 2
Is this the agent I meant?
Domain, provider and signature together tell you who stands behind the agent. A registry listing alone is not proof.
- 3
Am I authorized, and is it?
Use the declared security schemes. Give each remote agent the narrowest credentials it needs, and authenticate the agents that call you.
- 4
Can I trust what it sends back?
Treat every message and artifact from another agent as untrusted input, just like web content. It may contain prompt injections meant to hijack your agent.
- 5
What happens if it misbehaves?
Set timeouts, cancel runaway tasks, validate structured outputs against a schema, and require human confirmation before acting on high-stakes results.
A signed card is not a safe agent
Signatures prove who published a card, not that the agent behaves well or that its outputs are clean. The OWASP Top 10 for Agentic Applications lists insecure inter-agent communication and cascading failures as distinct risks: one compromised or confused agent can pass bad instructions down a chain. Module 11 covers defenses in depth.
Caching matters too. Cards change rarely, so servers should send Cache-Control and ETag headers, and clients should make conditional requests rather than re-downloading the card before every call.
A2A among its neighbors
A2A isn't the only effort to connect agents. The others mostly solve different problems, and several are complementary. Here's how the main ones compare as of October 2026.
| Protocol | Backed by | Main job | Identity and discovery | Status |
|---|---|---|---|---|
| MCP | Started by Anthropic; now at AAIF | Agent to tools and data (vertical) | OAuth 2.1 with Client ID Metadata Documents; MCP Registry | Widely adopted; 2026-07-28 spec made the core stateless |
| A2A | Started by Google; Linux Foundation, now at AAIF | Agent to agent (horizontal): tasks, messages, artifacts | Agent Cards at well-known URLs, optionally JWS-signed; standard web auth | v1.0 stable; native in major clouds |
| ANP | Open-source community founded by Gaowei Chang | Decentralized agent networking with meta-protocol negotiation | Decentralized identifiers (did:wba) and semantic discovery | Draft; discussed in the W3C AI Agent Protocol Community Group |
| AGNTCY | Launched by Cisco with LangChain and Galileo; Linux Foundation since July 2025 | "Internet of Agents" infrastructure: directory, messaging, identity, observability | OASF schemas for directories; verifiable agent identity; SLIM messaging | Active; 75+ contributing organizations |
| NLWeb | Microsoft (Build 2025) | Turns a website into a natural-language /ask endpoint | Site-level; every instance is also an MCP server | Available, including a managed offering from Cloudflare |
A practical reading of the table: use MCP to give your agent tools, A2A when you hand work to another agent, and NLWeb if you want your website to be queryable by agents. ANP and AGNTCY are worth watching for open, decentralized networks of agents and for infrastructure such as directories and secure messaging, but most production agent-to-agent traffic in 2026 runs on A2A.
MCP and A2A together
A common architecture: your agent exposes itself over A2A to other agents, and internally uses MCP servers for its own tools. Callers see one opaque agent with a card. You can swap internal tools freely without changing your public contract.
Designing an agent other agents can use
Most frameworks now speak A2A natively (Google ADK, Microsoft Agent Framework, Amazon Bedrock AgentCore Runtime, and others), and official SDKs exist for Python, JavaScript, Java, Go and .NET. So the hard part isn't the wire format. It's the design. Here's a checklist for building an A2A agent that other agents can rely on.
- 1
Scope skills narrowly and describe them precisely
Each skill should do one recognizable job. Write descriptions and examples for an LLM reader, and declare accurate input and output media types.
- 2
Return results as artifacts with structure
Put deliverables in artifacts, use
dataparts with a documented shape when callers will parse the result, and keep messages for questions and progress. - 3
Use the interrupted states honestly
Ask for missing information with
TASK_STATE_INPUT_REQUIREDrather than guessing. UseTASK_STATE_REJECTEDfor requests outside your scope, so the caller can route elsewhere. - 4
Support the long haul
If work can take more than a few seconds, return a task early, support streaming and push notifications, and make
GetTaskandCancelTaskwork reliably. - 5
Secure by default
Require authentication, request minimal scopes, sign your Agent Card, and serve per-customer agents through the
tenantfield instead of mixing data. - 6
Treat callers' input as untrusted
Messages from other agents can carry prompt injections. Keep your agent's own powerful tools behind confirmation or policy checks, and never let a caller's text override your instructions.
- 7
Version your contract
Bump the card
versionwhen skills change, keep old skills working during transitions, and use caching headers so clients notice updates. - 8
Make it observable
Log task IDs, context IDs and state transitions end to end. When something goes wrong across three agents and two companies, a shared task ID is how you find it.
Do you even need a second agent?
A2A is the right tool when the other side really is an independent agent, owned by another team or company, or needing its own long-running process. If you control both sides and the work is a simple function, an MCP tool is simpler and cheaper. Module 6 looks at when multi-agent designs pay off.
Key takeaways
- Tools are functions your agent controls; remote agents are opaque peers with their own reasoning, state and timelines. MCP covers the first, A2A the second.
- A2A went from a Google proposal (April 2025) to the Linux Foundation, absorbed IBM's ACP, reached a stable v1.0, and joined the Agentic AI Foundation on August 27, 2026.
- The Agent Card at /.well-known/agent-card.json advertises identity, skills, interfaces and security; v1.0 cards can be signed with JWS over JCS-canonicalized JSON.
- Work happens in tasks with a clear lifecycle, including the interrupted states INPUT_REQUIRED and AUTH_REQUIRED; results belong in artifacts, while messages carry the conversation.
- Follow long tasks by polling, SSE streaming or push notifications, over JSON-RPC, gRPC or HTTP+JSON bindings.
- Discovery is easy and trust is hard: verify cards, use least-privilege auth, and treat everything another agent sends you as untrusted input.
Sources & further reading
- A2A Protocol Specification (latest) — Agent Card, task states, operations, bindings, signing
- A2A joins the Agentic AI Foundation (A2A blog, 2026-08-27)
- Linux Foundation: A2A surpasses 150 organizations (2026-04-09)
- AAIF: A2A v1.0 builder's guide, part 2 — Migration and security changes in v1.0
- Agent2Agent (Wikipedia) — Timeline overview
- TechCrunch: Linux Foundation forms the Agentic AI Foundation
- W3C AI Agent Protocol Community Group — Home of ANP standardization discussions
- AGNTCY documentation
- Neowin: Microsoft unveils NLWeb
- OWASP Top 10 for Agentic Applications