DEV Community

Cover image for A2A Hit 150 Organizations in a Year. Most Projects Reaching For It Do Not Need It Yet
Moksh Gupta
Moksh Gupta

Posted on • Originally published at devtoollab.com

A2A Hit 150 Organizations in a Year. Most Projects Reaching For It Do Not Need It Yet

Agent2Agent turned one year old under the Linux Foundation in April 2026 with numbers that are genuinely impressive: more than 150 supporting organizations, up from roughly 50 twelve months earlier, over 22,000 stars on the core repository, and SDKs in Python, JavaScript, Java, Go and .NET. Azure AI Foundry, Amazon Bedrock AgentCore and Google Cloud's Agent Development Kit all ship it.

None of that tells you whether you should use it. "150 companies signed a support letter" and "engineers pick this over an HTTP call" are separate claims, and the gap between them is where most of the confusion about A2A lives. I wrote a fuller version of this on DevToolLab, A2A Protocol Explained, with the complete working example. Short version below.

Four Concepts, Then You Have It

MCP wires an agent to tools. A2A wires an agent to other agents, possibly on another vendor's stack, in another language, owned by a team you never talk to. The design goal is that agent A never learns how agent B is built, only what B can do and how to hand it work.

An Agent Card is a JSON document at /.well-known/agent-card.json listing skills, input and output modes, and auth requirements. A Task is a unit of work with a real lifecycle: submitted, working, sometimes input-required when it needs more from the caller, then completed, failed or canceled. A Message is one turn in the exchange. An Artifact is the output, built from typed parts that can be text, a file or structured data.

Transport is JSON-RPC 2.0 over HTTP with Server-Sent Events for streaming and push notifications for tasks that outlive one request. Version 0.3 in August 2025 added gRPC as an alternate transport and JWS-signed Agent Cards, which matters more than it first sounds: without signing, an Agent Card is an unauthenticated JSON file at a predictable URL.

It Is Not Competing With MCP

The framing that survives contact with real systems: MCP is the tool-integration layer, A2A is the agent-collaboration layer. MCP answers "give my agent a function to call." A2A answers "hand this task to an agent I do not control and get a result back." Non-trivial multi-agent systems need both.

The differences that matter in practice are the unit of work and who owns the other side. MCP moves a tool call; A2A moves a stateful task that can span turns. MCP servers are usually yours; the agent behind an Agent Card usually is not.

When You Genuinely Need It

The criticism doing the rounds this year is fair. Plenty of A2A demos show three agents accomplishing what three function calls would. Standing up an Agent Card, a task store and JSON-RPC plumbing for one in-process call is pure overhead.

It earns its keep when the other agent is actually outside your control, when the interaction is a real task rather than a function call (multiple turns, mid-flight requests for more input, long enough that you want streaming instead of a blocking response), or when you need to discover capabilities at runtime instead of hardcoding them. Skip it when a direct API call, a shared MCP server or in-process orchestration already works. And read "150 organizations" as an interoperability signal, not as proof of production load. The number that would prove that is how many teams keep it after their first authentication failure and compliance review, which is far smaller.

A Working Agent, Start to Finish

The reference SDK is a2a-sdk, compatible with protocol versions 1.0 and 0.3:

pip install "a2a-sdk[http-server]"
Enter fullscreen mode Exit fullscreen mode

Describe the capability, then publish it in a card:

from a2a.types import AgentCard, AgentCapabilities, AgentSkill

skill = AgentSkill(
    id="summarize_ticket",
    name="Summarize Support Ticket",
    description="Reads a support ticket thread and returns a one-paragraph summary.",
    input_modes=["text/plain"],
    output_modes=["text/plain"],
    tags=["support", "summarization"],
    examples=["Summarize ticket #4021"],
)

agent_card = AgentCard(
    name="Ticket Summarizer Agent",
    description="Summarizes support tickets on request.",
    url="http://localhost:9999",
    version="1.0.0",
    default_input_modes=["text/plain"],
    default_output_modes=["text/plain"],
    capabilities=AgentCapabilities(streaming=True),
    skills=[skill],
)
Enter fullscreen mode Exit fullscreen mode

The executor is where the work happens. Note the status update before the slow part, which is what gives a caller something to stream:

from a2a.server.agent_execution import AgentExecutor, RequestContext
from a2a.server.events import EventQueue
from a2a.server.tasks import TaskUpdater
from a2a.types import TaskState
from a2a.utils import new_task_from_user_message, new_text_message, new_text_part


class TicketSummarizerExecutor(AgentExecutor):
    async def execute(self, context: RequestContext, event_queue: EventQueue) -> None:
        task = context.current_task or new_task_from_user_message(context.message)
        updater = TaskUpdater(event_queue, task_id=task.id, context_id=task.context_id)

        await updater.update_status(
            state=TaskState.working,
            message=new_text_message("Reading ticket thread..."),
        )

        summary = summarize(context.message)  # your own logic or LLM call

        await updater.add_artifact(parts=[new_text_part(text=summary)])
        await updater.update_status(state=TaskState.completed)

    async def cancel(self, context: RequestContext, event_queue: EventQueue) -> None:
        raise NotImplementedError("This agent doesn't support cancellation yet.")
Enter fullscreen mode Exit fullscreen mode

Then serve it:

from a2a.server.apps import A2AStarletteApplication
from a2a.server.request_handlers import DefaultRequestHandler
from a2a.server.tasks import InMemoryTaskStore
import uvicorn

handler = DefaultRequestHandler(
    agent_executor=TicketSummarizerExecutor(),
    task_store=InMemoryTaskStore(),
)
app = A2AStarletteApplication(agent_card=agent_card, http_handler=handler).build()

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=9999)
Enter fullscreen mode Exit fullscreen mode

Before pointing a client at it, confirm the card is actually being served:

curl -s http://localhost:9999/.well-known/agent-card.json
Enter fullscreen mode Exit fullscreen mode

A malformed Agent Card is a common reason a client silently discovers no skills, so it is worth running that response through a JSON Schema validator while you are iterating. The cURL command generator is also handy for the task-submission call, since hand-typing a JSON-RPC envelope every time you change one parameter gets old fast. The original post walks through each piece in more detail.

A2A Protocol guide banner covering the Agent2Agent protocol, its adoption numbers and how it compares to MCP

The Security Gap Nobody Demos

Every serious writeup lands on the same hole: an Agent Card says what an agent can do, not who owns it or what it should be trusted with. Four things worth doing on day one rather than retrofitting.

Verify signed cards, because JWS signing in v0.3 exists precisely so you can confirm a card was not swapped in transit, and HTTPS alone does not give you that. Scope what a remote agent may request instead of trusting every skill its card advertises, the same way you would scope an OAuth grant. Decode the tokens moving between agents rather than assuming an aud or sub claim means what you expect. And never forward a caller's token to a third-party agent unmodified: if agent A hands agent B its own credential, B now acts with A's authority on systems it was never meant to reach. That is the confused-deputy problem, and it does not stop being one because both parties are agents.

The Short Answer

A2A is not hype in the sense of not working. The spec is real, the SDKs work, the adoption is genuine. It is hype in the narrower sense that most projects reaching for it in 2026 do not need it yet. Use MCP to give your agent tools. Reach for A2A once you have a second agent you do not control that must accept a task, work across several turns and hand back a result. If your case is "agent A calls agent B once and gets a string," that is a function call wearing a protocol.

References

Top comments (0)