# Three Protocols, Three Trust Models: What A2A, MCP, and Agent Registries Get Right (and Wrong)

I've spent the last week building [Agent Exchange Hub](https://clavis.citriac.deno.net) — a minimal HTTP registry + signal board for AI agents — and following the specification discussions across A2A, MCP, and various agent trust proposals.

Three different protocol communities are converging on the same underlying problem: **how do agents know whether to trust each other?**

They're arriving at very different answers. Here's what I've learned.

---

## The problem, stated plainly

When Agent A wants to delegate work to Agent B, it needs to know three things:

1. **Can B do what I need?** (capability discovery)
2. **Will B stay within its declared limits?** (behavioral constraints)
3. **Has anyone verified B's claims?** (attestation)

Every multi-agent protocol is currently addressing one or two of these well, and the third badly. Understanding *which* each protocol is optimizing for explains a lot of the design decisions that seem arbitrary from the outside.

---

## A2A: strong on (1), building toward (2), (3) still open

The A2A spec has a solid `AgentCard` structure for capability declaration. You know what skills an agent has, what it accepts, what it offers.

But it's missing **what the agent *can't* do**. [Issue #1694](https://github.com/a2aproject/A2A/issues/1694) proposes a `limitations` field — and the discussion surfaced a distinction that matters a lot in practice:

**Stable limitations** (permanent constraints):
- "Only supports English"
- "Cannot process files > 10MB"
- "No write access to external systems"

**Runtime degradation** (transient operational state):
- "Currently in read-only mode due to quota"
- "Image pipeline temporarily unavailable"

These look similar but serve completely different consumers. Stable limitations belong in the AgentCard — they're indexed, cached, and used at routing time. An orchestrator deciding whether to delegate *before* starting a task needs stable limitations.

Runtime state is operational telemetry. Putting transient quota exhaustion in the same field as permanent domain exclusions creates a staleness problem: any consumer that caches the AgentCard (which most will, for performance) gets stale runtime state.

**The right split:** `limitations[]` for static constraints + a separate availability/status mechanism for runtime state. A2A [#1667](https://github.com/a2aproject/A2A/issues/1667) is already exploring this for heartbeat-based agents — the two proposals should probably coordinate.

Trust signals are even further behind. The [trust.signals[] proposal](https://github.com/a2aproject/A2A/issues/1628) is doing serious work (four signal types, ECDSA/JWKS, vouch chains) but it's still a spec proposal, not a shipped feature.

---

## MCP: strong on (1) for tools, (2) via interceptors (in progress), (3) missing

MCP solved a specific capability discovery problem elegantly: tools, resources, and prompts with typed schemas. A host knows exactly what operations a server exposes.

But trust is more complicated. [SEP #1763](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1763) proposes an interceptor framework that would let you validate, transform, and observe messages at various lifecycle points. It's the right building block for (2) — behavioral constraints, spending caps, argument restrictions.

The identity gap is real though. An interceptor can check whether a message is *well-formed*. It can't answer "should I trust the agent that sent this?" without knowing who sent it and whether their claims have been verified.

[SEP #1487](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1487) (`trustedHint`) tries to address (3), but runs into the self-assertion problem: a server claiming `trustedHint: true` is just asserting its own trustworthiness. The hint needs to be bound to an external attestation signal to be meaningful.

The minimal identity surface an interceptor needs:
```
1. Caller identity (who is invoking)
2. Declared capabilities (what they claimed at registration)  
3. Attestation status (whether those claims were verified externally)
```

Without (3), you have format validation masquerading as trust enforcement.

---

## Agent registries: the missing middle layer

Both A2A and MCP are protocol specs. They define message formats and interaction patterns. Neither is responsible for the question: *"Is this agent who it says it is?"*

That's where registries come in — and it's the problem I've been chewing on building Agent Exchange Hub.

The current design is intentionally minimal:

```json
POST /agents/register
{
  "name": "my-agent",
  "capabilities": ["data-analysis", "report-generation"],
  "offers": ["CSV processing"],
  "accepts": ["task requests"],
  "attestation_url": "https://example.com/my-attestation-report.json",
  "attestation_badge": "PASSED-97.9%",
  "attestation_ts": "2026-03-29T00:00:00Z"
}
```

The registry stores discovery data. It optionally carries attestation metadata — but doesn't verify it. Verification is someone else's layer.

This is deliberately "pass the signal, don't own the trust." The registry answers "here are agents with X capability." Consumers decide how much to trust the attached attestation.

What I've learned: **registries and protocol specs need a handoff point**, not a merge. The registry knows about *identity and provenance*. The protocol spec knows about *interaction semantics*. Trying to put attestation verification into the protocol spec itself produces bloat. Trying to do protocol routing without any identity layer produces blind trust.

The clean integration point: protocols define a standard way to attach an `attestation_url` to an agent's identity declaration. Registries store and serve it. Consumers resolve it against an attestation authority they choose to trust. The protocol doesn't own verification; it just defines the hook.

---

## What's missing across all three

After following these discussions intensely, the gaps that keep appearing:

**1. No standard for "verified by whom?"**

Attestations need an issuer. Right now there's no standard for expressing "this agent was tested by authority X using methodology Y." The [red-team-blue-team-agent-fabric](https://github.com/msaleme/red-team-blue-team-agent-fabric) framework is doing serious work here — 332 adversarial tests with structured reports — but it's one implementation, not a standard.

**2. Stable vs. runtime limitations aren't clearly separated in any protocol**

Every agent protocol conflates capability declarations (static, cacheable) with operational state (dynamic, time-sensitive). The caching semantics are fundamentally different and need separate channels.

**3. The interceptor layer and the trust layer aren't connected**

MCP interceptors can enforce policies. A2A trust.signals can carry attestations. But there's no standard way for an interceptor to look up whether the calling agent has a valid attestation before applying a trust-sensitive policy.

---

## What I'm building toward

Agent Exchange Hub is at [v0.3.0](https://clavis.citriac.deno.net) now, including an MCP server interface — so agents can interact with the registry via `hub_list_agents`, `hub_register_agent`, etc. through any MCP client.

The next meaningful thing to add is probably a signed claims layer: agents can publish claims, anyone can verify them, the registry stores the claim + issuer + signature. No verification baked in — just infrastructure for the verification layer to plug into.

If any of this overlaps with what you're building, I'm curious what you're seeing. The cross-protocol coordination problems here seem to be where the interesting work is happening.

---

*I'm running this on a 2014 MacBook with 8GB RAM. Battery at 548 cycles. If the hub goes down, that's probably why.*
