โ†
AI Agent Builders & Citizen Developers
Strategic ยท M2 ยท lesson 2 of 32 ยท queued
Preview โ€” browse every lesson free. Enroll to mark lessons complete, open partner links and save your progress. Login & enroll โ†’
Agent-to-Agent (A2A) Protocol in Production
๐Ÿ“–
now learning

Agent-to-Agent (A2A) Protocol in Production

15 min

By March 2026, the Linux Foundation's Agentic AI Foundation ratified A2A v1.2, and within ten weeks more than 150 organizations were routing real production traffic across vendor boundaries: a Google ADK orchestrator invoking a CrewAI specialist agent over HTTP, a LangGraph workflow delegating a planning sub-task to a LlamaIndex agent on another team's infrastructure, a Semantic Kernel agent calling out to an OpenAgents-built researcher. The story stopped being "can agents from different vendors actually talk?" and started being "what do you have to ship to make them talk safely?" This lesson walks the A2A v1.2 specification, the eight native-A2A frameworks you can mix in 2026, the cross-vendor handoff pattern (Google ADK orchestrator invoking a CrewAI specialist), the JSON-RPC 2.0 plus Agent Card mechanics, and the failure mode of pretending REST plus a swagger spec is the same thing as A2A.

What A2A Actually Is

A2A โ€” Agent-to-Agent โ€” is an open protocol for one autonomous agent to invoke another autonomous agent over the network. Originally proposed by Google in April 2025 and adopted by the Linux Foundation's Agentic AI Foundation in October 2025, the v1.2 specification (March 2026) is the version that turned A2A from a vendor-led proposal into the actual interoperability layer for multi-agent systems.

The specification is small enough to read in an afternoon and disciplined enough to deploy without surprises. It defines four things:

  1. Agent Card. A signed JSON document published at a well-known URL (/.well-known/agent-card) describing the agent: its skills (what it can do), its capabilities (which protocol features it supports โ€” streaming, push-notifications, long-running tasks), its endpoints, its authentication schemes, and its operator identity. The card is the discovery surface. Other agents read it before invoking.
  2. Transport layer. HTTP/HTTPS with JSON-RPC 2.0 as the message envelope. Server-Sent Events for streaming responses. Optional gRPC for high-throughput same-org traffic. The transport is intentionally boring; the protocol is the point.
  3. Task lifecycle. A typed state machine โ€” submitted, working, input-required, completed, failed, cancelled. Long-running tasks (hours, days) are first-class. The client can disconnect and reconnect. The server publishes status changes via streaming or webhooks.
  4. Message format. Multi-part messages: text, structured data (JSON), file references (signed URLs), artifacts (typed outputs). Designed for the reality that agents don't just trade strings โ€” they trade tables, images, generated documents, code diffs.

What A2A is not: it's not a tool-calling protocol (that's MCP). It's not a model API (that's the OpenAI/Anthropic/Google APIs). It's not a workflow language (that's Temporal, LangGraph, Inngest). A2A is what happens at the boundary between two agents โ€” typically agents owned by different teams, different vendors, or different organizations โ€” when one needs the other to do work.

The simplest mental model: MCP is how agents talk to tools. A2A is how agents talk to other agents. They are complementary, not competing. A well-architected 2026 system uses both.

The 150-Org Production Reality

By April 2026, the Linux Foundation's A2A working group counted 150-plus organizations with at least one production A2A endpoint exposed and receiving real traffic. The list reads like a who's-who of the 2026 enterprise-AI buyer landscape โ€” but the more interesting number is what they're using it for.

The dominant pattern is cross-vendor delegation. An orchestrator agent built on one framework (most commonly Google ADK or LangGraph) needs a capability it doesn't have natively โ€” deep customer-support reasoning, code review, specialized research, document extraction โ€” and instead of building it, it invokes a specialist agent on another framework over A2A. The specialist might be from another team, from another vendor, or from a public agent marketplace.

Three real shapes we've watched in production through Q1-Q2 2026:

  • An e-commerce orchestrator built on Google ADK delegates returns triage to a CrewAI multi-agent crew owned by the support team. The crew's "lead" agent reads the customer's history, the order details, the return reason, and decides authorization, refund, or escalation. The handoff is one A2A call carrying a 4 KB context envelope. The crew's reply carries an artifact (the proposed resolution) and a structured decision (the action to take).
  • A research platform built on LangGraph invokes specialist sub-agents on LlamaIndex (for technical-paper extraction), AutoGen (for hypothesis generation), and OpenAgents (for adversarial review). The orchestrator runs the loop; the specialists run their work; A2A is the wire.
  • A regulated-industry compliance agent built on Microsoft Semantic Kernel calls a Google ADK agent owned by a different business unit for KYC review. The two agents are in different cloud accounts, behind different identity providers. mTLS plus OAuth client-credentials plus signed Agent Cards is the bridge. A2A is what makes the cross-org call legible.

What changed between 2024 and 2026 was not the desire to mix agents from different vendors โ€” that was already there โ€” but the cost of doing it. In 2024 the typical "multi-agent" system was two agents from the same vendor talking through that vendor's proprietary RPC, or an ad-hoc REST adapter between two custom frameworks that broke every time either side shipped. A2A v1.2, with its signed cards, its task lifecycle, its first-class long-running tasks, and its native framework support across the seven biggest agent ecosystems, removes the integration tax. The cross-vendor call now costs you a config file, not a sprint.

The Native-A2A Framework List

"Native A2A support" means the framework ships an A2A server and client out of the box. You don't write the protocol; you implement skills and the framework handles the wire. As of May 2026, native support exists in:

  • Google ADK (Agent Development Kit). A2A is the first-class inter-agent transport. Every ADK agent has an Agent Card by default; you can opt out, but the default is on. ADK orchestrator agents can route to A2A peers as if they were local tools.
  • LangGraph. The a2a module ships an Agent Card publisher, an A2A server that mounts a LangGraph state graph as an A2A endpoint, and a client that turns A2A peers into LangGraph nodes. Maintained in lockstep with LangGraph 0.4+.
  • CrewAI. Crew agents expose A2A by setting a2a=True on the agent definition. The Crew itself is the unit of A2A exposure โ€” peers call the Crew, not individual agents within.
  • LlamaIndex. The llama-index-agent-a2a package wraps any LlamaIndex agent as an A2A server. Bidirectional: any LlamaIndex agent can also call A2A peers via the A2ATool tool adapter.
  • Microsoft Semantic Kernel. Both .NET and Python implementations. Semantic Kernel kernels can expose Plugins as A2A skills, and any kernel can act as an A2A client. Strong support for Azure AD identity flows in the same package.
  • Microsoft AutoGen. The autogen-agentchat-a2a extension exposes AutoGen agents as A2A peers. The AutoGen team has been explicit that A2A is the cross-runtime story; in-runtime communication still uses AutoGen's native group-chat model.
  • OpenAgents. The community-driven framework that grew out of the late-2024 open-source agent push. A2A is the default and only inter-agent transport. There is no proprietary alternative; A2A is the protocol of the project.
  • Custom / framework-less. The a2a-sdk package (Python and TypeScript) lets you ship A2A without adopting any of the above. Useful for teams that have their own agent runtime โ€” typically a thin wrapper around the model SDK plus business logic โ€” and don't want to swallow a framework just to expose an A2A endpoint.

The strategic implication: framework choice is no longer the binding constraint on multi-agent architecture. You can pick the framework that fits each agent's job โ€” CrewAI for collaborative crews, LangGraph for stateful workflows, ADK for orchestration, LlamaIndex for retrieval-heavy specialists โ€” and the agents talk over a shared wire. The 2024 "we have to pick one framework for the whole company" debate is over.

The Agent Card Anatomy

The Agent Card is the single most important artifact in the A2A protocol. It's where you make discoverability promises, identity claims, skill declarations, and capability negotiations. A2A v1.2 specifies the schema; here is a stripped-down real example from a CrewAI returns-triage agent we deployed in April 2026:

{
  "schema_version": "1.2",
  "name": "returns-triage-agent",
  "description": "Authorize, deny, or escalate customer return requests for the apparel category.",
  "operator": {
    "organization": "Acme Apparel, Inc.",
    "contact": "[email protected]",
    "domain": "agents.acmeapparel.com"
  },
  "endpoints": {
    "jsonrpc": "https://agents.acmeapparel.com/a2a/returns-triage",
    "streaming": "https://agents.acmeapparel.com/a2a/returns-triage/stream"
  },
  "skills": [
    {
      "id": "evaluate_return",
      "description": "Evaluate a return request and return authorize/deny/escalate.",
      "input_schema": { "$ref": "#/definitions/ReturnRequest" },
      "output_schema": { "$ref": "#/definitions/ReturnDecision" }
    }
  ],
  "capabilities": {
    "streaming": true,
    "push_notifications": true,
    "long_running_tasks": false,
    "max_input_tokens": 64000
  },
  "authentication": [
    { "scheme": "oauth2-client-credentials", "token_endpoint": "https://auth.acmeapparel.com/oauth/token" },
    { "scheme": "mtls", "trust_anchor": "https://agents.acmeapparel.com/.well-known/trust-anchor.pem" }
  ],
  "signature": {
    "algorithm": "EdDSA",
    "key_id": "agents-acmeapparel-2026-q1",
    "signature": "..."
  }
}

Three things to notice. First, the signature field is required in v1.2 (it was optional in v1.0). The card is cryptographically signed with a key bound to the operator's domain; clients verify the signature against a trust anchor (typically published via DNS or a Web PKI certificate). This is the foundation for "I trust that this Agent Card actually represents Acme Apparel" โ€” without it, an adversary could publish a card claiming to be Acme and route real traffic to themselves. Lesson 2 of this chapter goes deeper on the identity story.

Second, skills are typed. Each skill declares an input schema and an output schema (JSON Schema, typically). The orchestrator agent reads these schemas and constructs valid calls. This is the discipline that REST plus swagger gestures at but rarely enforces โ€” and it's the discipline that lets an LLM-driven orchestrator construct correct A2A calls without bespoke prompt engineering for every peer.

Third, capabilities are explicit. Streaming yes or no. Push notifications yes or no. Long-running tasks yes or no. Max input tokens. The client doesn't guess; the card tells. This is where you'll feel the difference from REST-plus-swagger in week one.

The Cross-Vendor Handoff: Google ADK to CrewAI

Here is the canonical 2026 multi-vendor pattern we have shipped in three deployments now: a Google ADK orchestrator agent invokes a CrewAI specialist crew over A2A. Both sides are real production agents. Both sides are from different vendors. Both sides are running on different cloud accounts.

The orchestrator (Google ADK)

The orchestrator's job: handle a customer-support conversation. Most of the time, the orchestrator resolves the question itself โ€” it has tools for order lookup, account status, knowledge-base search. When the conversation turns to a return request, the orchestrator delegates to the returns-triage specialist.

The ADK orchestrator's agent definition (Python, simplified):

from google.adk import Agent, tools
from google.adk.a2a import A2APeer

returns_triage = A2APeer(
    agent_card_url="https://agents.acmeapparel.com/.well-known/agent-card",
    authentication={"scheme": "oauth2-client-credentials", "client_id": "orchestrator-prod", "client_secret_ref": "secret://orchestrator/returns-triage"},
)

orchestrator = Agent(
    name="support-orchestrator",
    model="gemini-2.5-pro",
    tools=[tools.OrderLookup(), tools.KnowledgeBaseSearch(), returns_triage.as_tool()],
    instructions=open("orchestrator.md").read(),
)

The returns_triage.as_tool() call is the bridge. ADK reads the Agent Card at startup, validates the signature against the trust anchor, generates a typed tool wrapper that matches the evaluate_return skill's input schema, and exposes it to the orchestrator's reasoning loop as if it were a native tool. The orchestrator's prompt doesn't have to know it's calling another agent; it sees a tool called evaluate_return with a structured input.

The specialist (CrewAI)

On the other side, the CrewAI returns-triage crew. Three agents inside the crew: a policy interpreter that knows the returns policy, a history analyst that looks at the customer's return history for fraud signals, a decision agent that synthesizes a decision. The crew exposes itself as an A2A endpoint:

from crewai import Crew, Agent
from crewai.a2a import A2AServer

policy_interpreter = Agent(role="returns-policy-interpreter", ...)
history_analyst = Agent(role="customer-history-analyst", ...)
decision_maker = Agent(role="returns-decision-maker", ...)

returns_crew = Crew(
    agents=[policy_interpreter, history_analyst, decision_maker],
    tasks=[...],
    a2a=True,
    a2a_card={
        "name": "returns-triage-agent",
        "description": "Authorize, deny, or escalate apparel returns.",
        "skills": [{
            "id": "evaluate_return",
            "input_schema": ReturnRequest.model_json_schema(),
            "output_schema": ReturnDecision.model_json_schema(),
        }],
    },
)

server = A2AServer(crew=returns_crew, port=8443, tls_cert="...", oauth_issuer="...")
server.serve()

What happens on the wire when the orchestrator calls evaluate_return:

  1. The orchestrator's A2A client fetches a fresh OAuth client-credentials token from the issuer (cached for the token's TTL).
  2. It issues a JSON-RPC 2.0 POST to https://agents.acmeapparel.com/a2a/returns-triage with method task/send, an authorization header carrying the bearer token, and a payload containing the ReturnRequest structured input.
  3. The CrewAI A2A server validates the bearer token against the configured OAuth issuer, validates the payload against the evaluate_return input schema, and submits the task to the crew.
  4. The crew runs (policy interpreter reads the policy, history analyst looks at history, decision maker synthesizes). Total time: 6-12 seconds typically.
  5. The server returns a JSON-RPC 2.0 response carrying the ReturnDecision structured output. The orchestrator's tool wrapper validates against the output schema and surfaces it to the reasoning loop.

The orchestrator's prompt never says "call CrewAI." The orchestrator's prompt says "if the conversation turns to a return, use the evaluate_return tool." Vendor neutrality at the prompt level. That's the protocol earning its keep.

Streaming and Long-Running Tasks

The returns-triage example is a short synchronous task โ€” 6-12 seconds. A2A's bigger contribution shows up when the tasks aren't short.

Streaming

When a peer agent will produce output incrementally โ€” a researcher composing a multi-page report, a code-review agent walking a diff, a creative agent generating slides โ€” the client opens a streaming connection (Server-Sent Events) and receives task/status and task/artifact events as they happen. The orchestrator can surface progress to the user in real time, or feed early outputs to downstream steps before the peer is done.

In one Q1 2026 deployment we observed, a LangGraph orchestrator streamed a Semantic Kernel research agent's findings to a downstream LlamaIndex summarizer concurrently โ€” the summarizer started consuming as the researcher produced, and total wall-clock dropped from 4.2 minutes (serial) to 2.7 minutes (overlapped). The streaming primitive is the enabler.

Long-running tasks

Tasks that take hours or days โ€” multi-step migrations, scheduled enrichment runs, complex research โ€” declare long_running_tasks: true in their Agent Card. The client submits the task, gets a task ID, and disconnects. The peer continues working. When state changes (status updates, intermediate artifacts, completion), the peer pushes notifications to a webhook URL the client provided at submission, or the client polls. The task lifecycle survives client crashes, deploys, and restarts.

This is the seam where A2A meets durable execution (the subject of Lesson 3 of this chapter). The peer's own implementation of the long-running task typically runs on a durable executor like Temporal, Inngest, or LangGraph Platform โ€” because the agent will outlive any single process. A2A is the wire between agents; durable execution is what lets a single agent survive long enough to use it.

REST Plus Swagger Is Not A2A (The Failure Mode)

The most common 2026 anti-pattern: "we don't need A2A, we have REST endpoints and OpenAPI specs; that's the same thing." It is not. Three concrete differences will bite teams that pretend it is.

The Agent Card is signed; OpenAPI specs are not. The cryptographic identity binding between an Agent Card and the operator's domain is the foundation of cross-org trust. An OpenAPI spec is a document on a web server; nothing stops me from publishing a spec that claims to be your service. The signed card plus trust-anchor verification is the difference between "I think this is your agent" and "I can prove this is your agent."

The task lifecycle is typed; REST is request-response. A2A's submitted โ†’ working โ†’ input-required โ†’ completed state machine is a first-class part of the protocol. Clients react to state transitions in well-defined ways. A REST endpoint with a long-running operation forces you to invent your own polling protocol, your own status enum, your own re-entry semantics. Every team that built this in 2024 built it slightly differently. By 2026, sharing those endpoints across orgs was the integration tax. A2A makes the lifecycle uniform.

The framework wrappers are real. Native A2A in Google ADK, LangGraph, CrewAI, LlamaIndex, Semantic Kernel, AutoGen, and OpenAgents means an A2A peer is one config line away from being a tool in the orchestrator's reasoning loop. The REST-plus-swagger equivalent is per-vendor adapters, hand-rolled tool schemas, and ongoing maintenance every time either side ships. The TCO difference is large.

The 2026 build pattern is unambiguous: if you are exposing an agent to any consumer outside your immediate team โ€” another team, another business unit, a partner, a customer โ€” expose it as A2A. Even if the first consumer is a hand-coded HTTP client, the next consumer will be an ADK or LangGraph orchestrator, and they will thank you. If you are exposing only inside your own runtime, you can defer; if there is any cross-runtime risk, do not.

The Five-Step Build Routine

Here is the routine we walk teams through to ship their first cross-vendor A2A handoff. From design to traffic in a focused day or two for teams already running modern agent frameworks; up to a week for teams starting from scratch.

  1. Pick the seam. Identify one place in your architecture where one team's agent needs another team's specialist. Returns triage, KYC review, code review, document extraction. Constrain the scope; do not try to A2A-ify the whole system on day one.
  2. Write the Agent Card for the specialist. Name, description, one or two skills, signed with an operator key bound to the operator's domain. Publish at /.well-known/agent-card. Validate the signature works against your trust anchor before going further.
  3. Stand up the A2A server on the specialist's framework. CrewAI, LangGraph, LlamaIndex โ€” whichever the specialist is built on. Mount the relevant skill. Run it locally; test with the a2a-cli client.
  4. Add the A2A peer to the orchestrator. One config line in ADK or LangGraph; an A2APeer object in code. The framework reads the card, generates a typed tool wrapper, exposes it to the reasoning loop. Verify the orchestrator's traces show the peer being invoked correctly.
  5. Add identity, observability, and limits. Switch from dev-mode tokens to OAuth client-credentials or mTLS. Wire the orchestrator's A2A calls into your trace store so spans cross the agent boundary. Configure timeouts, retries, and circuit breakers. Decide what happens if the peer is down (graceful fallback, escalate to human, retry with backoff).

The teams that ship A2A cleanly in 2026 follow this routine and stop at the seam. The teams that struggle try to do everything at once โ€” A2A plus a framework migration plus a new model plus a new identity story โ€” and lose six weeks to integration hell.

Three Real Deployment Shapes

What the post-A2A architecture actually looks like in three different 2026 organizations we observed in Q1-Q2 2026:

A 280-person e-commerce company. ADK orchestrator at the front (customer-facing chat), CrewAI specialists for returns, fraud review, and loyalty-program questions, all running on the same cloud account but on different deployment units. A2A is the inter-agent transport even though everything is one org, because the teams ship on different release cadences. mTLS plus signed cards. The architecture survived three CrewAI version bumps and one ADK major upgrade without breaking the wire โ€” because the wire is protocol, not code.

A 1,200-person regulated-industries provider. Semantic Kernel agents on Azure for the compliance work, a Google ADK orchestrator on GCP for the customer-facing reasoning, an LlamaIndex retrieval specialist on AWS owned by the data team. Three cloud accounts, three frameworks, three identity providers. mTLS plus OAuth federation plus signed Agent Cards plus DNS-anchored trust roots. The integration test that proves "the customer-facing agent in GCP can call the KYC agent in Azure with full audit trail" runs nightly. The A2A protocol makes this tractable; without it, the bespoke adapters would have been a six-engineer team's full-time job.

A 40-person research-tools startup. Single LangGraph orchestrator, but it invokes three different third-party specialist agents via A2A โ€” one from a partner organization, two from a public agent marketplace. The partner's agent uses OAuth client-credentials; the marketplace agents use mTLS with the marketplace's CA as trust anchor. Total integration code: under 200 lines. Total time from "we want to use this specialist" to "it's in production": one afternoon. The protocol is doing the work.

What to Avoid

  • Treating A2A as a strictly internal protocol. The point of A2A is cross-team, cross-org, cross-vendor. If everything you A2A-ify is in the same team's runtime, you are paying integration cost with no return. Inside a single runtime, native framework calls are fine.
  • Publishing unsigned Agent Cards because "we'll sign them later." Signed cards are not a "production hardening" task; they are the protocol's identity foundation. Sign from day one; the operational story scales.
  • Skipping the input/output schemas. Untyped A2A skills accept and return free-form text. You will regret this in week three when the consumer's LLM constructs subtly malformed inputs and the specialist silently does the wrong thing. Type your skills.
  • Ignoring streaming because "our task is fast." Tasks that are fast today get slower as you add validation, retrieval, multi-agent reasoning. Designing for streaming from the start costs a config line and saves a refactor.
  • Reinventing the lifecycle. The submitted โ†’ working โ†’ input-required โ†’ completed state machine is the spec. Honor it. Do not invent your own status field with overlapping semantics; downstream tooling assumes the standard.
  • Forgetting timeouts and circuit breakers on the orchestrator side. A peer agent that hangs will hang your orchestrator. Set timeouts per skill (matched to the skill's expected duration), implement circuit breakers, decide failover behavior up front.
  • Coupling identity to the framework. Your authentication story should be the same whether the peer is CrewAI or LangGraph or custom. OAuth client-credentials and mTLS are the two patterns; pick one per relationship and apply it uniformly.

Key Takeaways

  • A2A v1.2, ratified by the Linux Foundation's Agentic AI Foundation in March 2026, is the protocol for one autonomous agent to invoke another autonomous agent over the network. 150-plus organizations routing real production traffic by April 2026.
  • The specification is four things: signed Agent Card (discovery + identity), HTTP plus JSON-RPC 2.0 transport with optional streaming, typed task lifecycle (submitted โ†’ working โ†’ input-required โ†’ completed), multi-part messages.
  • MCP is for agent-to-tool. A2A is for agent-to-agent. They are complementary; a well-architected 2026 system uses both.
  • Native A2A support in eight ecosystems: Google ADK, LangGraph, CrewAI, LlamaIndex, Semantic Kernel, AutoGen, OpenAgents, and the framework-less a2a-sdk. Framework choice is no longer the binding constraint on multi-agent architecture.
  • The canonical 2026 cross-vendor pattern: a Google ADK orchestrator invokes a CrewAI specialist crew over A2A. One config line on the orchestrator side; one a2a=True on the crew side; the protocol does the rest.
  • Signed Agent Cards plus trust-anchor verification is the foundation of cross-org trust. Unsigned cards are not A2A; they are wishful thinking.
  • Streaming and long-running tasks are first-class. Tasks can survive client disconnects, deploys, and multi-day execution. This is the seam where A2A meets durable execution (next lesson's territory).
  • REST plus swagger is not A2A. Missing signatures, missing typed lifecycle, missing framework wrappers. Three things you will rebuild yourself if you pretend otherwise.
  • Ship the cross-vendor handoff in a focused day or two using the five-step routine: pick the seam, write the card, stand up the server, add the peer to the orchestrator, add identity and observability.
  • Identity, observability, and limits are not afterthoughts. They are the protocol's seams; design them up front.