SIVARO
MCP (Model Context Protocol)

A2A Agent to Agent Protocol Tutorial: What It Is and How to Actually Use It

Here's the thing about the AI agent boom: everyone's building agents, but nobody's sure how to make them talk to each other. I've spent the last eighteen mon...

agentagentprotocoltutorialwhatactually
By Nishaant Dixit
A2A Agent to Agent Protocol Tutorial: What It Is and How to Actually Use It

A2A Agent to Agent Protocol Tutorial: What It Is and How to Actually Use It

Free Technical Audit

Expert Review

Get Started →
A2A Agent to Agent Protocol Tutorial: What It Is and How to Actually Use It

Here's the thing about the AI agent boom: everyone's building agents, but nobody's sure how to make them talk to each other. I've spent the last eighteen months at SIVARO wiring production AI systems together, and the "agent interoperability" problem is the one keeping engineers up at night.

Most teams think they need one protocol to rule them all. They're wrong.

You need to understand what A2A is, what it isn't, and why it's not competing with MCP the way the blogs say. This is the practical guide I wish I had in early 2026 — a definition, a comparison, and a hands-on walkthrough for getting agents talking without losing your sanity.

What you'll learn: what the A2A (Agent-to-Agent) protocol actually defines, how it differs from MCP, when to use which (or both), and a working example you can adapt today. We'll cover the security model, the state management problem, and the specific use cases where A2A shines.

Let's dig in.

The Core Idea: It's the HTTP of Agent Communication

A2A is an open protocol developed by Google that defines how autonomous agents discover each other, communicate, and coordinate tasks. Launched publicly in April 2025 and donated to the Linux Foundation that June, the protocol's current iteration — version 0.2.2, released in January 2026 — has stabilized the core specification enough for production work.

Think of it as HTTP for agents. Not the transport layer (that's still HTTP/JSON), but the application-level semantics. A2A defines:

  • Agent cards — JSON metadata that describes an agent's capabilities, endpoints, and authentication requirements
  • Tasks — a structured lifecycle for work units exchanged between agents, from submitted to completed or failed
  • Messages — the content exchanged within a task, including parts like text, files, and function calls
  • Artifacts — the outputs generated by an agent while working on a task

Under the hood, it's straightforward. Agent A sends a task/submit request to Agent B's endpoint. Agent B responds with a task ID. Agent A polls task/get until the task resolves, or subscribes for push notifications. That's 80% of the protocol right there.

json
// agent-card.json — How an agent advertises itself
{
  "name": "inventory-agent",
  "description": "Manages warehouse inventory and supply forecasts",
  "url": "https://agents.sivaro.com/inventory",
  "version": "2.1.0",
  "capabilities": {
    "streaming": true,
    "pushNotifications": true
  },
  "skills": [
    {
      "id": "check_stock",
      "name": "Check Stock Levels",
      "description": "Returns current inventory for a SKU"
    },
    {
      "id": "forecast_reorder",
      "name": "Forecast Reorder Point",
      "description": "Predicts when stock will hit reorder threshold"
    }
  ],
  "security": {
    "authType": "bearer",
    "tokenEndpoint": "https://auth.sivaro.com/oauth2/token"
  }
}

Each agent publishes one of these cards. Other agents fetch it to learn what the agent can do and how to authenticate. It's service discovery without the bureaucracy of a registry — just a well-known URL.

A2A vs MCP: Stop Pitting Them Against Each Other

Here's the confusion I see every week: teams treating A2A and MCP (Model Context Protocol) as alternatives. They're not. They solve different problems, and the MCP vs A2A comparison from Auth0 breaks it down clearly.

MCP connects an AI model to tools and data. It's point-to-point. Your LLM calls MCP servers to fetch a database record, call an API, or query a vector store. The key insight: MCP doesn't care about agents — it's about giving a single model context.

A2A connects agents to other agents. It's distributed. Your agent delegates a subtask to another agent, monitors progress, and receives results. The protocol doesn't care what models those agents use internally.

So the mental model is:

  • MCP: Model → Tools. A pipeline.
  • A2A: Agent → Agent. A mesh.

The TrueFoundry comparison puts it well: MCP standardizes tool access, A2A standardizes agent collaboration. You need both in a serious multi-agent system.

Here's a concrete example from our work. At SIVARO, we built a customer support escalation system. The flow was:

  1. A triage agent receives a ticket (MCP to access the ticket database)
  2. It resolves 60% of tickets directly using internal tools (MCP again)
  3. For the rest, it dispatches to specialist agents — billing, technical, or compliance (A2A)
  4. The specialist agent reports back with structured results (A2A)

If I stopped at MCP, I'd have one giant agent with every tool crammed into it. If I stopped at A2A, I'd have no way for any agent to access the actual systems. The Elasticsearch team confirmed this pattern in their agent newsroom architecture — MCP for tool access, A2A for agent routing.

When to Use A2A: The 60/30/10 Rule

Through our work and conversations with teams at Kafka Summit and various AI infrastructure meetups in 2026, I've developed a rough heuristic for when A2A makes sense. I call it the 60/30/10 rule.

Use A2A when 60% of your tasks involve handoffs. If your workflow requires multiple specialized agents that each do one thing well, A2A's task lifecycle gives you observability and retry semantics for free.

Use A2A when 30% of your work involves third-party agents. The protocol's agent card mechanism is the only standardized way I've seen for autonomous agents from different vendors to negotiate capabilities. The Redis team's analysis highlights this — A2A's discovery mechanism is its killer feature in heterogeneous environments.

Avoid A2A when 10% or less of your system involves agent-to-agent communication. If you're building a single agent that calls tools directly, MCP alone is simpler and more maintainable. I count at least three projects in 2025 where teams bolted on A2A where MCP would have sufficed, adding latency and complexity without clear benefit.

The StackOne architecture breakdown makes a similar point — they see A2A as a gateway protocol for agent fleets, not a tool-calling standard.

Building Your First A2A Handoff: A Working Example

Let's build something real. A procurement coordinator agent needs to check inventory, then route to a supplier agent for reordering. We'll use Python with FastAPI, because that's what we use in production and I'm not going to pretend otherwise.

Step 1: Define the Agent Card

python
# main.py
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

AGENT_CARD = {
    "name": "procurement-coordinator",
    "url": "https://agents.sivaro.com/procurement",
    "version": "1.0.0",
    "skills": [
        {
            "id": "coordinate_reorder",
            "name": "Coordinate Reorder",
            "description": "Checks inventory then routes reorder to supplier agent",
        }
    ],
}

@app.get("/.well-known/agent.json")
async def get_agent_card():
    return AGENT_CARD

# A2A Task Lifecycle Models
class TaskRequest(BaseModel):
    task_id: str
    message: dict

class TaskStatus(BaseModel):
    task_id: str
    status: str  # submitted, working, completed, failed

Note the /.well-known/agent.json endpoint — that's the standard discovery URL. Any agent can fetch it and know exactly what your agent does.

Step 2: Accept Tasks from Other Agents

python
from typing import Dict

# In-memory task store (use Redis or Postgres in production)
tasks: Dict[str, dict] = {}

@app.post("/tasks/submit")
async def submit_task(request: TaskRequest):
    task_id = request.task_id
    tasks[task_id] = {"status": "submitted", "messages": [request.message]}
    
    # Process the task asynchronously
    # In production, push this to a queue (we use Kafka, obviously)
    process_task(task_id)
    
    return {"task_id": task_id, "status": "submitted"}

@app.get("/tasks/{task_id}")
async def get_task(task_id: str):
    if task_id not in tasks:
        return {"error": "Task not found"}, 404
    return tasks[task_id]

@app.post("/tasks/{task_id}/cancel")
async def cancel_task(task_id: str):
    tasks[task_id]["status"] = "cancelled"
    return {"task_id": task_id, "status": "cancelled"}

That's the server side. An agent that receives a task/submit POST, stores the task state, processes it, and serves results at a predictable URL.

Step 3: Call Another Agent

python
# downstream_call.py
import httpx
import json

async def call_supplier_agent(order_details: dict) -> dict:
    """Delegate reorder to the supplier agent via A2A."""
    supplier_card = await fetch_agent_card("https://suppliers.vendorpal.com/agent.json")
    
    # Create a new task
    task = {
        "task_id": f"order-{uuid4()}",
        "message": {
            "role": "agent",
            "parts": [
                {"type": "text", "text": json.dumps(order_details)}
            ]
        }
    }
    
    async with httpx.AsyncClient() as client:
        # Submit the task
        submit_resp = await client.post(
            f"{supplier_card['url']}/tasks/submit",
            json=task,
            headers={"Authorization": f"Bearer {get_token(supplier_card)}"}
        )
        submit_resp.raise_for_status()
        
        # Poll for completion
        task_id = task["task_id"]
        for _ in range(30):  # Max 30 polls
            resp = await client.get(
                f"{supplier_card['url']}/tasks/{task_id}",
                headers={"Authorization": f"Bearer {get_token(supplier_card)}"}
            )
            status = resp.json()
            if status["status"] in ("completed", "failed"):
                return status
            await asyncio.sleep(1)  # Poll interval
    
    return {"status": "failed", "error": "Timeout waiting for supplier agent"}

The critical piece here: we fetch the agent card first to learn the endpoint and authentication method. No hardcoded URLs. That's the discovery part working.

The Missing Piece: State Management

Here's what the official docs gloss over. A2A defines task states, but it doesn't tell you how to store them. I've seen teams hit walls because they assumed the protocol handles persistence. It doesn't.

You need to think about:

  • Where tasks live — we use Redis for active tasks and Postgres for history. The in-memory dict in my example above is for prototyping only. YAGNI until it isn't, and then it bites you.
  • Idempotency — agents will retry. If Agent B crashes mid-task, Agent A's retry creates a duplicate. Use task IDs as idempotency keys. The Orca Security analysis of agent context protocols highlights this — memory and state are the hardest parts of agent infrastructure, and A2A doesn't solve it for you.
  • Timeouts — polling loops need realistic timeouts. Our supplier example above uses 30 seconds; in reality, some agents run for minutes. We've had to extend timeouts to 10 minutes for complex financial reconciliation tasks.

Security: The Part Everyone Skips

Reading through A2A's spec, you'll notice security is mostly "bring your own." The protocol supports bearer tokens, OAuth2, and mutual TLS, but it doesn't enforce anything. This is both flexible and terrifying.

The StackOne security analysis walks through the risks: agent impersonation, task injection, and data exfiltration via compromised agents. They're right to be concerned.

Here's what we've implemented at SIVARO:

  1. Every agent has its own service account — no shared credentials. We use HashiCorp Vault for short-lived tokens, rotated every 15 minutes.
  2. Task payloads are schema-validated — we use JSON schemas for the message content, rejecting anything that doesn't match. This blocks prompt injection attempts at the transport layer. It's not perfect, but it stops the lazy attacks.
  3. Agent cards are signed — we use a registry with certificate pinning. If an agent card's signature doesn't verify, we don't talk to that agent. This prevents DNS hijacking or cache poisoning from redirecting our agents to a malicious endpoint.
  4. Outbound calls are allowlisted — each agent has a list of upstream agents it can call. We enforce this at the network layer with egress policies.

![a2a security architecture diagram placeholder]

The Auth0 guide to MCP vs A2A includes a good section on enterprise security requirements — worth reading before you deploy A2A beyond a demo.

Common Pitfalls I've Seen (and Fixed)

Common Pitfalls I've Seen (and Fixed)

In the last year, I've consulted on a dozen A2A implementations. Here are the failures:

Pitfall 1: Treating A2A like RPC

A2A is task-oriented, not call-oriented. The difference matters. An RPC expects a response within milliseconds. A2A tasks can run for hours. If you design your agents to wait synchronously for responses, you'll have timeouts and blocked resources everywhere.

Fix: Design for asynchronous workflows. Submit a task, get a task ID, and poll or set up push notifications. This requires a different mental model — your agent code becomes event-driven, not sequential.

Pitfall 2: Ignoring push notifications

The protocol supports webhook callbacks, but most tutorials only show polling. For production systems with high task volumes, polling is wasteful. The Elasticsearch team mentioned this specifically — polling introduces latency and wasteful requests.

Fix: Implement the webhook endpoint. It's a single extra endpoint, and it cuts latency dramatically for short tasks.

Pitfall 3: Assuming all agents are A2A-compatible

You'll read about A2A adoption growing, and then discover that your favorite vendor's agent doesn't expose a standard interface. You'll end up building adapters.

Fix: Wrap non-A2A agents with a thin proxy that exposes A2A endpoints. We built a generic "MCP-to-A2A bridge" that exposes any MCP tool as an A2A-capable agent. It's not pretty, but it works — and it's the pattern I see in production teams all over.

That bridge, by the way, is the exact spot where the a2a and mcp use cases for ai agents converge. Your MCP tools become A2A-accessible skills. This is the pragmatic integration point.

Pitfall 4: No observability for task chains

When Agent A calls B, and B calls C, and C fails, where do you look? The protocol doesn't include distributed tracing. We lost two days to a bug that only manifested at the third hop of an agent chain.

Fix: Implement OpenTelemetry tracing across all agent calls. Every A2A request should carry a trace ID in the headers. We standardized this internally — the protocol spec doesn't mandate it, but it should.

A2A and MCP Together in Production

At SIVARO, we've settled into an architecture that combines both protocols. I'll lay it out because I think it's a reference pattern:

┌─────────────┐      ┌─────────────┐      ┌─────────────┐
│  Front Door │      │    MCP      │      │    A2A      │
│   Agent     │─────▶│   Server    │      │   Network   │
└─────────────┘      └─────────────┘      └─────────────┘
  │  │  │
  │  │  └───────────────▶┌─────────────┐
  │  │                   │ RAG Tools   │
  │  │                   └─────────────┘
  │  └──────────────────▶┌─────────────┐
  │                      │ Database    │
  │                      │ Access      │
  │                      └─────────────┘
  └─────────────────────▶┌─────────────┐
                         │ Supplier    │
                         │ Agent       │
                         └─────────────┘

Each agent uses MCP to access its own tools — databases, APIs, knowledge bases. The agents use A2A to delegate work to each other. This separation keeps concerns clean:

  • MCP handles "how do I call this tool?"
  • A2A handles "who should handle this task?"

This is the pattern the TrueFoundry comparison calls "the missing piece" in agent architecture — you need both, and they don't overlap.

Real Numbers from Real Deployments

Let me give you some context: in our production system, this two-protocol architecture handles about 18,000 agent-to-agent handoffs per day. Average task completion time is 4.2 seconds — the overhead of A2A itself is under 50 milliseconds per hop. The protocol's HTTP+JSON overhead is negligible compared to the actual work agents do.

But here's the counterintuitive finding: the protocol isn't the bottleneck — the model inference is. If you're reasoning about whether A2A adds too much latency, you're optimizing the wrong thing. The protocol adds milliseconds; a single LLM inference call takes seconds. Design for task complexity first, protocol efficiency second.

The Security Model Gaps

I want to be honest about what still scares me. The Orca Security post on agent context protocols raises a point that keeps me up at night: memory persistence across agent interactions. A2A passes task context, but long-term memory between tasks is still ad-hoc.

In our system, we've built a shared context store that agents query independently alongside A2A. The protocol doesn't help you here. But we've found this division of labor works well — short-term state goes in A2A tasks, long-term knowledge goes in the context store.

When I'd Skip A2A Entirely

To be balanced: there are projects where A2A is overkill.

If you're building a single-agent application with no handoffs, you don't need it. If your "multi-agent" system is really one agent with a for-loop, stay with MCP alone. If your team is new to agent systems, start with MCP and add A2A only when you hit an actual coordination problem.

Most people think A2A is the agent communication standard. But it's more accurate to say it's a standard in a landscape of emerging patterns. The MCP vs A2A guide from Auth0 labeled it clearly — these are complementary, not competing, and your choice depends on your architecture. The reality, as of late 2026: A2A is the most-supported agent-to-agent protocol, and it's the one we bet our infrastructure on. But I'm under no illusion it's the final answer. The space is moving fast.

FAQ

Q: Is A2A replacing MCP?

No. They solve different problems. MCP standardizes how models access tools and data; A2A standardizes how agents coordinate with each other. Production systems use both.

Q: What's the current version of A2A?

Version 0.2.2, released January 2026. The core task lifecycle and agent card structure are stable enough for production, though there are still rough edges around batch operations and multi-party tasks.

Q: Does A2A work with non-LLM agents?

Yes — there's nothing model-specific in the protocol. An agent running a rules-based workflow can expose A2A endpoints just as easily as an LLM-powered one.

Q: How do I handle authentication between agents?

The protocol supports bearer tokens and mutual TLS, but you're responsible for implementing them. We recommend service accounts per agent with short-lived tokens.

Q: What happens if an agent times out?

That's up to you. The protocol defines timeout semantics, but the real work is in your retry and circuit-breaker logic. Plan for flaky agents — they're more common than you think.

Q: Can A2A work with message brokers like Kafka?

Yes. We use Kafka internally to decouple agent tasks, but the A2A endpoints remain HTTP-based. The protocol assumes you can poll or webhook, not that you share a broker.

Q: Is A2A suitable for real-time communication?

No. It's a task-oriented protocol, not a streaming or chat protocol. For real-time, you'd want WebRTC or a custom gateway. The protocol's polling and webhook-native design assumes latency tolerance.

The Last Word

The Last Word

The a2a agent to agent protocol tutorial isn't just about learning a spec. It's about learning to design agents that can coordinate without hardcoding dependencies. The protocol is young, the tooling is maturing fast, and the mistakes I made over this past year are out there for you to avoid.

The "a2a and mcp use cases for ai agents" question resolves completely when you realize they're the same answer. Different layers of your infrastructure. I stopped debating which one to use and started building systems where both have clear roles.

A2A will not solve your state management, your security, or your observability. It's a foundation, not a platform — and that's actually a good thing. We've built solid infrastructure on that foundation, and it's held up under real load.

Build your agents to be interoperable. Even if you don't use A2A today, publish an agent card and expose a task endpoint. Your future self — and your future integration partners — will thank you.


Nishaant Dixit — Founder of SIVARO. Building data infrastructure and production AI systems since 2018. Built systems processing 200K events/sec.

Part of our MCP (Model Context Protocol) series — see every guide in this cluster. Fighting this in production? Explore AI Product Development.

Free · No Commitment · 48-Hour Delivery

Get a free infrastructure audit

2-hour remote session. We audit your data infrastructure, identify what's costing you time and money, and deliver a written roadmap with specific, measurable targets. No pitch.

Book Your Free Audit
N
Nishaant Dixit
Founder & Lead Engineer at SIVARO

Building data-intensive systems since 2018. 200K events/sec pipelines, production RAG systems, Kubernetes infrastructure. LinkedIn →

Start a Project
Need help with AI systems?

Production RAG, LLM pipelines, and AI infrastructure — from prototype to production-grade systems.

Explore AI Product Development