The Agent2Agent (A2A) protocol gives agents a standard way to publish what they can do (an Agent Card), hand off work to another agent (a Task), and track that work through its lifecycle. It solves a real interoperability problem: an orchestrator agent built by one team can delegate to a specialist agent built by another, across organizational and vendor boundaries, without bespoke integration code per pair.
What A2A doesn't standardize is the same question we've written about for every other agent protocol: should this agent be allowed to hand this specific piece of work to that agent, right now, given its trust level and context? A2A's own spec leaves authentication and authorization to "established enterprise practices" — reasonable, since protocol design and policy enforcement are different concerns, but it means every A2A deployment inherits the same gap we described for MCP, LangChain, CrewAI, and AutoGen: an agent being discoverable and delegatable-to is not the same as a delegation being authorized.
Where the gap shows up
A remote A2A agent accepts a message/send call from whichever client reaches its endpoint. In the patterns we've seen:
- The Agent Card advertises what the agent can do, but says nothing about which callers should be allowed to invoke it, beyond a declared auth scheme (API key, OAuth, mTLS) that proves identity, not authorization.
- There's no standard place to ask "is this delegation, from this agent, in this context, allowed?" before the task starts — a receiving agent either trusts every authenticated caller equally, or bakes its own ad hoc policy logic directly into its task handler.
- Delegation chains compound the problem: an orchestrator delegating to a specialist, which delegates to a sub-specialist, has no standard way to carry whose authority is actually behind the request three hops upstream.
That last point is the one A2A shares most closely with plain delegation chains in general — see why autonomous agents need their own identity infrastructure for the underlying problem.
How the Gateway works
Same shape as the MCP Gateway, because the underlying problem is the same: register your downstream A2A agent with AGF once, and the A2A Gateway sits in front of it, intercepting traffic at the protocol level rather than requiring a code change in either agent.
- You point AGF at your A2A agent's endpoint (
target_url) and register theaudienceyour delegation tokens should carry. AGF gives you back a gateway URL. - Callers send
message/send(andmessage/sendStreaming) to that gateway URL instead of your agent directly — these are the two methods that actually cause the remote agent to do something, so they're the ones that get a decision. - The Gateway resolves the calling agent's identity, runs the same three-signal decision (policy, trust score, risk) every other AGF integration uses, and produces a signed decision artifact either way.
- Only on ALLOW does the original request forward to your agent, byte-for-byte. Read-only and management methods —
tasks/get,tasks/list,agentCard/get,tasks/cancel, push-notification config — pass straight through once your credentials check out, since they don't initiate new work.
A blocked delegation never reaches your agent. It comes back as a standard JSON-RPC error, exactly like the MCP Gateway.
Where we are today
The A2A Gateway is live — registration, the proxy route, and full decision-artifact parity with /v1/decide are shipped. See the A2A Gateway integration guide for exact request shapes.
Two honest limitations worth knowing about: delegation chains travel over the same stopgap X-AGF-Chain header as the MCP Gateway, pending native OAuth 2.1 support. And unlike MCP's tools/call, an A2A message/send has no mandated field naming which skill is being invoked — a Message's content is free-form parts, not a named tool call. AGF looks for an optional metadata.skill_id on the message; if your agents don't set it, every delegation is authorized against the generic resource "message" rather than a specific skill. If your policies need to distinguish between skills, set metadata.skill_id on outgoing messages.

