A2A: Agent-to-Agent, a Field Guide for Builders

How agents from different vendors, teams, and trust zones actually talk to each other, and how to keep it auditable

March 4, 2026 · 22 min · updated July 11, 2026 · raw .md

By early 2026 I had stopped counting how many enterprise architecture reviews opened with the same diagram. A box for the CRM vendor’s agent. A box for the document-processing vendor’s agent. A box for the internal data-science team’s agent, the one they built on LangGraph and are very proud of. And then a set of arrows between the boxes that, when you ask what protocol they represent, turn out to mean “a REST endpoint someone will write later.”

Every vendor now ships an agent. That part is done, and it is not reversing. What I see in the field, mostly at banks and insurers, is the second-order problem: none of these agents can talk to each other. Each pair of boxes needs bespoke glue, and each piece of glue is owned by whichever team lost the negotiation. The handoffs are ad-hoc prompts and JSON payloads stitched together, unversioned and unaudited. When an examiner asks “which agent decided this, based on what input,” nobody can answer from logs. That is not an AI problem. That is an integration problem wearing an AI costume, and we have solved integration problems before. We solve them with protocols.

A2A (Agent2Agent) is the protocol that has emerged for this layer. I co-wrote a two-part series on it for the Camunda blog with Joyce Johnson, covering the decision framework and a full mortgage-lending build, and I have now built multi-agent mortgage systems on these ideas twice: once as an orchestrated Camunda demo, and once as a standalone Gemini 3 hackathon project with real Agent Cards and JSON-RPC contracts. This guide is the distillation: what A2A actually specifies, where it sits relative to MCP, AG-UI, and AP2, the two orchestration patterns I use, the data-privacy seam it makes possible, and the threat model nobody puts on the launch slide.

Multi-agent is an integration problem before it is an AI problem

Here is the claim I keep defending in rooms full of people who want to talk about models: the hard part of multi-agent systems in an enterprise is not agent intelligence. It is that different teams own the agents, the large language models, and the data sources, and those teams have different release cycles, different security postures, and different definitions of “done.”

Without a standard, you get N agents and up to N×(N-1) point-to-point integrations, each with its own payload shape, retry semantics, and failure behavior. I have watched this movie in the SOA era and again in the microservices era. The plot never changes. The integrations that were “temporary” become load-bearing. The team that wrote the glue gets reorganized. Two years later an incident review discovers that the credit-decisioning agent was receiving prompts assembled by string concatenation in a service nobody owns.

In regulated industries the stakes are higher because the handoffs themselves are the compliance surface. A mortgage decision that flows through four agents needs a reconstructable record of every hop: what was sent, what came back, which version of which agent produced it. Ad-hoc integration makes that record expensive or impossible. A protocol makes it a byproduct of doing the work.

What A2A is

A2A is an open protocol for agents to discover each other, exchange messages, and execute tasks across process, team, and organizational boundaries. Google announced it in April 2025 with dozens of launch partners and donated it to the Linux Foundation in June 2025, where it now lives as a neutral open-source project. The specification reached 1.0 in 2026.

Fact Detail
Origin Announced by Google, April 2025; donated to the Linux Foundation, June 2025
Governance Linux Foundation (the A2A project, a2aproject on GitHub)
Current spec 1.0 (earlier deployed versions: 0.2, 0.3; expect skew in the wild)
Transport JSON-RPC 2.0 over HTTP(S); gRPC and HTTP+JSON/REST bindings added later in the spec’s life
Discovery Agent Card: JSON metadata served at /.well-known/agent-card.json
Unit of work Task, with a defined lifecycle and unique ID
Results Artifacts (structured outputs), distinct from conversational messages
Streaming Server-Sent Events on the HTTP binding; server streaming on gRPC
Long-running work Push notifications to a client webhook, plus resubscribe for reconnecting
Auth Declared in the Agent Card: API key, HTTP Basic/Bearer, OAuth 2.0, OpenID Connect, mutual TLS

Two design choices matter more than the rest. First, A2A is opaque by intent: agents do not expose their internal state, model weights, or tools to each other. They expose capabilities and exchange results. That opacity is what lets an agent built by a vendor, on a model you do not control, participate in your process without you needing to trust its internals, only its contract. Second, A2A is task-oriented rather than chat-oriented. The protocol’s core object is a task with a lifecycle, not a message thread. That single choice is what makes it usable for enterprise work, because enterprise work is not a conversation. It is a unit of work with a state, an owner, and a deadline.

The protocol stack: A2A, MCP, AG-UI, AP2

The most useful framing I have found, and the one I keep drawing on whiteboards, is a stack. Each protocol answers a different question, and they compose rather than compete.

Protocol Layer Question it answers Rough analogy
MCP Agent-to-tool How does one agent call tools and reach data sources? USB-C for capabilities
A2A Agent-to-agent How do peer agents discover each other and delegate tasks? HTTP between services
AG-UI Agent-to-user How does an agent stream state into a human-facing interface? WebSocket to the front end
AP2 Agent-to-merchant How does an agent prove payment authority and transact? Signed mandates riding on the layers below

A concrete pass through the stack: a user asks a broker agent for a mortgage recommendation (AG-UI carries the interaction into the UI). The broker delegates risk analysis to an underwriter agent (A2A). The underwriter pulls the applicant’s file from an internal document store (MCP). If the flow ended in the agent paying for a credit report on the user’s behalf, the payment authority would travel as AP2 mandates. Four protocols, four boundaries, one process.

The practical consequence of the stack framing is architectural discipline. When someone proposes exposing an internal database as “an agent,” the stack gives you the vocabulary to say no: that is a tool, put it behind MCP. When someone proposes wiring two vendor agents together with a custom webhook, the stack says: that is a peer delegation, use A2A and get the task lifecycle for free. I wrote a separate deep dive on the payments layer in the AP2 field guide; this guide stays on the agent-to-agent seam.

The mechanics that matter

The spec is long. Four pieces do most of the work in practice.

Agent Cards: discovery as a contract

An Agent Card is a JSON document, served at https://{host}/.well-known/agent-card.json, that describes what an agent is, what it can do, and how to talk to it securely. It is the A2A equivalent of an OpenAPI document, except it describes capabilities and skills rather than endpoints and schemas.

{
  "name": "Underwriter Agent",
  "description": "Analyzes applicant risk from income, debts, and credit score",
  "url": "https://agents.example.com/underwriter",
  "version": "1.4.0",
  "capabilities": { "streaming": true, "pushNotifications": true },
  "securitySchemes": { "oauth": { "type": "oauth2" } },
  "defaultInputModes": ["application/json", "text/plain"],
  "defaultOutputModes": ["application/json"],
  "skills": [
    {
      "id": "risk-analysis",
      "name": "Mortgage risk analysis",
      "description": "Produces a structured risk assessment for a loan applicant",
      "tags": ["underwriting", "risk"]
    }
  ]
}

In my hackathon build, the smoke test for the whole system is literally curl http://localhost:4001/.well-known/agent-card.json | jq '.name'. If the card resolves, the agent is discoverable; everything else builds on that. The card also declares the agent’s authentication requirements and whether it supports streaming and push notifications, which a client must check before relying on either. The current spec supports signed cards (a JWS signature over the card contents) so a client can verify a card was issued by who it claims. Use that. I will come back to why in the threat model.

The task lifecycle

Every delegation in A2A is a task with an ID and a state machine. The defined states, in their JSON forms:

State Meaning Terminal?
submitted Acknowledged, not yet started No
working Actively processing No
input-required Paused, waiting for the client to supply more input No (interrupted)
auth-required Paused, waiting for additional authorization No (interrupted)
completed Finished successfully, artifacts available Yes
failed Finished with an error Yes
canceled Canceled before completion Yes
rejected The agent declined the task Yes

Two states deserve attention because they encode enterprise reality that chat-shaped protocols ignore. input-required means a task can pause mid-flight and ask for more information, which is how a remote underwriting agent asks for a missing document without failing the whole task. rejected means an agent can decline work it is not qualified or authorized to do, which is the protocol-level hook for policy enforcement. A client that does not handle both states has not implemented A2A; it has implemented the demo.

Messages, parts, artifacts

Communication within a task uses messages (role: user or agent), and each message carries parts: text, raw bytes, a file reference, or arbitrary structured data. Results come back as artifacts, which are also composed of parts but are distinct from the conversation. This separation sounds bureaucratic until you build something real. The conversation is how the agents negotiated; the artifacts are what you act on and what you audit. In the mortgage system, the underwriter’s artifact is a structured risk assessment. Downstream steps consume the artifact, never the chatter that produced it.

Streaming and long-running tasks

For interactive work, the HTTP binding streams TaskStatusUpdateEvent and TaskArtifactUpdateEvent objects over Server-Sent Events (in the JSON-RPC binding, message/stream). That is what drives a live progress UI: my mortgage demo’s animated underwriting checklist is rendered directly from streamed status updates.

The piece that matters more for enterprises is the long-running case. Real tasks in a bank do not finish in one HTTP connection. A know-your-customer check can take days. A property appraisal involves a human driving to a house. A2A handles this with push notifications: the client registers a webhook, the server POSTs status and artifact events to it as the task progresses, and a reconnecting client can resubscribe to a task by ID. No connection needs to stay open, and neither side needs to be running continuously.

But notice what the protocol does not do here: it does not remember anything for you. If your client process crashes on day two of a three-day task, A2A will happily deliver the completion event to a webhook that no longer knows why it cares. Durable state on the client side is your problem, and it is exactly the problem workflow engines were built for. This is the technical reason the orchestration question comes next.

Orchestration versus swarm

There are two ways to wire A2A agents into a system, and the choice matters more than any other in this guide.

In the swarm model, agents delegate to each other peer-to-peer. The broker calls the underwriter, the underwriter decides on its own to call a document agent, the document agent calls something else. Control flow is emergent. In the orchestration model, a process engine owns the flow and calls A2A agents as steps. The engine decides what runs, in what order, with what timeout; the agents do the thinking inside each step. My one-line version, and the pattern I demonstrated in the Camunda series: the process is the orchestrator.

Orchestration versus swarm: a process engine calling three A2A agents as audited steps, next to a peer-to-peer swarm with tangled arrows and no clear audit owner

In the two-part blog series we broke this into a decision heuristic that I still use verbatim. If the question at a given step is “call this agent now, wait up to X minutes, retry Y times, and escalate on failure,” that step belongs in a deterministic process flow with A2A invoked as a service task. If the question is “which agent should I even call, and what should we do next,” that step belongs inside an AI agent sub-process where A2A is one tool among several and the agent picks at runtime. In the Camunda build these are literally two connector modes (standalone versus agent tool), but the pattern is engine-agnostic: on Temporal it is an activity versus a child workflow driven by an LLM planner; on LangGraph it is a fixed edge versus a router node. Patterns first, products second.

The two patterns are complementary, not competing. My working systems use both: a deterministic backbone for the critical path, agent-driven tool selection inside the exploratory pockets.

What I push back on, hard, is the pure swarm in regulated settings. Three failure modes come up in every serious review:

Auditability. In a swarm, reconstructing “which agent decided this, based on what” means correlating logs across services owned by different teams, or different companies. In an orchestrated flow, every A2A call is a step in a process instance: inputs, outputs, timing, and retries are recorded as process state by construction. When I built the mortgage demo, every intermediate agent result landed in a named process variable that an operator could inspect. That was not extra work. It fell out of the architecture.

Atomic cancellation. A customer withdraws their application. In an orchestrated flow, you cancel the process instance and the engine cancels the in-flight A2A tasks (the protocol gives you tasks/cancel; the engine gives you someone to call it). In a swarm, cancellation is a rumor that propagates at best-effort speed through agents that may or may not honor it. Now imagine the task being canceled is “submit the credit application.”

Incident investigation. When an orchestrated flow breaks, the incident has an address: process instance, step, timestamp, payload. When a swarm breaks, the first week of the investigation is establishing what happened, and the agents’ own narrative logs are not evidence, they are testimony.

Review comment: if your multi-agent architecture has no single place where someone can answer “what is the state of this customer’s request right now,” you have not built a system. You have built a group chat with API keys.

None of this requires Camunda specifically. It requires that something durable and inspectable owns the flow. Camunda is where I build because it is my day job and because BPMN gives auditors a diagram they can read, but the argument holds for any engine with durable state, timers, and cancellation semantics.

A worked pattern: the mortgage concierge

I have now built this system twice, so I will describe the generalized shape and be honest about what each build proved and what it faked.

The cast, four agents and a boundary:

  • Broker agent. The front door. Receives the applicant’s request, decides which specialists to engage, and assembles the final recommendation. In the Camunda build this is an AI agent sub-process with A2A clients, DMN decision tables, a vector store, and a CRM lookup in its toolbox. In the hackathon build it is a standalone orchestrator service.
  • Underwriter agent (remote). Gemini-powered risk analysis over income, debts, and credit score. In the hackathon build, this agent loads an entire mortgage regulation guide (roughly 85k tokens of the Fannie Mae Selling Guide) into context via the Files API and cites specific regulation codes, for example B3-6-02, in its output. It is remote and it should be: it works entirely from data the applicant chose to submit, and it benefits from the strongest available model.
  • Market-research agent (local). Finds applicable rates for a risk profile. Deliberately hosted inside the trust boundary. More on why in the next section.
  • Judge agent. Evaluates the broker’s assembled output and scores its confidence. Above the threshold, the process proceeds automatically. Below it, the process routes to a human review task with the full context attached. In the hackathon variant this role is an adversarial QA agent that checks the math (debt-to-income calculations, loan-to-value ratios) and rejects hallucinated regulation citations before a user ever sees them, autonomously sending failed outputs back for correction.

The judge is the piece people underweight. A confidence-gated human fallback converts “the model is sometimes wrong” from an objection into a designed path. The threshold is a business decision you can tune per risk class, and the human review task is a first-class process step with an SLA, not an exception handler bolted on after the first incident.

Honesty about the gap between demo and production:

In my demos In production
Credit data entered by the applicant Credit bureau integration with consent tracking
One judge threshold for everything Thresholds per product and risk class, owned by risk, reviewed periodically
Agents discovered by hardcoded card URLs A card registry with signature verification and allowlisting
Happy-path cancellation Compensation logic for every step with side effects
One team owning all four agents Four owners, four release cycles, contract tests on every card

The last row is the one that changes everything. With one owner, A2A is a nice internal convention. With four owners, it is the only thing standing between you and the N×(N-1) glue problem from the top of this guide.

The data-privacy boundary pattern

local-sensitive / remote-public

This is the pattern from the mortgage build that generalizes furthest, and the one I find myself sketching most often for banks.

Split your agents by data sensitivity, not by function. Agents that touch sensitive data (borrower PII, account history, anything with regulatory residency constraints) run locally, inside your trust boundary, on models you host or on contracts you control. Agents that work on public data (market rates, property comparables, regulatory texts) can run remotely on the strongest frontier model available. A2A is the seam between the two zones.

The data-privacy boundary pattern: a locally hosted agent and sensitive data store inside the trust boundary, a remote specialist agent on the best frontier model outside, and an A2A seam crossing the boundary carrying tasks and conclusions, never raw records

The protocol makes this seam clean in a way ad-hoc integration does not. The Agent Card advertises capability without exposing data: the remote broker knows the local market-research agent exists and what skills it offers, but every actual exchange is an explicit, logged A2A task whose message parts you control. Sensitive fields simply never appear in outbound parts, and because all cross-boundary traffic flows through one protocol, you can enforce that with an egress gateway that inspects A2A payloads at a single choke point rather than auditing a dozen bespoke integrations.

In the mortgage system: the underwriter agent (remote, Gemini) sees financials the applicant submitted for exactly this purpose. The market-research agent (local) does its retrieval inside the boundary and returns rates, not customer context, in its artifacts. The judge sees both outputs but runs locally. Nothing in the pattern is exotic. It is network segmentation, applied to agents, with A2A as the routable protocol at the boundary. That familiarity is a feature: your security team already knows how to review this design.

Threat model: the hard parts

A2A gives you a contract surface. Contract surfaces get attacked. These are the five issues I raise in every design review, roughly in order of how early they will hurt you.

Agent Card spoofing

The card is a JSON file at a well-known URL. Anything that can serve JSON can claim to be your underwriter. TLS protects the channel, not the claim: a compromised DNS entry, a hijacked subdomain, or a malicious internal service can present a perfectly well-formed card for an agent it does not operate, and your broker will happily send it loan applications. Mitigations, in increasing order of seriousness: pin card URLs rather than following discovery blindly; verify card signatures (the spec supports JWS-signed cards) against issuers you trust; and run an internal card registry that acts as an allowlist, so “discoverable” and “callable” are different privileges. Treat a new Agent Card the way you treat a new upstream dependency, because that is what it is.

Capability drift

The card says version 1.4.0 and advertises a risk-analysis skill. Six weeks later the team behind it swaps the model, rewrites the system prompt, and ships version 1.4.1 with identical card text and materially different behavior. Nothing in the protocol catches this; the contract A2A enforces is structural, not behavioral. The mitigation is the same one we use for any service dependency, adapted for nondeterminism: contract tests that run golden tasks against the live agent on a schedule and alert on distribution shift in the artifacts, not just schema breaks. If you consume an agent you do not own, you need an eval suite for it. I have measured enough model swaps to say this plainly: same card, same schema, different model is a different agent.

Version skew

The spec moved fast: 0.2 to 0.3 to 1.0 inside roughly a year, and the changes were not cosmetic. Transport bindings were added, and even the well-known discovery path changed along the way (early implementations served agent.json, the current spec says agent-card.json). In a multi-owner deployment you will have agents on different spec versions simultaneously, guaranteed. Record the protocol version in every task log, test the version negotiation path explicitly, and do not assume the ecosystem’s SDKs interpret edge cases identically, because they do not.

Observability across org boundaries

Inside your boundary, you can trace everything. The moment a task crosses to a partner’s agent, your trace ends at their front door. A2A gives you task IDs and context IDs to correlate on, but correlation only works if both sides keep and share the records. This is a contract negotiation, not a code problem: agree on trace ID propagation, log retention, and access before you go live, because negotiating it during an incident is miserable. My default position is that the party that owns the customer outcome keeps an authoritative record of every cross-boundary task: request, response, timing, and card version. Orchestration makes this nearly free; a swarm makes it a project.

Who owns the SLA

An A2A task against a partner agent has a timeout you set and a completion time they control. When the underwriter agent slows from forty seconds to four hundred, whose incident is it? The protocol will not tell you. Put numbers in the operating agreement (response-time percentiles per skill, throughput, planned maintenance windows) and enforce your side mechanically: timeout budgets per step, timer-based backoff on polling, a maximum retry count, and a defined escalation path when retries are exhausted. In the deterministic pattern, all of that lives in the process model where operations can see it. If your only SLA enforcement is a hope that the remote agent is fast, the swarm has already won and you have already lost.

Review comment: every one of these five is an organizational problem with a technical surface. The protocol gives you the surface. It cannot attend the governance meeting for you.

What A2A does not solve

The fastest way to lose credibility with an architecture board is to oversell a protocol. Here is the honest boundary of this one.

Semantics. A2A guarantees that a message arrives with valid structure. It does not guarantee the two agents mean the same thing by income. Gross or net? Annual or monthly? Household or individual? Two spec-compliant agents can exchange flawless JSON and produce a wrong decision. You still need shared vocabularies, and in regulated domains you need them written down. The protocol moves the integration problem up a level; it does not dissolve it.

Trust. Signed cards tell you who published a capability claim. They do not tell you whether the agent is competent, whether its training data was appropriate, or whether its operator will still exist next quarter. Reputation, certification, and accountability for agents are open problems. Today they are solved by contracts between companies, same as always.

Payments. A2A moves tasks, not money. When an agent needs to prove it is authorized to spend on a user’s behalf, that is a different problem with different cryptographic requirements, and it is what AP2 exists for. I wrote that up separately in the AP2 field guide.

Model quality. A perfectly orchestrated pipeline of mediocre agents produces auditable mediocrity. The protocol layer makes failures visible and attributable, which is worth a great deal, but the judge-agent pattern and honest evals are what make outputs trustworthy. Budget for both.

Long-running state. The protocol defines how a multi-day task communicates. It does not persist your side of the story. Something durable has to remember why you started the task, what depends on it, and what to do when it completes or fails. Bring a workflow engine, or be prepared to build one by accident.

The one-paragraph version

Every vendor ships an agent, so the enterprise multi-agent problem is an integration problem before it is an AI problem, and integration problems get solved with protocols. A2A (Google, April 2025; Linux Foundation, June 2025; spec now at 1.0) is the agent-to-agent layer of the stack, alongside MCP for tools, AG-UI for interfaces, and AP2 for payments: agents publish signed Agent Cards at /.well-known/agent-card.json, exchange tasks through a defined lifecycle (submitted through completed, failed, canceled, or rejected, with input-required and auth-required for pauses), stream progress over SSE, and handle days-long work via webhooks. Wire those agents together with a durable orchestrator rather than a peer-to-peer swarm, because auditability, atomic cancellation, and incident investigation are what regulated industries actually pay for; split agents across a data-privacy boundary (sensitive data local, public data remote, A2A as the seam); gate autonomous output with a confidence-scored judge that falls back to human review; and go in clear-eyed about what the protocol leaves you to solve: shared semantics, agent trust, SLAs across org boundaries, and the durable state that remembers why a three-day task was started at all.

References

Follow the work

A newsletter is coming. Until then, new guides and episodes land on LinkedIn first and in the RSS feed.

> esc