A2A Protocol
Key Points
- A2A (Agent-to-Agent) protocol: standard for agents from different platforms / vendors to communicate.
- Early in 2026; emerging standard.
- Use case: your .NET Agent Framework agent talks to a Claude-hosted agent or a third-party orchestration platform.
- Complements MCP (tool exchange) — A2A is for agent-to-agent dialogue.
- Status: protocol drafts circulating; production rollout starting.
Why A2A
MCP standardized tools. A2A standardizes agent dialogue.
Without A2A:
Your agent → custom integration → Claude.ai agent → custom response
Your agent → custom integration → ChatGPT agent → custom response
...
With A2A:
Your agent ──A2A──▶ Other agent
◀── A2A ── response
Concepts
- Agent card: discovery metadata (name, capabilities, endpoint).
- Conversation: ongoing message exchange between agents.
- Tool call across agents: optional; one agent uses another's capabilities.
- Authentication: OAuth-based handshake.
Sketch
// Discover other agent
var agentCard = await A2AClient.DiscoverAsync(new Uri("https://other-agent.com/.well-known/agent.json"));
// Start conversation
var convo = await A2AClient.StartConversationAsync(agentCard, new()
{
Auth = ...,
Capabilities = ["chat", "tool-use"]
});
// Send message
var resp = await convo.SendAsync(new ChatMessage(ChatRole.User, "Help me plan my trip"));
// Continue
await convo.SendAsync(new ChatMessage(ChatRole.User, "Make it 5 days"));
(Specific API depends on .NET A2A SDK; details may change.)
When use A2A
- Cross-vendor orchestration: your .NET agent uses ChatGPT for brainstorming + Claude for code.
- Multi-organization: customer's agent talks to your support agent.
- Federated agents: loose coupling across orgs.
When NOT
- Single-vendor stack — internal patterns suffice.
- Simple chat completion —
IChatClientenough. - Stateful workflows — workflow engines.
Comparison
| Protocol | For |
|---|---|
| MCP | Tool servers ↔ agents |
| A2A | Agent ↔ agent |
| HTTP | Generic client/server |
| OpenAI assistant API | Vendor-specific agent state |
Authentication
OAuth-style handshake. Each agent has a registered identity. Permissions checked per-action.
Status (mid-2026)
A2A is emerging — protocol drafts being finalized. Early adopters: enterprise multi-vendor scenarios. .NET SDK in preview/early stages.
For most apps in 2026: not yet needed. Watch the space.
Status note: A2A in Agent Framework moved from preview into shipping packages (
Microsoft.Agents.AI.A2A,Microsoft.Agents.AI.Hosting.A2A,Microsoft.Agents.AI.Hosting.A2A.AspNetCore) but the protocol is still evolving. Several capabilities below (background responses, stream reconnection, catalog-based discovery beyond well-known URIs) should be treated as emerging — verify against current docs before designing production systems around them.
Architecture (cross-boundary agent dialogue)
Org A (your .NET app) Org B (partner / vendor)
+--------------------------+ +---------------------------+
| ChatClientAgent | | AnyAgent (.NET / Py / |
| | | | LangChain / custom) |
| | (uses as tool) | | ^ |
| v | | | hosted via |
| A2AAgent (proxy) | | Microsoft.Agents.AI |
| +--------------------+ | | .Hosting.A2A.AspNetCore |
| | A2AClient | | | (or any A2A server SDK) |
| +---------+----------+ | +-----------+---------------+
+------------+-------------+ ^
| |
| 1. GET /.well-known/agent-card.json |
+--------------------------------------->|
| <-- AgentCard (capabilities, auth) --|
| |
| 2. OAuth / token exchange |
+--------------------------------------->|
| |
| 3. HTTP+JSON (default) or JSON-RPC |
| message / streaming SSE / task |
+<-------------------------------------->+
(context_id ties turns)
Discovery options: A2ACardResolver against the well-known URI, an AgentCard retrieved from a registry/catalog, or direct A2AClient construction when the endpoint is known. The remote agent maintains its own conversation state keyed by the A2A context_id (mapped to the local AgentThread's id).
Pros & cons
| Pros | Cons |
|---|---|
| Framework-agnostic — your .NET agent can call a Python/LangChain/JS agent without custom adapters | Every call is an HTTP hop; latency dominates short interactions |
A2AAgent looks like any AIAgent — RunAsync / RunStreamingAsync work as usual | You don't see the remote agent's tool calls or reasoning, only its output |
| Dynamic discovery via agent card means you can swap providers without code changes | Discovery is only as good as the registry/well-known URI you trust |
| Streaming via SSE and background-response continuation tokens for long tasks | Background-response and stream-reconnection semantics are still firming up |
Built-in ASP.NET Core hosting (MapA2A style) for exposing your own agents | Cross-org auth is your problem — OAuth flows, token caching, rotation |
| Default protocol auto-negotiates HTTP+JSON over JSON-RPC | Default changed in v1 SDK — old code that relied on JSON-RPC silently switched |
When to use / when to avoid
- Use when the agent you need to call is in a different process, service, team, or organization.
- Use when you need framework-agnostic interop (your .NET agent calling a partner's Python LangChain agent).
- Use when an agent must be exposed as a stable, discoverable endpoint to multiple consumers.
- Use when teams own different release cycles and you don't want shared in-process coupling.
- Avoid when all agents are in the same process — use agent-as-tool composition; A2A adds an HTTP hop for nothing.
- Avoid for tight inner loops where 50–200ms of HTTP overhead matters.
- Avoid when MCP fits — A2A is for agent dialogue, MCP is for tool/data exposure. They're complements, not alternatives.
Interview Q&A
Q1. What is A2A in one paragraph? A2A (Agent-to-Agent) is an open protocol — see a2a-protocol.org — that standardizes how agents discover each other (via Agent Cards), exchange messages, stream responses, and coordinate on long-running tasks across process and organizational boundaries. Microsoft Agent Framework ships A2AAgent (client-side proxy) and Microsoft.Agents.AI.Hosting.A2A.AspNetCore (server-side hosting) so a .NET agent can speak to or be exposed as any A2A-compliant peer regardless of language or framework.
Q2. A2A vs MCP — what's the right mental model? MCP is for tools and data: a server exposes capabilities (tools, resources, prompts) that any agent can consume. A2A is for agents talking to agents: full dialogues, possibly multi-turn, where the other end is itself an LLM-driven agent with its own reasoning. They're orthogonal and frequently combined — your A2A-exposed agent internally calls MCP servers for its tools.
Q3. How does discovery work? Three patterns. (1) Well-known URI: https://{host}/.well-known/agent-card.json returns an AgentCard; resolved via A2ACardResolver(uri).GetAIAgentAsync(). (2) Catalog/registry: a central service hands you an AgentCard; convert with agentCard.AsAIAgent(). (3) Direct: when you already know the endpoint, new A2AClient(uri).AsAIAgent(...). The card lists name, description, capabilities, supported protocol bindings (HTTP+JSON, JSON-RPC), and auth schemes.
Q4. The default protocol binding changed in the v1 SDK. Why does that matter? Pre-v1, A2AClient always used JSON-RPC. From v1, the default is HTTP+JSON with JSON-RPC fallback — if the remote supports both, requests silently switch. Code that assumed JSON-RPC framing on the wire (proxy filters, request inspectors) breaks. Pin behaviour with A2AClientOptions.PreferredBindings = [ProtocolBindingNames.JsonRpc] if you need the old default.
Q5. How is a remote agent's conversation state tracked? The remote agent owns its state, keyed by the A2A context_id. The Agent Framework maps the local AgentThread.Id (or a new id if absent) onto context_id so a sequence of RunAsync calls against the same thread continues the same remote conversation. If the remote restarts and loses state, your local thread points at a context that no longer exists — you must handle that as a session-recovery case.
Q6. How do you authenticate cross-org A2A calls? The agent card declares supported auth schemes (typically OAuth 2.0). You handle the token acquisition outside A2A — client credentials for service-to-service, OBO/delegated for user-on-behalf-of — and configure A2AClient (or the underlying HTTP client) with the bearer token. Token refresh is your code. Treat partner agents like any external API: scope tokens narrowly, rotate, audit. (Auth ergonomics in the SDK are still maturing — verify current options.)
Q7. Streaming and background responses — what's the model? RunStreamingAsync opens a Server-Sent Events stream; you yield AgentResponseUpdates as they arrive. For long-running operations the remote can return a task instead of a message, and the SDK gives you a continuation token to poll (AllowBackgroundResponses). For interrupted streams you can reconnect using a continuation token — note the spec calls this "reconnection" (replay from start), not "resumption" from a midpoint. Treat background/reconnection as emerging — pin docs to the SDK version you ship.
Q8. How do you expose your own ChatClientAgent over A2A? Install Microsoft.Agents.AI.Hosting.A2A.AspNetCore, register the agent in DI, map the A2A endpoint in the ASP.NET Core pipeline (e.g. at /a2a/{agent-name}), and the framework publishes the agent card at /.well-known/agent.json. Any A2A-compliant client can now discover and call it. Add the same auth, rate-limiting, and OTel middleware you would on any HTTP endpoint.
Q9. Latency and reliability — what changes vs in-process composition? Every interaction is an HTTP request: connection, TLS, possibly token refresh, then LLM time on the remote. A two-agent in-process orchestration that takes 800ms can become 1.5–2s over A2A. You inherit all the distributed-systems concerns: retries (idempotency-aware), circuit breakers, timeouts, partial-failure handling. Use Microsoft.Extensions.Http.Resilience on the client; isolate A2A calls behind their own bulkhead.
Q10. Gotcha: what if the remote agent's card claims capabilities it doesn't actually support? The card is metadata — claims can lie or drift from implementation. Treat it as advisory. Validate on first call (probe with a minimal prompt; check streaming actually streams, etc.), assert critical capabilities at startup, and fail loud rather than silently falling back. For high-stakes integrations, contract-test the partner's agent in CI like any external API.
Q11. Design: federate three vendors' agents (legal review, medical triage, translation) behind one orchestration. How? Each vendor exposes an A2A endpoint. Your orchestrator is a ChatClientAgent (or a Workflow) whose tools include three A2AAgent proxies wrapped via agent.AsAIFunction(). Discovery via well-known URIs at startup, with an in-memory cache of AgentCards refreshed periodically. Per-vendor auth credentials stored in Key Vault, fetched via IConfiguration + Azure.Identity. Per-vendor circuit breaker and per-tenant audit log. Expose the orchestrator itself over A2A so customer agents can call it.
Q12. When would you specifically NOT use A2A? When everything runs in one process and one team — agent.AsAIFunction() and direct in-process composition is simpler and faster. When the relationship is "tool/data," not "agent dialogue" — use MCP. When the partner integration is one-off and won't be reused — a plain HTTP API may be a smaller commitment than implementing A2A on both ends. A2A pays for itself when interop and cross-boundary discovery are real requirements.
Gotchas / common mistakes
- Relying on JSON-RPC framing after the v1 SDK switched default to HTTP+JSON — set
PreferredBindingsexplicitly. - Treating
AgentCardcapabilities as guaranteed — validate at runtime. - Sharing one
A2AClient/HTTP client across tenants without scoping auth headers per request — token leakage. - Forgetting that the remote owns conversation state keyed by
context_id— losing the id means losing context. - Using A2A for in-process composition where agent-as-tool would do — pure overhead.
- Not setting timeouts on
RunAsync— a stuck remote stalls your whole orchestration. - Logging full A2A request/response bodies — they're prompt content, often PII; redact like any LLM trace.
- Assuming background-response and stream-reconnection contracts are stable — they are still firming up; pin SDK version.
Further reading
- Agent-to-Agent (A2A) journey guide
- A2A Integration (Agent Framework)
A2AAgentprovider docs (C#)- A2A hosting (ASP.NET Core)
- A2A SDK v1 migration guide
- A2A protocol specification
- Agent discovery (well-known URI, catalog, direct)
Senior considerations
- Don't over-engineer: A2A only when you actually need cross-vendor communication.
- Privacy: agent-to-agent passes prompts; data crosses boundaries.
- Audit: log every cross-agent conversation.
- Trust: agent cards make claims; verify capabilities you depend on.