Contents
Map

14 ยท MCP & A2A

The A2A Protocol

View as:

The A2A Protocol

Agent2Agent (A2A) is an open protocol for one agent to delegate work to another - across frameworks, vendors and organisations - without either side exposing its internals. Where MCP connects an agent to tools, A2A connects agents to agents: a client agent discovers a remote agent through its Agent Card, sends it a message, and follows the resulting task through its lifecycle by polling, streaming or push notification. This chapter covers A2A v1.0.

Learning objectives 45 min
By the end of this page you will be able to:
  • Explain when to use A2A rather than MCP or an in-process sub-agent
  • Describe the Agent Card, messages, parts, tasks, artifacts and context, and the task state machine
  • Choose between polling, streaming and push notifications for a task, and between the JSON-RPC, gRPC and HTTP+JSON bindings
  • Secure an A2A integration - authentication schemes, signed Agent Cards, and treating remote agents as untrusted
  • Publish an agent over A2A and call it from another agent with the Python SDK
Prerequisites

Why a Second Protocol?

An MCP server exposes tools: small, well-described operations whose inputs and outputs the calling agent controls. Some counterparts aren't tools. A fraud-investigation agent run by another team, a supplier's procurement agent, a travel agent product - each has its own model, tools, memory and policies, works for minutes or hours, may ask follow-up questions, and must keep its internals private. Treating it as a tool loses all of that.

MCPA2A
Other sideA server exposing tools, resources, promptsAn opaque agent with its own reasoning
Unit of workA tool callA task with a lifecycle
DurationUsually secondsSeconds to days
Mid-work interactionElicitation for a specific inputMulti-turn: the agent can ask for input or authorization
OutputTool resultMessages and artifacts (documents, data, files)
Typical boundaryInside your applicationAcross teams, frameworks and organisations

The two compose: an agent reachable over A2A usually uses MCP servers internally. And inside a single application, a sub-agent is often just a function call (Agent Patterns & Multi-Agent); A2A earns its overhead when the agents are built, deployed or owned separately.

History

DateMilestone
Apr 2025Google announces A2A with 50+ partners
Jun 2025A2A becomes a Linux Foundation project (AWS, Cisco, Google, Microsoft, Salesforce, SAP, ServiceNow)
Aug 2025IBM's Agent Communication Protocol (ACP) merges into A2A
Sep 2025Agent Payments Protocol (AP2) launched as an A2A extension for agent-initiated payments
Mar 2026A2A v1.0: signed Agent Cards, multi-tenancy, multiple protocol bindings, version negotiation
Aug 2026A2A joins the Agentic AI Foundation, alongside MCP

Core Concepts

flowchart LR
    CA["๐Ÿค– Client agent"] -->|"1 GET /.well-known/agent-card.json"| AC["๐Ÿชช Agent Card<br/>skills, endpoint, auth"]
    CA -->|"2 SendMessage / SendStreamingMessage"| RA["๐Ÿค– Remote agent"]
    RA -->|"3 Task: status updates"| CA
    RA -->|"4 Artifacts"| CA

    style AC fill:#e8e0d4,stroke:#c8b89a
    style RA fill:#dde4dc,stroke:#b0c4b0
    style CA fill:#d8dfe8,stroke:#b0bac8
ConceptWhat it is
Agent CardA JSON document describing the agent: name, description, version, provider, skills (id, description, tags, examples, input/output modes), capabilities (streaming, push notifications, extended card), interfaces (URL + protocol binding + version), security schemes and requirements, and optional signatures. Published at https://{domain}/.well-known/agent-card.json or distributed through a registry or configuration
MessageOne turn: a role (user or agent), a messageId, optional contextId and taskId, and parts
PartContent: text, a file (inline bytes or a URL, with media type), or structured data (JSON)
TaskThe unit of work, with a server-generated id and a status; created when the remote agent decides the request needs tracked work (a simple reply can be a plain message)
ArtifactAn output of a task - a document, a dataset, an image - made of parts, possibly streamed in chunks
Context (contextId)Groups related tasks and messages into one conversation

The task lifecycle

stateDiagram-v2
    [*] --> SUBMITTED
    SUBMITTED --> WORKING
    WORKING --> INPUT_REQUIRED: needs more from the client
    INPUT_REQUIRED --> WORKING: client sends a message
    WORKING --> AUTH_REQUIRED: needs authorization
    AUTH_REQUIRED --> WORKING
    WORKING --> COMPLETED
    WORKING --> FAILED
    SUBMITTED --> REJECTED
    WORKING --> CANCELED: CancelTask
    COMPLETED --> [*]
    FAILED --> [*]
    CANCELED --> [*]
    REJECTED --> [*]

COMPLETED, FAILED, CANCELED and REJECTED are terminal; INPUT_REQUIRED and AUTH_REQUIRED are interrupted states that resume when the client responds in the same task.

Operations and update delivery

OperationPurpose
SendMessageStart or continue an interaction; returns a message or a task
SendStreamingMessageSame, with a stream of task, status and artifact events
GetTask, ListTasksRead task state (polling)
CancelTaskRequest cancellation
SubscribeToTaskRe-attach a stream to an existing task
Push notification config (create / get / list / delete)Register a webhook the agent calls on state changes
GetExtendedAgentCardFetch a fuller card after authenticating

Three ways to follow a task: polling GetTask (simple, fine for short tasks), streaming over SSE (live progress while connected), and push notifications to a webhook (long tasks, disconnected clients - the webhook must authenticate the agent's calls and validate URLs to avoid SSRF).

Protocol bindings

The same operations are defined over JSON-RPC 2.0 over HTTP, gRPC and HTTP+JSON (REST-style); an agent lists the bindings it supports as interfaces in its card, and clients pick one they share. Version negotiation lets v0.3 and v1.0 peers interoperate during migration.


Security

A remote agent is a third party. Its outputs are untrusted input to your agent - exactly like tool results (MCP Security) - and your requests may carry your users' data to it.

  • Authentication uses standard schemes declared in the Agent Card: API keys, HTTP auth, OAuth 2.0, OpenID Connect or mutual TLS. Credentials travel in HTTP headers, never in A2A messages.
  • Signed Agent Cards (v1.0) let a client verify a card was issued by the domain owner, defeating fake cards that redirect traffic to an attacker. Verify signatures before trusting a card from a registry or a link.
  • Authorization is the remote agent's job, per skill and per task; the extended card can reveal skills only to authenticated clients.
  • Data minimisation: send only what the task needs; check the remote agent's data handling before sending personal data across an organisational boundary.
  • Treat artifacts as untrusted: validate structured data, never execute returned content, and don't let instructions inside an artifact drive your agent's privileged actions.

A2A in Code

The Python SDK (a2a-sdk, v1.x) provides a server side - you implement an AgentExecutor and publish task events through a TaskUpdater - and a client that resolves the card and streams events. From the lab, which wraps the MCP-backed shop agent:

from a2a.types import AgentCard, AgentInterface, AgentSkill, AgentCapabilities, TaskState

CARD = AgentCard(
    name="Outdoor-gear shop support agent", version="0.3.0",
    description="Resolves order questions, cancellations, address changes and refunds.",
    supported_interfaces=[AgentInterface(url="http://127.0.0.1:9999", protocol_binding="JSONRPC",
                                         protocol_version="1.0")],
    capabilities=AgentCapabilities(streaming=True),
    default_input_modes=["text/plain"], default_output_modes=["text/plain"],
    skills=[AgentSkill(id="order-support", name="Order support", tags=["retail", "orders"],
                       description="Look up, cancel, re-address or refund a customer's orders.")])

class ShopAgentExecutor(AgentExecutor):
    async def execute(self, context: RequestContext, event_queue: EventQueue) -> None:
        if context.current_task is None:                        # publish the task first
            await event_queue.enqueue_event(new_task_from_user_message(context.message))
        updater = TaskUpdater(event_queue, context.task_id, context.context_id)
        await updater.start_work(updater.new_agent_message([new_text_part("Looking into it...")]))
        answer = await run_shop_agent(context.get_user_input())  # the MCP-backed loop
        await updater.add_artifact([new_text_part(answer)], name="reply")
        await updater.complete()

A client run against it prints the lifecycle:

[task] id=b01dcae5 state=TASK_STATE_SUBMITTED
[status] TASK_STATE_WORKING Looking into it...
[status] TASK_STATE_WORKING Tools used: find_customer, list_orders, cancel_order
[artifact] Your order O1002 has been cancelled. A refund of $89.50 will be processed.
[status] TASK_STATE_COMPLETED

Frameworks increasingly expose agents over A2A directly (for example Google ADK, the Microsoft Agent Framework and LangGraph deployments), and cloud agent platforms can host A2A endpoints - see Agent Frameworks.

ProtocolScope
MCPAgent โ†” tools and context
A2AAgent โ†” agent
AP2 (Agent Payments Protocol, an A2A extension)Agent-initiated payments: signed intent, cart and payment mandates
AG-UIAgent โ†” user-interface streaming (events for front ends)

Check Yourself

Check yourself
0 / 5 answered
  1. Where does a client agent find a remote agent's skills, endpoint and auth requirements?
  2. Which task states are interrupted (the task waits for the client) rather than terminal?
  3. A task will take about six hours and the client may disconnect. How should it follow the task?
  4. What threat do signed Agent Cards address?
  5. Your planner agent calls a summarisation step that lives in the same codebase and deploys with it. Should that be A2A?

Exercises

Exercise - Write an Agent Card

Write the Agent Card JSON for an internal "IT help desk" agent with two skills (password reset guidance, laptop request), streaming support, OAuth 2.0 client-credentials authentication for other internal agents, and a JSON-RPC interface.

Solution

Include name, description, version, provider, supportedInterfaces [{url, protocolBinding: "JSONRPC", protocolVersion: "1.0"}], capabilities {streaming: true}, defaultInputModes ["text/plain"], defaultOutputModes ["text/plain", "application/json"], skills with id, name, description, tags and examples, securitySchemes {"oauth": {oauth2 flows: clientCredentials with tokenUrl and scopes}}, and securityRequirements [{"oauth": ["helpdesk.tasks"]}]. Sign it if it will be published beyond your own configuration.

Exercise - MCP or A2A?

Classify each integration and justify: (a) an agent needs to read Jira issues; (b) your sales agent hands a qualified lead to a partner company's onboarding agent, which takes days and asks questions; (c) a coding agent runs the test suite; (d) a travel-booking agent offered by a vendor that your assistant should use for trips.

Solution

(a) MCP - a tool/data source. (b) A2A - opaque agent, long-running, multi-turn, cross-organisation. (c) Neither protocol needed - a local tool (or an MCP server if shared). (d) A2A - a separately operated agent product with its own reasoning; your assistant delegates tasks and receives itineraries as artifacts.

Exercise - Run the A2A part of the lab

Start the lab's A2A server, fetch the Agent Card with curl, and send two requests with the client - one that succeeds and one that the policy should refuse (cancel a shipped order). Compare the task events.

Solution

The card appears at http://127.0.0.1:9999/.well-known/agent-card.json. Both requests produce SUBMITTED โ†’ WORKING โ†’ artifact โ†’ COMPLETED at the protocol level: a policy refusal is a successful task whose artifact explains the refusal. FAILED is reserved for the agent failing to process the task. This distinction - business outcome vs protocol outcome - is worth designing deliberately.

Study Notes

  • A2A = agent โ†” agent for opaque, separately owned agents; MCP = agent โ†” tools; they compose
  • Agent Card at /.well-known/agent-card.json: skills, capabilities, interfaces, security schemes, optional signatures
  • Messages (role, parts: text/file/data), tasks (server ids, lifecycle), artifacts (outputs), contextId (conversation)
  • States: SUBMITTED, WORKING, INPUT_REQUIRED, AUTH_REQUIRED, COMPLETED, FAILED, CANCELED, REJECTED
  • Operations: SendMessage, SendStreamingMessage, GetTask, ListTasks, CancelTask, SubscribeToTask, push config, GetExtendedAgentCard
  • Follow tasks by polling, streaming or push notifications; bindings JSON-RPC, gRPC, HTTP+JSON
  • v1.0 (Mar 2026): signed cards, multi-tenancy, version negotiation; governed by the Agentic AI Foundation since Aug 2026
  • Remote agents are untrusted third parties: authenticate, verify cards, minimise data, validate artifacts

References

Last reviewed: 2026-09

โšกAI-assisted content - always verify, always explore multiple perspectivesยท