Agent Interoperability — ACP & ANP
A2A isn't the only agent-interop protocol. ACP (Agent Communication Protocol) and ANP (Agent Network Protocol) tackle nearby-but-different problems. This chapter maps the wider landscape so you can tell the protocols apart, understand what each optimizes for, and reason clearly in a space that is still consolidating.
Learning objectives
- Explain what ACP optimizes for and how it differs from A2A.
- Explain ANP's decentralized, open-network ambition and why identity is central.
- Place MCP, A2A, ACP, and ANP on one map by what they connect and at what scope.
- Reason about an emerging, unconsolidated standards space without over-committing.
- Extract the durable principles that outlast any single protocol.
Why several protocols? intermediate
"Let agents interoperate" isn't one problem — it's several, and different groups attacked different slices. Understanding the slice each targets is the whole game. Three axes separate them:
| Axis | The question it answers |
|---|---|
| What connects? | Agent↔tools (MCP) vs agent↔agent (A2A/ACP/ANP) |
| What scope? | Within a system · across organizations · across an open public network |
| What's centered? | Task delegation · message passing · decentralized identity & discovery |
ACP — Agent Communication Protocol intermediate
ACP focuses on a standard message/communication layer between agents, with an emphasis on a RESTful, framework-neutral way for agents to exchange messages — including local and offline-friendly scenarios, not only cross-cloud calls. Where A2A centers on delegating a task to a remote peer, ACP centers on the communication substrate agents use to talk, aiming to be simple to adopt from any stack.
| ACP emphasis | Contrast with A2A (I2) |
|---|---|
| A general message layer between agents | A2A centers the task lifecycle (submitted→working→done) |
| REST-style, framework-neutral, easy adoption | A2A centers discovery via the Agent Card |
| Works for local/edge/offline too | A2A is oriented to remote, cross-org calls |
ANP — Agent Network Protocol intermediate
ANP aims higher and wider: an open, decentralized network of agents — think "an internet for agents" — where any agent can discover and interact with any other, across owners, without a central broker. Because there's no central authority in that vision, ANP puts decentralized identity (e.g. DID-style identifiers) and verifiable descriptions at the center — an agent must be able to prove who it is to strangers on an open network.
This picture contrasts two shapes of agent-to-agent connection. The left side is how A2A and ACP normally work; the right side is the bigger, more open world ANP imagines. Read it left-to-right as a jump in scale.
- On the left ("A2A / ACP: point-to-point") you see two labelled
agentboxes with a single arrow between them. That arrow is one connection to one agent you already know about — a known peer you deliberately arranged to talk to, sitting on the other side of a boundary (a different team, company, or network). - On the right ("ANP: open mesh") the small circles are many agents and the lines criss-crossing between them are connections that form on the fly. No single agent is the hub — any agent can reach any other. That web-of-lines shape is what "open network" means.
- The captions under each side are the takeaway: left = known peer, across a boundary (you set it up in advance); right = any agent discovers any agent, identity-first (agents meet as strangers).
- Why "identity-first" on the right? With no central broker vouching for anyone, each agent must prove who it is before others trust it — hence verifiable identity is the foundation of the open-mesh vision.
In short: Point-to-point is like phoning a contact you already saved; the open mesh is like anyone on the internet being able to call anyone — which only works if callers can prove who they are.
The unified map advanced
Put all four protocols from this module on one picture. Read it by what connects and at what scope — that's how you place any new protocol you meet.
This is a 2-axis map that places all four protocols from the chapter in one picture. It answers two questions at once: what does each protocol connect (the rows, going down) and how far does it reach (the columns, going right). Read a box by where it sits in the grid.
- The columns are scope, widening left→right:
within(inside your own system) →cross-org(between organizations) →open network(out among strangers). The two vertical lines just separate these three zones. - The rows, top→bottom, are what connects: the top band is agent↔tools, the middle is agent↔agent, the bottom is the open agent network.
- MCP sits top-left — it connects an agent to tools and data, usually within your control. A2A / ACP sit in the middle at cross-org scope — agent talking to a known peer agent, typically across a company boundary.
- ANP sits at the bottom-right — the widest reach, an open mesh of agents that don't know each other yet. The little
↑ tools/↑ known peers/↑ strangerslabels underneath name who each column is really about. - The important pattern: as you move right (wider scope), the trust and identity you need grows — connecting to your own tool is easy, connecting to a stranger safely is hard.
In short: Position on the grid tells you the trade-off: further right means more reach but more identity/trust work. That's the whole map — place any new protocol by asking "what does it connect, and how far does it reach?"
| Protocol | Connects | Centered on | You'd reach for it when… |
|---|---|---|---|
| MCP (T3/I1) | Agent ↔ tools/data | Capabilities & resources | Your agent needs a tool or data source |
| A2A (I2) | Agent ↔ known peer | Task delegation + discovery | Delegate a task to a specific external agent |
| ACP | Agent ↔ agent | Message substrate, framework-neutral | A simple, REST-y comms layer (incl. local) |
| ANP | Agent ↔ any agent | Decentralized identity & discovery | An open, broker-less network of agents (emerging) |
The durable principles advanced
Protocols will merge and rename. These underlying ideas won't — and they're what actually matter for building:
| Principle | Shows up as… |
|---|---|
| Discovery | Some machine-readable descriptor of "what can you do & how do I reach you" — MCP tool lists, A2A Agent Cards, ANP identity docs |
| A shared message contract | Agreed shapes for requests/results so heterogeneous systems interoperate (echoes structured output, Ch 2) |
| Identity & trust | Knowing who you're talking to — trivial within your walls, hard across an open network |
| Long-running interaction | Tasks that stream, pause, and resume — not just request/response (L5, I2) |
| Untrusted-input discipline | Anything from another agent is untrusted & must be validated (T1) — protocol-independent |
A practical stance on emerging standards advanced
How to act sensibly while the field consolidates:
Common pitfalls expert
| Pitfall | Fix |
|---|---|
| Treating the protocols as direct competitors | Place each by what it connects & at what scope |
| Memorizing today's exact boundaries | Learn the map; verify specifics when you must choose |
| Betting your architecture on one new protocol | Build on the stable layer; abstract the interop |
| Underestimating identity on open networks | Open discovery needs verifiable identity — plan for it |
| Trusting another agent's output by protocol | Untrusted input regardless of wire format (T1) |
| Ignoring interop entirely | Cross-agent collaboration is coming — stay literate |
Exercises expert
Exercise I3.1 — Place them on the map
Context: The one artifact that outlives every spec revision is a mental map of what each protocol connects and when to reach for it.
Your task: From memory, redraw the unified map and place MCP, A2A, ACP, and ANP by what they connect and at what scope, with a one-line "reach for it when…" trigger for each.
Requirements:
- Place all four by what they connect (tools vs agents) and their scope
- Give each a single "reach for it when…" trigger sentence
- Do it from memory — recall, not lookup, is the skill being built
- The result should stay correct even as the individual specs change
💡 Hint: If you can place a protocol on the two axes (what connects / what scope), the trigger sentence usually writes itself.
Exercise I3.2 — Slot a new protocol
Context: The durable test of the map is whether it can absorb something it has never seen — a protocol invented after you learned it.
Your task: Invent or find a hypothetical new agent protocol, place it on the three axes, and predict which existing protocol it most overlaps.
Requirements:
- Use only the three axes: what connects / what scope / what it centers on
- Locate the newcomer on all three
- Name its nearest existing neighbor and justify the overlap from the axes
- The reasoning, not the specific protocol, is the deliverable
💡 Hint: Answer the three axis questions in order — the answers both place it and reveal its closest existing relative.
Show the method
Ask: does it connect agents to tools or to other agents? Within a system, across orgs, or across an open network? Is it centered on delegation, messaging, or identity? Those three answers locate it — and reveal its nearest neighbor.
Exercise I3.3 — The trust checklist
Context: Whatever wire an external agent speaks, the trust decision is the same: you must authenticate, scope, validate, and gate before you act on its output.
Your task: Write a protocol-agnostic checklist for safely accepting work or output from any external agent, and confirm it reads identically across A2A, ACP, and ANP.
Requirements:
- Cover authenticate, scope/authorize, validate, and gate as distinct steps
- Keep every item independent of the wire protocol
- Verify the same checklist applies whether the transport is A2A, ACP, or ANP
- That protocol-independence is the point — call it out explicitly
💡 Hint: Write each item as a property of the interaction (who, what scope, valid shape, which action needs approval), never as a property of the transport.
🪜 Practice ladder beginner → industry
Six graded exercises, easy to real-world. Try each before opening its solution.
Context: Agent-interop protocols churn fast, but their shape is durable. The single most useful artifact is a one-line summary of what each protocol actually connects.
Your task: Write a lookup that returns a durable one-line summary for each of MCP, A2A, ACP, and ANP, keyed by protocol name.
Requirements:
- Store the four summaries in a dict keyed by protocol name (upper-cased)
- MCP is agent→tools/data; A2A is agent→peer task delegation; ACP is a general agent↔agent message substrate; ANP is an open, identity-centered network
- A lookup function returns the summary (and a sane fallback for unknowns)
- Print all four so the map is legible at a glance
💡 Hint: Capture what each protocol connects, not today's exact spec — the connection is what survives the churn.
Show solution
The map is worth more than any memo. Runnable:
SUMMARY = {
"MCP": "agent -> tools/data it uses (down)",
"A2A": "agent -> peer agent: delegate a task, with discovery",
"ACP": "agent <-> agent: a general REST-style message substrate",
"ANP": "open, decentralized network of agents; identity-centered",
}
def describe(p):
return SUMMARY.get(p.upper(), "unknown protocol")
for p in ["mcp", "a2a", "acp", "anp"]:
print(p.upper(), "::", describe(p))
Protocols move fast; the shape lasts. Learn what each connects, not today's exact spec.
Context: "Which protocol wins?" is the wrong question; "for this connection, at this scope, which fits?" is the right one. Three axes make that answerable.
Your task: Tag each of the four protocols on three axes — what connects, what scope, and what it centers on — and print the grid.
Requirements:
- Axis 1: what connects (agent↔tools vs agent↔agent)
- Axis 2: scope (in-system / cross-org / open-network)
- Axis 3: what it centers on (capability-invocation / task-delegation / message-passing / decentralized-identity)
- Model the axes as structured fields per protocol and print an aligned table
💡 Hint: Model each protocol as a small record of three fields; the value is in the columns lining up, not in any one label.
Show solution
Model the axes as fields and print the grid. Runnable:
AXES = {
"MCP": ("agent<->tools", "in-system", "capability-invocation"),
"A2A": ("agent<->agent", "cross-org", "task-delegation"),
"ACP": ("agent<->agent", "in-system+", "message-passing"),
"ANP": ("agent<->agent", "open-network", "decentralized-identity"),
}
print(f"{'proto':5} {'connects':14} {'scope':13} centered-on")
for p, (conn, scope, center) in AXES.items():
print(f"{p:5} {conn:14} {scope:13} {center}")
"Which wins?" is the wrong question. "For this connection, at this scope, which fits?" is the right one.
Context: ACP and A2A overlap on purpose (both are agents talking to agents), so choosing between them is about the slice of the problem, not the hype.
Your task: Write a selector that recommends ACP or A2A from the need: discovery, cross-org reach, wanting a REST-style substrate, or local/offline operation.
Requirements:
- ACP is favored for a general REST-style substrate or local/offline use
- A2A is favored when you need discovery and cross-org delegation
- Take the deciding factors as parameters (booleans) rather than free text
- Acknowledge the overlap case where either could serve — don't force a false winner
💡 Hint: Lead with the strongest single signal (a REST substrate or offline need points to ACP); note that the space is consolidating, so verify status when it's close.
Show solution
Pick by the slice, not by hype. Runnable:
def pick(need_discovery, cross_org, want_rest_substrate, local_offline):
if want_rest_substrate or local_offline:
return "ACP -- general message substrate, easy adoption, local-friendly"
if need_discovery and cross_org:
return "A2A -- task delegation with Agent Card discovery across orgs"
return "either overlaps here -- check current governance/status before picking"
print(pick(need_discovery=True, cross_org=True, want_rest_substrate=False, local_offline=False))
print(pick(need_discovery=False, cross_org=False, want_rest_substrate=True, local_offline=True))
They overlap on purpose (both are agents talking to agents) — which is why the space is consolidating. Hold the lean, verify status when you must choose.
Context: ANP's open network has no central broker, so an agent must prove who it is to strangers — decentralized identity has to be built in, not delegated to an authority.
Your task: Model a DID-style identity check offline with a toy signature: an agent presents an id plus a signature you verify against its published key material.
Requirements:
- Use only the standard library (e.g.
hashlib) — a hash stands in for real signing - A public directory maps a DID to a digest of its key material
verify()rejects an unknown DID and rejects a mismatched key- A valid signature over a message verifies True; a forged/other identity verifies False
- Demonstrate both the accept and the reject path
💡 Hint: Compose the signature from the DID, its secret, and the message; verification re-derives it and also checks the presented key against what the directory published.
Show solution
No central authority means identity must be verifiable point-to-point. Model it offline with a toy signature (a hash), stdlib only:
import hashlib
def sign(did, secret, message):
return hashlib.sha256(f"{did}|{secret}|{message}".encode()).hexdigest()
# public directory maps a DID to the digest of its secret (its "key material")
def register(did, secret):
return {did: hashlib.sha256(secret.encode()).hexdigest()}
def verify(directory, did, secret_claim, message, signature):
if did not in directory:
return False # unknown identity on the open network
if directory[did] != hashlib.sha256(secret_claim.encode()).hexdigest():
return False # key material does not match the published DID
return sign(did, secret_claim, message) == signature
dir_ = register("did:agent:alice", "s3cr3t")
msg, sig = "hello", sign("did:agent:alice", "s3cr3t", "hello")
print(verify(dir_, "did:agent:alice", "s3cr3t", msg, sig)) # True
print(verify(dir_, "did:agent:mallory", "x", msg, sig)) # False
Real ANP uses proper DIDs and public-key crypto (needs the spec/SDK). The durable point: on an open network, identity and verifiable descriptions must be built in — you can't lean on a broker.
Context: A mature system doesn't bet on one protocol — it speaks several, one per kind of connection: MCP for its tools, A2A for cross-org sub-tasks, ACP as an internal bus.
Your task: Write a dispatcher that, given an edge described by its kind and scope, routes it to the right protocol.
Requirements:
- A tool edge → MCP
- An agent edge that is cross-org → A2A; internal → ACP; open-network → ANP
- Route by the edge's nature (kind + scope), not by a hard-coded name
- Run it over a small list of mixed edges and print each routing decision
💡 Hint: The protocols are complementary layers; branch on (kind, scope) and give the common case a sensible default.
Show solution
A real system layers them. Route each edge by its nature. Runnable:
def dispatch(edge):
kind, scope = edge["kind"], edge["scope"]
if kind == "tool":
return "MCP"
if kind == "agent" and scope == "cross-org":
return "A2A"
if kind == "agent" and scope == "internal":
return "ACP"
if kind == "agent" and scope == "open-network":
return "ANP"
return "MCP"
edges = [
{"name": "vector-db", "kind": "tool", "scope": "internal"},
{"name": "partner-pricing", "kind": "agent", "scope": "cross-org"},
{"name": "sibling-worker", "kind": "agent", "scope": "internal"},
]
for e in edges:
print(f"{e['name']:16} -> {dispatch(e)}")
The protocols are complementary layers. The engineering skill is slotting each connection onto the right one, not betting on a single winner.
Context: The whole point of the axes map is to place newcomers fast. A new interop protocol will appear next quarter, and you shouldn't need to memorize its memo to react.
Your task: Write a triage that classifies a new protocol on the three axes and emits a posture: adopt-now / watch / ignore.
Requirements:
- Take the protocol's connects/scope/maturity and whether it overlaps existing protocols
- Stable + fills a real gap → adopt-now
- Promising but overlapping (or only shared-governance maturity) → watch
- Draft-stage → ignore for now (likely to churn or merge)
- Return both the placement (axes) and the stance
💡 Hint: Placement comes first (the axes locate it); maturity plus overlap then decide the posture. Names merge and governance shifts — the axes let you reason without over-committing.
Show solution
The whole point of the map is to place newcomers fast. Runnable:
def triage(proto):
connects = proto["connects"] # 'tools' | 'agents'
scope = proto["scope"] # 'in-system'|'cross-org'|'open-network'
maturity = proto["maturity"] # 'draft'|'shared-governance'|'stable'
overlaps = proto["overlaps_existing"]
# place it, then decide a posture
slot = f"connects={connects}, scope={scope}"
if maturity == "stable" and not overlaps:
stance = "ADOPT-NOW -- fills a real gap and is stable"
elif maturity in ("shared-governance", "stable"):
stance = "WATCH -- promising but overlaps; wait for consolidation"
else:
stance = "IGNORE for now -- draft-stage, likely to churn or merge"
return slot, stance
new = {"connects": "agents", "scope": "cross-org",
"maturity": "draft", "overlaps_existing": True}
slot, stance = triage(new)
print(slot)
print(stance)
This is a moving frontier: names merge, governance shifts, some fade. Learning the axes lets you reason about anything new without over-committing to today's field notes.
✓ Checkpoint — you can move on when you can…
- Explain what ACP emphasizes vs A2A.
- Explain ANP's open-network ambition and why identity is central.
- Place MCP, A2A, ACP, ANP on one map by what/scope.
- State the durable principles that outlast any single protocol.
- Take a sensible build-vs-watch stance on emerging standards.
Knowledge check check yourself
What does ACP emphasize compared with A2A, and why does ANP make decentralized identity its foundation?
Show answer
Using the two axes 'what connects' and 'what scope', place MCP, A2A/ACP, and ANP on the map.