Skip to content

3.A2A

👉 #AI #LLM #Agent #SystemDesign #Security

I. A2A (Agent-to-Agent Protocol)

📅 2026-04-28 CDT; Claude Opus 4.6 📎 A2A Official Specification 📎 A2A GitHub Repository 📎 A2A Python SDK 📎 Google Codelab: A2A Purchasing Concierge 📎 A2A Protocol Guide (codilime) 📎 A2A Protocol Guide (letsdatascience) 📎 AWS Bedrock A2A Contract 📎 Microsoft Semantic Kernel + A2A

1. Overview

1.1. Definition & Why
  • A2A (Agent-to-Agent) is an open protocol that lets AI Agents built by different vendors and frameworks discover, communicate, and collaborate with each other.
  • Released by Google at Google Cloud Next '25 on April 9, 2025 with 50+ launch partners; donated to the Linux Foundation in June 2025; by mid-2026 it has 150+ supporting organizations (AWS, Microsoft, Cisco, Salesforce, SAP, ServiceNow, etc.).
  • Core metaphor: the "HTTP of AI Agents". Just as HTTP standardized browser-server communication, A2A standardizes Agent-to-Agent communication.
  • Pain solved: the Agent-silo problem.
  • Without A2A: every Agent is a black box; you can't know what other Agents can do; every integration is custom engineering.
  • With A2A: Agents declare capabilities via an Agent Card and delegate tasks via a standard protocol — cross-organization, cross-vendor collaboration becomes possible.
  • Analogy: before HTTP, every networked application had a custom protocol. After HTTP, any browser could access any website.
  • Technical essence: a stateful task protocol over JSON-RPC 2.0 + HTTP/HTTPS, with SSE streaming and Push Notification asynchronous callbacks.
  • Relationship with MCP — complementary, not competitive:
  • MCP: vertical integration (Agent ↔ Tool) — solves "how does an Agent use tools".
  • A2A: horizontal integration (Agent ↔ Agent) — solves "how does an Agent collaborate with other Agents".
  • Both are now under the Linux Foundation Agentic AI Foundation (AAIF); production systems typically use both.
1.2. Features & Use Cases
(1) Core Features
Feature Description
Opaque Agents Internals not exposed; Agents interact as black boxes via standard interfaces
Agent Card A JSON "business card" declaring skills, input/output formats, and authentication
Task Lifecycle Standard state machine (submitted → working → completed/failed); supports long-running tasks
Streaming Real-time progress updates and incremental results via SSE
Push Notification Webhook-based notifications after disconnection
Multi-modal Text, images, audio, video, files — multiple content types supported
Enterprise Security OAuth 2.0, API Key, JWT, OpenID Connect — enterprise-grade auth
Vendor Neutral Linux Foundation governance, 150+ organizations
(2) Typical Use Cases
  • Cross-department workflow orchestration: a Sales Agent delegates contract review to a Legal Agent, then payment processing to a Finance Agent.
  • Multi-Agent collaborative analysis: a Data Agent collects data, a Stats Agent models, a Visualization Agent produces the report.
  • Enterprise service integration: HR Agent + IT Agent collaborate on new-hire onboarding (account creation, equipment, permissions).
  • Supply-chain coordination: Procurement Agent negotiates with a Supplier Agent on price; a Logistics Agent arranges delivery.
  • Customer-service escalation: when a frontline customer-service Agent can't resolve, delegate to a specialist Agent.
  • Code-development collaboration: Coding Agent writes code, Testing Agent runs tests, Deploy Agent ships to production.
1.3. Competitors & Alternatives
Protocol/Approach Sponsor Position Pros Cons
A2A Google → AAIF Agent ↔ Agent (horizontal) 150+ orgs, enterprise security, task lifecycle New (2025-04); production deployment still early
MCP Anthropic → AAIF Agent ↔ Tool (vertical) De-facto standard, 97M+ downloads, 10K+ Servers Doesn't handle Agent-to-Agent comms
ACP (Agent Communication) IBM and community Agent-to-Agent comms Community-driven, flexible Low adoption; no big-vendor backing
ANP (Agent Network Protocol) Community Decentralized Agent network Decentralized, DID identity Experimental; tiny ecosystem
LangGraph / CrewAI Frameworks In-framework multi-Agent orchestration Smooth dev experience, fast prototyping Framework-locked; not cross-vendor
Custom REST/gRPC Each team Point-to-point integration Full control Every integration is custom; doesn't scale
  • Key distinctions:
  • A2A vs MCP: A2A is the diplomatic protocol between Agents; MCP is the driver an Agent uses to operate tools. See 4.Protocol/2.MCP.md §1.3.
  • A2A vs ACP: similar position, but A2A has Google + 150 orgs behind it; ACP is more of a community experiment.
  • A2A vs in-framework orchestration: LangGraph/CrewAI work best for multi-Agent setups inside the same framework; A2A works best across frameworks, organizations, and vendors.

2. Concept, Component, & Architecture

2.1. Key Concepts
(1) Agent Card — the Agent's "business card"
  • Every A2A Server must expose an Agent Card at /.well-known/agent.json.
  • The Agent Card is a JSON capability declaration: name, description, skills, input/output formats, auth.
  • The Client reads the Agent Card to discover and select an Agent — like a fusion of DNS and API documentation.
  • Core fields: json { "name": "Recipe Agent", "description": "Helps users find and customize recipes", "url": "https://recipe-agent.example.com", "version": "1.0.0", "provider": { "organization": "FoodTech Inc" }, "capabilities": { "streaming": true, "pushNotifications": true }, "authentication": { "schemes": ["OAuth2"] }, "defaultInputModes": ["text/plain", "application/json"], "defaultOutputModes": ["text/plain", "image/png"], "skills": [ { "id": "find-recipe", "name": "Find Recipe", "description": "Search recipes by ingredients or cuisine", "tags": ["cooking", "search"], "examples": ["Find Italian pasta recipes with mushrooms"] } ] }
  • Design philosophy: Agents are opaque. The Client doesn't need to know which framework or LLM is inside — it only needs the Agent Card.
(2) Task — the unit of collaboration
  • The most central concept in A2A: a unit of work delegated from a Client to a Server.
  • Every Task has a unique ID and follows a standard state machine.
  • Task state machine: submitted → working → completed ↓ ↑ input-required ─────┘ ↓ failed / canceled / rejected
  • States:
State Description
submitted Task submitted, waiting to be processed
working Task is processing
input-required Server needs additional input from the Client (multi-turn)
auth-required Additional authentication needed
completed Successfully completed
failed Execution failed
canceled Canceled by the Client
rejected Rejected by the Server
(3) Message & Part — the communication content
  • Message: an exchange between Client and Server, with role (user/agent) and parts array.
  • Part: the content units of a Message; supports multiple types:
Part type Description Example
TextPart Plain text Natural-language message
FilePart File content (inline bytes or URI) Image, PDF, source file
DataPart Structured JSON data Form data, API response
  • Multi-modal: a single Message can contain multiple Parts of different types — text + image + structured data combined.
(4) Artifact — the task output
  • An Artifact is a result produced during Task execution, stored separately from Messages.
  • A single Task can produce multiple Artifacts (e.g., a report + a chart + a data file).
  • Artifacts are also composed of Parts; multi-modal supported.
  • Design intent: separate "the conversation" (Message) from "the deliverable" (Artifact) for clean result extraction.
(5) Streaming & Async — Two delivery modes
  • Streaming (SSE): Client holds an HTTP connection; Server pushes progress updates and incremental results via Server-Sent Events.
  • Best for: short-to-medium tasks where the Client is actively waiting.
  • Event types: TaskStatusUpdateEvent, TaskArtifactUpdateEvent.
  • Push Notification (Webhook): Client disconnects; Server calls back via webhook on status change.
  • Best for: long-running tasks (minutes to hours); Client doesn't need to stay online.
  • Flow: Client sets a pushNotification URL → Server POSTs to it on completion.
(6) Five Design Principles
  1. Agentic Capabilities: don't degrade to simple APIs — support multi-turn negotiation, long tasks, multi-modality.
  2. Opaque Agents: don't require exposing internals; Agents interact as black boxes.
  3. Built on Existing Standards: HTTP, JSON-RPC 2.0, SSE, OAuth — no reinventing wheels.
  4. Security First: enterprise-grade auth, authorization, audit.
  5. Long-Running Tasks: tasks may run seconds to hours, with full lifecycle management.
2.2. Core Components
(1) A2A Client
  • The party initiating task requests — typically an "orchestrator Agent" or a "user proxy".
  • Responsibilities: discover Agents (read Agent Cards), send tasks, receive results, handle multi-turn interaction.
  • A single Client can interact with many Servers simultaneously to orchestrate multi-Agent workflows.
(2) A2A Server
  • The party that receives and executes tasks — an Agent with specific capabilities.
  • Responsibilities: expose an Agent Card, accept tasks, execute, return results / request input.
  • The Server can use any framework internally (LangChain, CrewAI, AutoGen, custom, etc.) — opaque to the Client.
(3) Agent Card
  • The capability-declaration file, hosted at /.well-known/agent.json.
  • Includes name, description, skill list, I/O formats, auth, capability flags (streaming, pushNotifications).
  • The basis for Agent discovery and selection.
(4) Task Manager
  • The Server-side component managing Task lifecycles.
  • Responsibilities: create Tasks, transition states, store Messages and Artifacts, handle cancellations.
(5) JSON-RPC Methods (API endpoints)
Method Description
message/send Send message and create/continue a Task (sync)
message/stream Send message and receive responses via SSE
tasks/get Query current state and history of a Task
tasks/cancel Cancel a running Task
tasks/pushNotification/set Set the Push Notification webhook
tasks/pushNotification/get Query current Push Notification config
tasks/resubscribe Re-subscribe to a Task's SSE stream
2.3. Architecture & Design
(1) Overall Architecture
graph TB
  subgraph Client["Orchestrator / User Agent (A2A Client)"]
    CC1["Agent Card Cache"]
    CC2["Agent Card Cache"]
    CC3["Agent Card Cache"]
    CC4["Agent Card Cache"]
  end

  subgraph SA["A2A Server A (Sales)"]
    TA["Agent Executor"]
  end
  subgraph SB["A2A Server B (Legal)"]
    TB["Agent Executor"]
  end
  subgraph SC["A2A Server C (Finance)"]
    TC["Agent Executor"]
  end
  subgraph SD["A2A Server D (HR)"]
    TD["Agent Executor"]
  end

  CC1 -->|HTTPS| SA
  CC2 -->|HTTPS| SB
  CC3 -->|HTTPS| SC
  CC4 -->|HTTPS| SD

  SA --> CRM["CRM System"]
  SB --> CDB["Contract DB"]
  SC --> PAY["Payment API"]
  SD --> HR["HR System"]
(2) Task Interaction Flow
sequenceDiagram
  participant C as A2A Client (Orchestrator)
  participant S as A2A Server (Specialist Agent)

  C->>S: GET /.well-known/agent.json
  S-->>C: Agent Card (skills, auth, capabilities)

  C->>S: message/send {task_id, message: "Analyze Q3 sales data"}
  S-->>C: Task {id, status: "working"}

  Note over S: Agent is processing...

  S-->>C: Task {status: "input-required", message: "Please specify the region"}
  C->>S: message/send {task_id, message: "APAC"}

  Note over S: Continuing...

  S-->>C: Task {status: "completed", artifacts: [report, chart]}
(3) Streaming Flow
sequenceDiagram
  participant C as A2A Client
  participant S as A2A Server

  C->>S: message/stream {message: "Generate the quarterly report"}
  Note over C,S: SSE connection established

  S-->>C: SSE: TaskStatusUpdateEvent {state: "working"}
  S-->>C: SSE: TaskArtifactUpdateEvent {part: "Chapter 1..."}
  S-->>C: SSE: TaskArtifactUpdateEvent {part: "Chapter 2..."}
  S-->>C: SSE: TaskStatusUpdateEvent {state: "completed"}

  Note over C,S: SSE connection closed
(4) A2A and MCP Co-architecture
graph TB
  User["User / Application"]
  User --> Orch

  subgraph Orch["Orchestrator Agent"]
    A2AClient["A2A Client (delegates tasks)"]
    MCPClient1["MCP Client (calls tools)"]
  end

  subgraph Specialist["Specialist Agent (A2A Server)"]
    MCPClient2["MCP Client"]
    MCPClient2 -->|MCP| MCPDB["MCP Server (Database)"]
  end

  MCPServer["MCP Server (GitHub)"]

  A2AClient -->|A2A| Specialist
  MCPClient1 -->|MCP| MCPServer
  • The Orchestrator delegates high-level tasks to Specialist Agents over A2A.
  • The Specialist Agent uses MCP internally to call concrete tools (DB, APIs).
  • Two protocols, distinct responsibilities: A2A handles "who does it"; MCP handles "how it's done".
2.4. Eco-system
(1) Official SDKs
Language Repo Install
Python github.com/google/a2a-python pip install a2a-sdk
TypeScript Community implementations npm install a2a-sdk
Go Official SDK go get
Java Official SDK Maven/Gradle
JavaScript Official SDK npm install
(2) Supported Platforms & Frameworks
Platform / Framework Integration
Google ADK (Agent Dev Kit) Native, first-class support
Google Cloud Agent Engine Hosted A2A Server
Amazon Bedrock AgentCore Native A2A support (Runtime layer)
Microsoft Semantic Kernel Plugin integration
LangChain / LangGraph Community adapter
CrewAI Community adapter
AutoGen Community adapter
(3) Governance & Community
Org / Resource Description
Linux Foundation AAIF Governance body; same as MCP
150+ supporting organizations AWS, Microsoft, Cisco, Salesforce, SAP, etc.
Agent Payments Protocol (AP2) A2A's commercial extension; 60+ payment orgs (Mastercard etc.)
Google Agent Registry Agent Card registration and discovery
a2a-protocol.org Official spec website

3. Install, Configure, Secure, & Cheatsheets

3.1. A2A Server Development — Python
(1) Install
# Official SDK
pip install a2a-sdk

# Community library (simpler API)
pip install python-a2a

# Google ADK (includes A2A)
pip install google-adk
(2) Minimal Server (Official SDK)
# server.py
import uvicorn
from a2a.server.apps import A2AStarletteApplication
from a2a.server.agent_execution import AgentExecutor
from a2a.server.request_handlers import DefaultRequestHandler
from a2a.types import AgentCard, AgentSkill, TaskState, Message, Part, TextPart

# Define the Agent Card
agent_card = AgentCard(
    name="Echo Agent",
    description="A simple agent that echoes back messages",
    url="http://localhost:9000",
    version="1.0.0",
    skills=[
        AgentSkill(
            id="echo",
            name="Echo",
            description="Echoes back the user's message",
            tags=["demo", "echo"],
            examples=["Say hello"]
        )
    ],
    defaultInputModes=["text/plain"],
    defaultOutputModes=["text/plain"],
    capabilities={"streaming": False, "pushNotifications": False}
)

# Implement Agent logic
class EchoAgentExecutor(AgentExecutor):
    async def execute(self, context, event_queue):
        # Get user input
        user_message = context.get_user_input()
        # Return result
        await event_queue.enqueue_event(
            TaskState.completed,
            message=Message(
                role="agent",
                parts=[TextPart(text=f"Echo: {user_message}")]
            )
        )

# Build the app
handler = DefaultRequestHandler(
    agent_card=agent_card,
    agent_executor_factory=lambda: EchoAgentExecutor()
)
app = A2AStarletteApplication(agent_card=agent_card, http_handler=handler)

if __name__ == "__main__":
    uvicorn.run(app.build(), host="0.0.0.0", port=9000)
# Run
python server.py

# Verify Agent Card
curl http://localhost:9000/.well-known/agent.json | python -m json.tool

# Send a Task
curl -X POST http://localhost:9000/ \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "message/send",
    "params": {
      "message": {
        "role": "user",
        "parts": [{"type": "text", "text": "Hello A2A!"}]
      }
    }
  }'
(3) Simplified Community Library (python-a2a)
# simple_server.py
from python_a2a import A2AServer, AgentCard, skill, run_server

class MyAgent(A2AServer):
    def get_agent_card(self) -> AgentCard:
        return AgentCard(
            name="Helper Agent",
            description="A helpful assistant agent",
            skills=[
                skill(
                    id="answer",
                    name="Answer Questions",
                    description="Answers general questions"
                )
            ]
        )

    def handle_task(self, task):
        user_msg = task.get_user_message()
        task.complete(f"You said: {user_msg}")
        return task

if __name__ == "__main__":
    run_server(MyAgent(), port=9000)
3.2. A2A Client Development — Python
# client.py
import httpx
import json

A2A_SERVER_URL = "http://localhost:9000"

# 1. Discover Agent (read Agent Card)
async def discover_agent():
    async with httpx.AsyncClient() as client:
        resp = await client.get(f"{A2A_SERVER_URL}/.well-known/agent.json")
        agent_card = resp.json()
        print(f"Agent: {agent_card['name']}")
        print(f"Skills: {[s['name'] for s in agent_card['skills']]}")
        return agent_card

# 2. Send a Task
async def send_task(message: str):
    payload = {
        "jsonrpc": "2.0",
        "id": 1,
        "method": "message/send",
        "params": {
            "message": {
                "role": "user",
                "parts": [{"type": "text", "text": message}]
            }
        }
    }
    async with httpx.AsyncClient() as client:
        resp = await client.post(A2A_SERVER_URL, json=payload)
        result = resp.json()
        return result

# 3. Streaming receive (SSE)
async def stream_task(message: str):
    payload = {
        "jsonrpc": "2.0",
        "id": 1,
        "method": "message/stream",
        "params": {
            "message": {
                "role": "user",
                "parts": [{"type": "text", "text": message}]
            }
        }
    }
    async with httpx.AsyncClient() as client:
        async with client.stream("POST", A2A_SERVER_URL, json=payload) as resp:
            async for line in resp.aiter_lines():
                if line.startswith("data:"):
                    event = json.loads(line[5:])
                    print(f"Event: {event}")
3.3. Google ADK Integration
# adk_a2a_server.py
from google.adk.agents import Agent
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService

# Define an Agent
agent = Agent(
    name="research_agent",
    model="gemini-2.5-pro",
    instruction="You are a research assistant. Help users find information.",
    tools=[]  # Add MCP Tools here
)

# Create the Runner (auto-exposes the A2A endpoints)
runner = Runner(
    agent=agent,
    app_name="research-app",
    session_service=InMemorySessionService()
)

# The runner auto-publishes the Agent Card at /.well-known/agent.json
# and handles message/send, message/stream, etc.
3.4. Scripts & Tools
(1) Agent Card Validator
#!/bin/bash
# validate_agent_card.sh -- validate an A2A Server's Agent Card
SERVER_URL=${1:-"http://localhost:9000"}

echo "=== Fetching Agent Card ==="
CARD=$(curl -s "${SERVER_URL}/.well-known/agent.json")

if [ $? -ne 0 ]; then
    echo "ERROR: Cannot reach ${SERVER_URL}"
    exit 1
fi

echo "$CARD" | python3 -c "
import json, sys
card = json.load(sys.stdin)
print(f'Name: {card.get(\"name\", \"MISSING\")}')
print(f'URL: {card.get(\"url\", \"MISSING\")}')
print(f'Skills: {len(card.get(\"skills\", []))}')
for s in card.get('skills', []):
    print(f'  - {s[\"name\"]}: {s[\"description\"]}')
print(f'Streaming: {card.get(\"capabilities\", {}).get(\"streaming\", False)}')
print(f'Push: {card.get(\"capabilities\", {}).get(\"pushNotifications\", False)}')
print(f'Auth: {[s for s in card.get(\"authentication\", {}).get(\"schemes\", [])]}')
"
(2) Quick Task Test
# test_a2a_task.py
import asyncio
import httpx

async def test_task(server_url: str, message: str):
    """Quickly test an A2A Server's Task handling."""
    payload = {
        "jsonrpc": "2.0",
        "id": 1,
        "method": "message/send",
        "params": {
            "message": {
                "role": "user",
                "parts": [{"type": "text", "text": message}]
            }
        }
    }
    async with httpx.AsyncClient(timeout=30) as client:
        resp = await client.post(server_url, json=payload)
        result = resp.json()

        if "error" in result:
            print(f"ERROR: {result['error']}")
        else:
            task = result.get("result", {})
            print(f"Task ID: {task.get('id')}")
            print(f"Status: {task.get('status', {}).get('state')}")
            artifacts = task.get("artifacts", [])
            for a in artifacts:
                for p in a.get("parts", []):
                    if p.get("type") == "text":
                        print(f"Result: {p['text'][:200]}")

if __name__ == "__main__":
    asyncio.run(test_task("http://localhost:9000", "Hello A2A!"))
(3) Common Tools and Platforms
Tool / Platform Use Link
Google ADK Agent dev framework, native A2A github.com/google/adk-python
Google Agent Registry Agent Card registration & discovery docs.cloud.google.com/agent-registry
AWS Bedrock AgentCore Hosted A2A Server docs.aws.amazon.com/bedrock-agentcore
python-a2a Community Python lib, simpler API github.com/themanojdesai/python-a2a
A2A Protocol Playground Online A2A interaction testing a2a.plus
3.5. Security Best Practices
(1) Authentication Methods

A2A reuses standard enterprise authentication mechanisms — no new ones invented. | Method | Best fit | Notes | | :---------------- | :----------------------------- | :----------------------------------- | | OAuth 2.0 | Enterprise, cross-organization | Recommended; fine-grained permissions | | API Key | Internal services, quick integration | Simple but less secure | | JWT Bearer Token | Microservice-to-microservice | Stateless; carries claims | | OpenID Connect | Identity-verification needed | Identity layer on top of OAuth 2.0 | | mTLS | High-security needs | Mutual certificate authentication |

(2) Security Checklist
  • [ ] Agent Card declares supported auth schemes (authentication.schemes)
  • [ ] HTTPS enforced in production
  • [ ] Verify Client identity before executing tasks
  • [ ] Don't leak internal implementation details in Task results
  • [ ] Validate and filter user input on input-required
  • [ ] Push Notification webhook URL validation (prevent SSRF)
  • [ ] Limit Task concurrency and execution time to prevent resource exhaustion
  • [ ] Audit logs: record creation, state changes, and completion of every Task
(3) Common Attack Vectors
Attack Description Defense
Agent Card forgery Malicious Agent impersonating a trusted Agent Card signature verification, registry whitelist
Task injection Malicious instructions injected via messages Input validation, Prompt isolation
Webhook SSRF Push Notification used to attack internal services URL allowlist, outbound traffic limits
Denial of Service Flood of Task requests exhausts resources Rate limiting, auth-first
Data exfiltration Sensitive data leaked via Artifacts Output filtering, DLP policies
3.6. Cheatsheets
(1) Development Workflow
# 1. Install SDK
pip install a2a-sdk
# or
pip install python-a2a

# 2. Define Agent Card (name, skills, auth)
# 3. Implement AgentExecutor (Task logic)
# 4. Start the Server
python server.py

# 5. Verify
curl http://localhost:9000/.well-known/agent.json

# 6. Test a Task
curl -X POST http://localhost:9000/ \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"message/send","params":{"message":{"role":"user","parts":[{"type":"text","text":"test"}]}}}'
(2) JSON-RPC Method Quick Reference
// Send (sync)
{"jsonrpc":"2.0","id":1,"method":"message/send","params":{"message":{"role":"user","parts":[{"type":"text","text":"..."}]}}}

// Send (streaming)
{"jsonrpc":"2.0","id":1,"method":"message/stream","params":{"message":{"role":"user","parts":[{"type":"text","text":"..."}]}}}

// Query Task state
{"jsonrpc":"2.0","id":2,"method":"tasks/get","params":{"id":"task-123"}}

// Cancel Task
{"jsonrpc":"2.0","id":3,"method":"tasks/cancel","params":{"id":"task-123"}}

// Set Push Notification
{"jsonrpc":"2.0","id":4,"method":"tasks/pushNotification/set","params":{"id":"task-123","pushNotificationConfig":{"url":"https://my-webhook.example.com/callback"}}}
(3) Task State Quick Reference
submitted ──→ working ──→ completed   (normal flow)
                 │
                 ├──→ input-required ──→ working   (additional input needed)
                 ├──→ auth-required  ──→ working   (auth needed)
                 ├──→ failed                        (execution failed)
                 └──→ canceled                      (canceled)

submitted ──→ rejected                              (rejected by Server)
(4) A2A vs MCP Quick Reference
Dimension A2A MCP
Direction Agent ↔ Agent (horizontal) Agent ↔ Tool (vertical)
Protocol JSON-RPC + HTTP + SSE JSON-RPC + stdio/HTTP
Discovery Agent Card (/.well-known/) Capability Negotiation
Core unit Task (stateful lifecycle) Tool Call (request-response)
Async Push Notification + SSE Sampling + Elicitation
Typical scenario Multi-Agent orchestration, cross-org collaboration Tool calls, data-source connections
Used together Orchestrator delegates tasks Agent calls tools internally

4. Bootcamp & Workshops

4.1. Learning Resources
Resource Type Audience
A2A Official Spec Spec Everyone
A2A GitHub Repo Source + samples Engineers
Google Codelab: A2A Purchasing Concierge Tutorial Beginners
A2A Protocol Guide (codilime) Deep dive Architects
A2A Multi-Agent Guide (letsdatascience) Guide Full-stack
Microsoft Semantic Kernel + A2A Integration .NET developers
AWS Bedrock A2A Contract AWS AWS users
A2A Python Tutorial (kanaries) Tutorial Python developers
A2A TypeScript Guide Tutorial TS developers
A2A Security (Red Hat) Security Security engineers
4.2. Trouble Shooting
(1) Agent Card not reachable
  • Symptom: GET /.well-known/agent.json returns 404.
  • Diagnostics: confirm the Server registered the route correctly.
  • Common causes: missing route in framework config; Server not running on the expected port.
(2) Task stuck in working forever
  • Cause: Agent execution didn't transition state correctly (no complete/fail).
  • Fix: ensure all paths end in a terminal state (completed/failed); add timeouts.
  • Recommendation: enforce a max execution time and auto-fail.
(3) SSE stream disconnects
  • Cause: middle proxy (Nginx, ALB) closes long-lived connections.
  • Fix: configure proxy timeouts (Nginx proxy_read_timeout 3600s).
  • Alternative: use Push Notification instead of SSE for long tasks.
(4) Multi-turn (input-required) doesn't work
  • Cause: Client doesn't handle input-required correctly, or doesn't pass task_id when continuing.
  • Fix: on input-required, the Client must send the next message/send with the same task_id.
  • Note: every message/send must include the task_id to continue the same Task.
(5) Authentication failure
  • Cause: Agent Card declares an auth scheme that doesn't match Server-side middleware.
  • Fix: ensure authentication.schemes matches Server-side configuration.
  • Common pitfalls: expired OAuth token, API key not properly passed in headers.
(6) CORS issues
  • Symptom: browser-side Client can't access the A2A Server.
  • Fix: configure CORS headers (Access-Control-Allow-Origin, etc.) on the Server.
  • Note: /.well-known/agent.json also needs CORS configuration.
4.3. Q & A
  1. How exactly do A2A and MCP work together?
  2. Short answer: A2A handles "who does it" (Agent-to-Agent delegation); MCP handles "how it's done" (Agent calls tools).
  3. Typical architecture: an Orchestrator Agent delegates tasks via A2A to Specialist Agents; each Specialist uses MCP internally to call DBs, APIs, etc.
  4. Both are governed by the Linux Foundation AAIF — they are not competing.
  5. See 4.Protocol/2.MCP.md §1.3 and Q&A items 5, 7.

  6. When do I need A2A and when don't I?

  7. Need A2A: multiple independent Agents need to collaborate, especially across teams, organizations, or vendors.
  8. Don't need A2A: a single Agent + MCP Tools is enough; multi-Agent within the same framework (use LangGraph/CrewAI — simpler).
  9. Test: if your Agent needs to "delegate to another Agent you don't control", you need A2A.

  10. What's the difference between an A2A Server and an MCP Server?

  11. MCP Server: exposes Tools/Resources/Prompts; used by an Agent as a tool; no autonomous decision-making.
  12. A2A Server: itself an Agent with autonomous decisions, multi-turn, can reject tasks.
  13. Analogy: MCP Server is "a hammer in the toolbox"; A2A Server is "a colleague you can delegate to".

  14. Difference between Agent Card and an MCP Tool Schema?

  15. Agent Card: describes the Agent's overall capabilities (skills) — high-level "what can I do".
  16. Tool Schema: describes a single tool's I/O — low-level "how to call this function".
  17. Agent Card is more like a resume; Tool Schema is more like API documentation.

  18. How is an A2A Task different from a normal API call?

  19. API call: synchronous, stateless, request-response, milliseconds.
  20. A2A Task: asynchronous, stateful, multi-turn, runs seconds to hours.
  21. A2A Task can pause (input-required) to wait for human input — API calls cannot.

  22. How mature is A2A as of mid-2026?

  23. Spec: stable; v0.3+ supports gRPC and signed agent cards.
  24. SDKs: official Python/Go/Java/JS SDKs available.
  25. Production: still early; mostly PoCs and pilot projects.
  26. Ecosystem: 150+ orgs support it, but the count of production-grade A2A Servers is far fewer than MCP Servers.
  27. Recommendation: track and learn it; pilot in suitable scenarios (cross-org multi-Agent); don't roll out broadly yet.

  28. When do you write a Skill, install an MCP, or use A2A?

  29. Skill: teach an Agent how to do something — workflows, conventions, templates (see 4.Protocol/1.Skill.md).
  30. MCP: give an Agent "hands and feet" — connect tools, data sources, external systems (see 4.Protocol/2.MCP.md).
  31. A2A: let an Agent "find a colleague" — delegate tasks to other Agents; cross-organization collaboration.
  32. The three are complementary: Skills define the flow; MCP provides the tools; A2A coordinates the division of labor.
  33. Heuristic: "I want to teach the Agent a process" → Skill; "I want the Agent to query a database" → MCP; "I want the Agent to hand a task to another Agent" → A2A.