← The Harness
CONNECT The Harness 2026-Q3

Where A2A Begins and Ends

A2A hit v1.0 in April, and MCP's extension catalog made the two protocols look alike on paper. The actual boundary is stance: compose a transparent workbench, or delegate to an opaque peer.

Companion to Agents Get a UI.

Your coding agent lives in Codex or Claude Code. Your designer’s agent lives in whatever their tool ships with. Your vendor runs one behind their own login, your accountant’s firm runs another, and the ops team has a fleet nobody outside the building can see. None of them are going to move into your chat window because that would be convenient for you.

The work worth doing next spans all of them. Somebody’s agent needs to ask your agent for last quarter’s numbers and get back something it can act on, without either side adopting the other’s vendor, model, or client. An interop layer is what makes that ordinary instead of a custom integration project every time. Two protocols carry that traffic today, and they spent 2026 growing into each other’s feature lists, so telling them apart has gotten harder exactly when more people need to choose between them.

MCP, A2A, and skills

Three names get thrown around in the same breath, and they answer different questions.

MCP (Model Context Protocol) is how you hand an agent a set of tools. You run a server, it advertises tools with JSON schemas, and the calling model reads those schemas and decides what to invoke. The caller keeps the plan. Anthropic shipped it in late 2024, and it’s why a chat client can read your calendar or query your database without anybody hard-coding that integration. The 2026-07-28 revision added inline UI, durable tasks, and an extension catalog.

A2A (Agent2Agent) is how you hand work to somebody else’s agent. There’s no tool list. The remote side publishes an agent card saying what it can do, you send it a message, and you get back a task you can poll or a refusal. Their model does the reasoning. Google released it in April 2025 and it’s been under Linux Foundation governance since.

Skills aren’t a protocol at all. A skill is a markdown file on disk that teaches the agent a procedure: when to reach for it, the steps to follow, and pointers to whatever reference it needs. No server, no wire, no handshake. The agent reads it into context and works from it, which is why a good skill file is mostly an exercise in writing clearly and pruning ruthlessly.

Sort them by where the work happens. Skills stay inside the context window and drive whatever’s already on the machine, so they cost tokens and nothing else. MCP and A2A both reach outside the process and pay network, auth, and latency for the privilege. Laurie Voss’s eval at AI Engineer Miami put numbers on that gap, with correctness a wash and MCP heavier on calls, latency, and cost. The conclusion wasn’t that one wins. Real agents run all three, and the interesting question is which one a given job deserves.

A2A is at v1.0.0. It shipped April 9, 2026 under Linux Foundation governance, with 150+ organizations, SDKs in five languages, and production deployments at the one-year mark. The v1.0 spec is a serious revision. Versions ride an A2A-Version header (unversioned requests default to 0.3). The data model is Protocol Buffers with three equivalent bindings (JSON-RPC, gRPC, REST). ListTasks finally exists. The task lifecycle grew auth_required and rejected states. Agent cards can be signed, and extensions are declared on the card, with a required: true flag that lets an agent refuse clients that don’t speak them.

Two breaking changes (the kind discriminator is gone; the extended-card field moved) mean the 0.2.x-era code most of us run is now two eras behind. Our own bench still pins protocolVersion: 0.2.5 on its agent cards. Nothing is on fire yet, because everything still speaks 0.3 by default. But “A2A” no longer means what your 2025 SDK thinks it means.

Meanwhile MCP’s 2026-07-28 revision grew task handles, a discovery RPC, and an extension catalog, and A2A 1.0 arrived with its own extensions and UI story. Line the two specs up feature by feature and they nearly rhyme. Line them up by stance toward the remote party and the boundary is sharp.

Composition versus delegation

The 2025 framing said MCP connects agents to tools and A2A connects agents to each other. That was useful, and it no longer holds as a sorting rule, because both sides landed on the same primitives. MCP has tasks (polling, mid-flight input, cooperative cancel); so does A2A. MCP has server/discover; A2A has the agent card. MCP has negotiated extensions; A2A has card-declared extensions. MCP has MCP Apps; A2A has A2UI.

MCP is a transparent workbench. The whole protocol is capability enumeration: list the tools, read their schemas, compose them. The caller’s model does the reasoning; the server executes narrow, described operations. The schema is the interface. The caller sees every knob, which is why Chrome DevTools’ line that “the schema is the UI for the agent” sits at the center of the design.

A2A is an opaque peer. There is no tools/list and there never will be. You don’t enumerate another agent’s insides. You read its card (what it says it can do), send it a message, and get back a task you can poll, or a refusal. The remote model does the reasoning. What crosses the wire is intent and outcome, not capability and invocation.

Everything else falls out of that distinction:

  • Session. MCP went aggressively stateless, so the conversation is the caller’s state. A2A’s contextId exists because an opaque peer keeps its own memory of you; the session lives on their side.
  • Trust surface. MCP’s unit of consent is the tool call, and the host can gate each one. A2A’s unit is the relationship: signed cards, security schemes, and now an auth_required task state where the remote agent pauses mid-task to make a human authenticate. That state has no MCP equivalent, and it shouldn’t live on a workbench; it belongs to delegation.
  • Time horizon. Both have tasks now, but MCP’s task extension exists so a tool call can outlive an HTTP request. A2A’s task is the product: submitted → working → input-required → completed is the shape of handing work to something that owns it, including rejected, because a peer may decline and a toolbox won’t.
  • Failure meaning. An MCP tool error means your plan failed. An A2A task failure means their attempt failed. That difference decides who has to re-plan.

Choose the steps, or name the outcome

Reach for MCP when you want to choose the steps. Reach for A2A when you want to name the outcome. If the caller should see the schemas, pick the calls, and stay responsible for the plan, speak MCP. If the caller should say “reconcile this quarter against the statement of work” and come back tomorrow, speak A2A, and let the task lifecycle (and its interrupts) carry the relationship.

The moment you find yourself wanting to enumerate a peer’s tools, you’ve decided you don’t trust it to plan, which means you needed a workbench. The moment your MCP server wants to keep a conversation going with its caller, it has become an agent; give it a card.

One implementation can answer on both. Our habitat containers expose the same agent through /mcp and /a2a, one tool registry and one task store behind both doors, which is the standards line we already follow (one definition, projected to every surface) applied to protocols. The seam turns out thinner than the diagrams suggest. UI resources ride both wires. A task minted under one surface resolves under the other. Delegation chains cross container boundaries with a recursion guard in message metadata. What the shared implementation can’t decide for you is which door a given caller should be knocking on, and that stays a design call every time.

What to do this quarter

Check what protocolVersion your agent cards declare and what your SDK emits. v1.0’s header-based negotiation and breaking changes will show up as mystery interop failures with newer peers. If you’re designing a new surface, run the rule of thumb before picking a protocol. The convergence means both will seem to work, and only one will still make sense when the other side changes.

One field note on that upgrade, because we sized it on our own bench before recommending it: the JS SDK’s 1.x line is a rewrite. Calling it a version bump undersells the work. The types are protobuf-generated end to end (numeric task-state enums, oneof message parts). The 0.3 compatibility layer covers the wire while leaving the programming model alone. The streaming contract dropped the final flag, so stream termination belongs to the transport. If your server logic ever depended on ordering events around final: true (ours did, on purpose), the migration is a redesign of that logic, verified against a live peer. Budget for that. “Update the dependency” is the wrong line item.