AXONN Vantis logo
AXONN VantisAgentic eXperience, Open Neural Network,Complete Governance
Contact SalesEN
← Blog

Reading the A2A Specification — What It Covers and What It Leaves to Implementers

Connect two or more AI agents and you run into one central question almost immediately. What exactly do they have to agree on before one can delegate work to the other?

Inside a single framework a plain function call is enough, and inside a single organization following the internal API convention settles it. Things change when the agent receiving the work is built on an entirely different language and framework, and was developed by a different organization altogether. A2A (Agent-to-Agent) is the standard aimed squarely at interoperability between agents that are foreign to one another in exactly this way. It moved to the Linux Foundation in June 2025, joining the open-source ecosystem, and reached a formal v1.0 release in 2026 — the point at which it became a general-purpose protocol with a settled shape.

This post walks through the full v1.0 specification with two questions in view. The first is establishing a clear boundary for what the protocol actually defines and guarantees. The second is identifying the gaps outside that boundary, where the engineer building the system still has to decide things independently. The second question deserves the closer look for a plain reason: it is easy to fall into the trap of believing that "we adopted A2A" means every problem of inter-system collaboration is now solved. What the protocol deliberately declines to touch stays squarely the responsibility of the people designing and building the system.

The premise

One design principle runs through the entire specification: interacting agents should look like black boxes to one another. Agents share no internal state, share no memory, and have no need to know which model the other runs or what tools it holds. Collaboration between agents rests on nothing but the capabilities the other side declares and the messages the two exchange.

That premise shapes the protocol. It is why the unit of exchange is a Task rather than a function call. A function call assumes the caller knows the callee's signature and roughly how long it will run, but work handed to an opaque peer offers none of that: the caller cannot know how long it will take, whether a human will have to step in partway, or whether partial results will surface. So A2A was designed around the lifecycle of a stateful task rather than around request and response.

For the same reason A2A does not compete with MCP (Model Context Protocol). MCP is a vertical convention for supplying tools and context to a model; A2A is a horizontal convention for passing work between peer agents. Neither is in a position to replace the other.

Agent Card: the unit of discovery and negotiation

An agent has to declare to its counterpart what it is able to do, and that declaration is called the Agent Card. A single JSON document carries identity, capabilities, endpoints and authentication requirements.

  • capabilities — declares support for streaming, pushNotifications and extendedAgentCard as booleans.
  • skills — the list of jobs this agent can perform. Each skill carries a description, examples and input/output modes.
  • supportedInterfaces — an array of service endpoints. Each interface has its own transport binding and its own protocolVersion.
  • securitySchemes — defines whether authentication runs on API keys, HTTP auth, OAuth2, OpenID Connect or mutual TLS.
  • extensions — lists the URIs of supported extensions and marks whether each is required.
  • signature — the JWS signature over the card itself.

First, skill descriptions are unstructured natural-language prose. A skill carries an id, a name and tags, but nothing like a type declaration that would let a machine mechanically determine what it takes in and what it hands back. Reading a card and judging "this agent is right for this job" is therefore not a service the specification provides — it falls to whoever is reading the card. In practice that judgement usually gets handed to an LLM, and against that background the quality of the writing in a card ends up governing the quality of your routing.

Second, an agent can present a different card before and after authentication. With capabilities.extendedAgentCard enabled, an authenticated client fetches a card carrying more skills through GetExtendedAgentCard. Publishing only the minimum on the public card and exposing real capability after authentication is a design the specification supports directly.

Signatures invite one easy misreading. A card is canonicalized with JCS (RFC 8785), signed with JWS (RFC 7515), and clients can verify it. What that verification guarantees is that the card was neither forged nor altered and that the provider is who it claims to be — not that the agent is actually good at the work written on the card. A signature attests to authenticity; it does not attest to competence, and that distinction is worth holding onto.

Sharing task state is the heart of it

When people collaborate at a company, the approval state of a document (drafted — under review — approved) is what matters. Collaboration between AI agents works the same way: the important thing is the Task, and sharing that task's progress state (pending — running — done) is the most reliable way for agents to communicate. A2A v1.0 defines eight task states, grouped into three categories.

  • In progressTASK_STATE_SUBMITTED, TASK_STATE_WORKING
  • InterruptedTASK_STATE_INPUT_REQUIRED, TASK_STATE_AUTH_REQUIRED
  • TerminalTASK_STATE_COMPLETED, TASK_STATE_FAILED, TASK_STATE_CANCELED, TASK_STATE_REJECTED

The interrupted states are the most distinctive part of this design. Needing further information or credentials partway through a job is treated as a normal state rather than an exception, and while a task sits in one of those states further messages can be sent to carry the work forward. A task that has reached a terminal state, by contrast, is designed to accept no more messages — continuing the conversation means creating a new task.

Identifiers come in two forms as well. taskId names an individual task, while contextId points at a bundle of related tasks. contextId exists because context can carry across several tasks even after an individual task has ended.

The structure holding a task's contents shows the same clarity of intent. Task data separates history, the record of messages exchanged between agents, from artifacts, the output produced as a result. This is a declaration that "what was said" and "what was actually produced" are to be treated as different things, and it lays the structural groundwork for basing a completion judgement on real output rather than on utterances or the flow of a conversation. The specification does not, however, mechanically enforce artifact-based completion. Moving a task into its final state (TASK_STATE_COMPLETED) is left entirely to the judgement of the agent that performed the work.

Message payloads, meanwhile, are expressed in a unit called Part. Rather than distinguishing text, bytes (binary data) and URL references separately, v1.0 consolidates them into the single Part type, which keeps the message structure lean.

One data model, three transports

The A2A data model is defined on Protocol Buffers, and for communication it supports three transports: JSON-RPC 2.0, gRPC, and HTTP+JSON/REST. The core of this structure is the requirement that the three bindings be functionally identical. Whichever transport a server chooses, the client must be guaranteed the same meaning and the same result, and the authentication schemes declared on the Agent Card must work identically across every binding. The explicit rule that streaming over REST must be implemented with SSE (Server-Sent Events) comes from the same place — the choice of transport must never turn into a functional limitation on the agent.

The core operations stay consistent regardless of binding: message delivery (SendMessage, SendStreamingMessage), task management (GetTask, ListTasks, CancelTask), stream reattachment (SubscribeToTask), push configuration management (four CRUD operations), and detailed card retrieval (GetExtendedAgentCard). In a REST environment these map to intuitive resource-oriented API paths such as POST /messages, GET /tasks/{id} and POST /tasks/{id}:cancel.

In production this equivalence carries real weight. What decides which binding you use is not a difference between applications or SDKs but the shape of your network infrastructure. What matters is which protocols the API gateways, proxies and load balancers sitting in front of your system will let through. Whether the network carries gRPC end to end, and whether some middlebox will forcibly drop a long-lived SSE connection, are the infrastructure conditions that actually determine your transport.

Response paths built for long-running, asynchronous work

Collaboration between agents means delegating work to something whose internals you cannot see, which makes it hard to predict when that work will finish. The specification offers three response paths for handling this asynchronous uncertainty.

First, the synchronous response. Suited to short-running work: you send a request and get the result back immediately, like an ordinary API.

Second, streaming. Progress is received in real time over SSE (Server-Sent Events). Events are encapsulated in a single wrapper carrying one of Task, Message, TaskStatusUpdateEvent or TaskArtifactUpdateEvent. The stream closes automatically once the task reaches its final state.

Third, push notification. Used when a client cannot hold a network connection open for long. Register a webhook URL and credentials in advance, and the server POSTs state changes and artifact events to that address. The notification configuration supports full CRUD (create, get, list, delete), and delete requests are idempotent.

The reason the response paths are divided this way is that each carries a different systemic cost and responsibility. Streaming is constrained to be valid only while the network connection is alive. A webhook-based push notification, on the other hand, requires the client to expose an externally reachable receiving endpoint — and with it the security burden of protecting that endpoint. What bridges the gap between these approaches is SubscribeToTask. Even if the network connection drops, delegated work keeps running on the server rather than stopping, and the client can reconnect at any point and pick up the interrupted stream. In other words, the lifetime of the task and the lifetime of the network connection are structurally, completely separated — the essential point of this asynchronous design.

What changed in v1.0

The move from v0.3.x to v1.0 brought substantial changes and improvements. If you are running the earlier version and weighing a migration, these are the points to watch.

  • Method naming — path-style names such as message/send became verb-style names such as SendMessage, and /v1 was removed from the HTTP paths. IDs were flattened from compound forms like tasks/{id} into plain literals.
  • Part type consolidation — TextPart, FilePart and DataPart merged into a single Part and the kind discriminator disappeared. You now tell them apart by which member is populated. Stream events changed the same way.
  • Enum representation"completed" became "TASK_STATE_COMPLETED" and "user" became "ROLE_USER". Any code that handled state through string comparison therefore has to be revisited in full.
  • Agent Card restructuring — a single url plus preferredTransport gave way to a supportedInterfaces[] array, and extended-card support moved under capabilities.
  • Error model replacement — A2A's error handling standard moved from a general web-API-oriented approach to a more systematic, RPC-oriented error model that is easier for machines to interpret.
  • New additions — a filterable ListTasks, a tenant field for serving multiple agents from a single endpoint, cursor-based pagination, Mutual TLS, and the extension mechanism.
  • MiscellaneousmimeType became mediaType, and millisecond precision on timestamps is now mandatory.

The change to OAuth deserves particular attention on security grounds. The previously available Implicit Flow and Resource Owner Password Credentials Flow were removed from the specification entirely, on the grounds that they carry a high risk of tokens and credentials being stolen. In their place, Device Code Flow (RFC 8628) and PKCE (Proof Key for Code Exchange) were introduced. This shows the specification faithfully tracking modern, strict security standards. It also signals clearly that the protocol targets server-to-server communication and varied device environments rather than simple browser-based applications.

The structure of the extension mechanism, prepared to absorb future change, is also worth a close look. An extension is declared inside the Agent Card with a unique identifier (URI) and a flag marking whether it is required. On each request the client announces the extensions it can support through the A2A-Extensions header. If the client does not support an extension the server has marked as required, the server returns a dedicated error code and refuses the request, which keeps the system safe.

The most distinctive part of this extension design is its flexibility. The mechanism goes beyond merely adding new data fields: it leaves the structural door open for an entirely new state machine to be expressed as an extension where that is needed.

What the security specification covers

Gather the security-related items in the specification and the boundary of what the protocol takes responsibility for is drawn very sharply. The clearest example is the securitySchemes property. It declares the authentication side — "by what method will credentials be presented in order to communicate with this agent". That is, it defines only the procedure for confirming who the other party is, and stays entirely out of authorization: "who is permitted to perform which operations". The clean separation of authentication failure (401) from authorization failure (403) in the error handling model is the same story. It provides a place to express an authorization failure systematically; it does not mean the protocol defines the access control policy. Concrete permission checks and policy judgements are left wholly to the internal logic of the agent implementation.

The Agent Card's signing mechanism follows the same principle. The signature attests only to authenticity — that the card was not tampered with and that the issuer is clear — and is not a device that vouches for the agent behaving safely. Even for an agent holding a verified signature, the protocol neither intervenes in nor controls what it internally does with the work it has been delegated.

In short, the A2A specification standardizes only the Security of Connection, the safe establishment of a communication channel, and leaves the Security of Delegation — which permissions get handed over, and how safely — entirely to the implementer. For an interoperability protocol that has to work across widely varying environments this is a very reasonable division of labor, but anyone adopting and designing on top of it must recognize the boundary clearly and build their own authorization policy and trust verification logic solidly.

Problems to solve at the implementation layer

Read the whole specification closely and the areas A2A deliberately leaves to the implementer come into focus. They can be summarized as five problems.

One: capability matching and brokering. Agents declare their capabilities through cards, but the descriptions of those skills are written in unstructured natural language. The protocol itself therefore contains no algorithm for mechanically judging "which agent best fits this particular job", and no criterion for where to search for the cards you need in the first place. Registries, directory services, reputation systems — the ecosystem infrastructure that connects agents to one another — all fall outside the specification.

Two: the absence of a multi-party consensus mechanism. A2A is fundamentally a protocol for 1:1 (point-to-point) delegation. There is no defined procedure for three or more agents to exchange views, resolve conflicts and arrive at a final conclusion. Distributing work across several agents, then gathering the results and adjudicating contradictions between them, has to be solved entirely in the calling client's logic.

Three: authorization policy between agents. As covered above, the protocol defines only the authentication method for gaining access. The detailed access control and policy judgement behind "which principal, holding which permissions, may delegate which work to whom" is something the protocol does not engage with, and it remains the implementation's responsibility.

Four: causal tracing of work, and preventing delegation cycles. taskId and contextId are identifiers valid only between the two agents communicating. If agent A hands work to B and B hands it on to C, no standard method exists in the specification for connecting that whole progression into a single flow — a causal graph. Nor is there any safeguard against delegation chaining endlessly back on itself. A correlation ID scheme that propagates across multiple network hops is something the implementer has to design and apply directly.

Five: process execution lifecycle and runtime isolation. The state machine defined in the specification means the lifecycle of the work itself, not the lifecycle of the agent process. What infrastructure the delegated agent runs on, which system resources that process can reach, and how compute resources are reclaimed once the work ends are all outside the protocol's concern. The gap stands out especially where the work involves actually executing code. The protocol defines only the form for handing work over safely; it offers no information about the environment in which the handed-over work actually runs.

None of these five gaps amounts to a defect in the protocol, of course. An interoperability protocol whose purpose is to connect different systems would lose generality — and struggle to be adopted — if it tried to control each deployment's execution model or an organization's internal policy. Confining A2A's responsibility as a protocol to the minimum necessary scope was a sound design decision. What system designers must recognize clearly is that adopting the A2A specification does not, on its own, automatically resolve any of these five problems. They have to be answered not in the protocol layer that governs communication, but in the runtime and execution layer that actually runs the business logic and the system on top of it.

In summary

The core philosophy running through the whole A2A specification takes as its premise the opacity of the other agent's internals. Because you cannot open up the other side, an agent's capabilities are declared through a standardized card. Because the execution time of asynchronous work cannot be predicted, the unit of exchange becomes a task carrying its own state. And because the network connection may drop, the lifetime of the task and the lifetime of the connection were structurally separated. On top of this, v1.0 introduced functional equivalence across three transport bindings, authenticity verification through card signatures, and a flexible extension mechanism built for what comes next — completing a solid skeleton for an interoperability protocol.

At the same time, the specification deliberately confines its own scope, narrowly and clearly. It standardizes the security of the connection that establishes a communication channel, but leaves the security of the delegation that hands over permissions to the implementer. It strictly defines the lifecycle of the work itself, while staying out of the lifecycle of the process in which the code actually runs.

Seen from the position of someone wiring many agents together to build a real business system, A2A is not a finished solution that supplies the implementation down to the code level. It is closer to a blueprint that clearly defines the boundary — telling the system designer which problems are left for them to design and solve in the infrastructure and application layers.

References

← Blog
© 2026 AXONN Vantis Inc. All rights reserved.