Why architecture matters here
Why does agent interop need a protocol at all — why not just HTTP APIs between services? Because agent delegation has a shape ordinary request/response doesn't capture: tasks that run for minutes to hours, emit partial results, pause to ask clarifying questions, and need cancellation, resumption, and state inspection — the whole task lifecycle A2A standardizes. Wrapping your agent in a bespoke REST API means reinventing exactly that lifecycle (status polling, webhooks, question-asking) per integration, and every consumer integrates differently. The protocol's value is the same as any interoperability standard's: the second integration is free, discovery is uniform (fetch the card), and the ecosystem's tooling — clients, gateways, registries, observability — compounds across everyone's agents.
For architecture inside an organization, the interop layer is also a decoupling instrument. Two teams' agents composed through the tree share deployment cadence, session storage, and failure domains; composed through A2A, each owns its runtime, scales independently, and exposes a versioned contract — the microservices argument replayed at the agent altitude, with the same trade (network seams and contract management in exchange for autonomy). The practical guidance that emerges: compose through the tree within a bounded context (one team, one deployment), through A2A across contexts — and resist both extremes (one mega-tree for the company; A2A between agents that ship together).
And crossing organizational boundaries changes the threat model categorically. An internal sub-agent is trusted code; a remote agent is an autonomous counterparty — its outputs are untrusted content (injection vectors for your orchestrator), its availability is someone else's SLO, its behavior can change without your deploy. The interop architecture therefore carries the full boundary kit: OAuth-scoped identity per the A2A auth spec, quarantine treatment of remote outputs in your context engineering, circuit breakers and fallbacks for its failures, and contract tests against its card — the discipline gap between 'calling our other agent' and 'depending on an external AI system' is the gap this architecture exists to close.
The architecture: every piece explained
Top row: exposing outward. The ADK agent tree — root, specialists, workflows — remains unchanged; the A2A server wrapper (ADK ships this integration: an app that hosts the agent behind A2A's JSON-RPC/HTTP surface) translates protocol calls into Runner invocations: message/send and message/stream become turns, task state transitions map from the invocation lifecycle, and input-required surfaces when the agent's flow needs the caller's answer (a long-running tool or an explicit ask). The agent card — served at the well-known URL — declares identity, endpoint, version, skills (named capabilities with descriptions that remote LLMs route on — write them like tool docs), supported modalities, and auth schemes; it is the discovery artifact and the contract. Remote consumers — other orchestrators, marketplaces, partner systems — discover the card, authenticate per its schemes, and delegate tasks with no ADK knowledge.
Middle row: consuming inward, and the two hard mappings. RemoteA2aAgent wraps an external agent's card as a local agent object: to the tree it looks like any sub-agent (transferable, sequenceable); at runtime it opens A2A exchanges against the remote endpoint. Task mapping is identity plumbing: the local session's continuity must correlate with the remote task/context IDs so a multi-turn exchange (user → your orchestrator → remote specialist → question back → user answers → resume) binds correctly across both systems; the integration stores remote task handles in session state and routes follow-ups to the same task. Auth boundary: outbound calls carry OAuth tokens per the remote card's scheme (client-credentials for service trust, user-delegated where the remote acts on your user's behalf); inbound, your wrapper validates tokens/audience exactly as any A2A server must — and your internal callback guardrails keep running regardless, because protocol auth authenticates the caller, not the safety of the content. The streaming bridge converts event streams: ADK events (partial text, tool activity, state changes) map onto SSE status/artifact updates outbound; inbound, remote task updates surface as events your UI and logs treat natively.
Bottom rows: governance. Trust tiers shape configuration: internal A2A (same org — lighter auth, richer skills exposed, shared tracing headers), partner (contracted counterparties — scoped skills, strict SLAs, legal-reviewed cards), public (marketplace exposure — minimal skills, aggressive rate limits, hardened validation). Contract versioning: cards carry versions; skill changes follow API-evolution rules (additive freely, breaking via new skill/version with migration windows); consumer contract tests pin against card snapshots. The ops strip: cross-org tracing (propagated correlation IDs both sides agree to log), SLA instrumentation per remote dependency (latency, completion rate, input-required frequency), and failure isolation — timeouts, circuit breakers, and degraded-mode answers when a remote specialist is down.
End-to-end flow
Compose a cross-boundary system: a travel company's trip-planning orchestrator (ADK) using an airline's booking agent (external, A2A) and its own internal loyalty agent (another team's ADK deployment, also consumed via A2A — the decoupling choice). The tree: root planner with sub-agents itinerary (local), loyalty (RemoteA2aAgent → internal tier), airline_booking (RemoteA2aAgent → partner tier, card fetched from the airline's well-known URL, OAuth client-credentials per its declared scheme).
A user plans a trip. The planner drafts an itinerary locally, then transfers to airline_booking with the flight request. Under the hood: message/stream opens a task at the airline; status events ('checking availability') bridge into the local event stream and the user's UI; 40 seconds in, the airline agent pauses with input-required — 'aisle or window for the overnight leg?' The bridge surfaces the question as a normal agent turn; the user answers; the reply routes to the same remote task (the handle lives in session state); the task resumes and completes with a booking artifact (PNR, fare rules). The orchestrator's after-tool-style sanitization treats the artifact as untrusted content — parsed into typed state, prose quarantined — before the planner reasons over it. Total: two companies' agents, one coherent conversation, and the user never saw a seam.
The operational vignettes prove the boundary kit. The airline deploys a card update adding a baggage skill (additive — consumers unaffected) and, a month later, renames a skill's parameter (breaking — caught by the travel company's nightly contract test against the card snapshot, raised through the partner channel before any user impact). A Friday incident: airline agent latency triples; the circuit breaker trips after threshold breaches; the planner degrades gracefully — itineraries complete with 'booking temporarily queued' and a resumable task list — while the SLA dashboard (completion rate, p95 task duration per remote) documents the breach for the quarterly review. And when a dispute arises ('the agent booked the wrong date'), the cross-org audit chain answers it: the travel company's event log shows the exact request and the user's confirmation turn; the airline's task history shows the same exchange from its side, joined by the correlation ID both agreed to propagate — two companies, one reconstructable truth, which is the whole reason the protocol carries identity and history instead of just payloads.