Agent Interoperability Architecture on AWS - Cross-Runtime Agents with A2A, MCP, and Amazon Bedrock AgentCore Gateway

First Published:
Last Updated:

1. Introduction

Most multi-agent systems in production today live inside a single process. A supervisor agent calls sub-agents as tools, or a swarm of agents shares one memory and one runtime, all built with one framework and deployed as one unit. That model is well understood, and the pattern-selection trade-offs for it — agents-as-tools, swarm, graph, and workflow — are covered in Strands Agents Multi-Agent Pattern Selection Guide. This article is about what happens when that boundary breaks: when an agent built by one team, on one framework, in one account, needs to delegate work to an agent owned by a different team, a different vendor, or a different organization entirely — and neither side can see the other's code.

The moment agents cross a runtime or an organizational boundary, three problems appear that in-process orchestration never had to solve. Discovery: how does agent A find out that agent B exists and what it can do, without a shared registry baked into both codebases? Delegation: how does A hand a task to B and get a result back, when they share no function signatures and no memory? Trust: how does B know who is really asking, whether they are allowed, and how does A know the agent it reached is the one it intended — across a boundary where neither party controls the other?

The industry has converged on two open protocols that, together, answer these questions, and they divide the work cleanly. The Model Context Protocol (MCP) standardizes how a single agent reaches its tools and data — the agent-to-tool edge. The Agent2Agent (A2A) protocol standardizes how independent agents discover and coordinate with each other — the agent-to-agent edge. They are complementary, not competing: a retail inventory agent might use MCP to query a product database, then use A2A to ask an external supplier's agent to place an order. Both protocols are now under neutral, open governance — A2A was contributed by Google to the Linux Foundation in June 2025, and MCP is an open specification with broad multi-vendor adoption.

On AWS, the service that brokers this fabric is Amazon Bedrock AgentCore. AgentCore Runtime can host A2A servers so an agent is reachable by peers; AgentCore Gateway consolidates tools and downstream agents behind a single governed endpoint; AgentCore Identity propagates the caller's identity across every hop; and Cedar-based authorization decides who may invoke what. This article is a single, end-to-end implementation walkthrough of one named reference architecture that wires these together: the Cross-Runtime Agent Fabric on AWS. The goal is a system you can reason about, instrument, and secure — not a demo.

The intended reader is an AI architect who already runs agents in production and now has to make two of them — built and operated by different teams or even different companies — work together without merging them into one codebase. By the end you should be able to host an agent that peers can reach, delegate a task to an agent you did not build and cannot introspect, carry the user's identity safely across that boundary, decide what each side is allowed to do, and tell exactly which hop failed when something breaks. Everything is grounded in a single running scenario — an inventory agent reordering stock from an external supplier's agent — so the abstractions stay concrete.

This article deliberately delegates the foundations to existing guides rather than repeating them. Building an MCP server (tools, resources, transport, OAuth 2.1) and registering it as a Gateway target are covered in MCP Server on AWS Lambda Complete Guide. Cedar authorization at the Gateway boundary — default-deny, forbid-wins, JWT claims as entity tags — is covered in depth in Amazon Bedrock AgentCore Policy Implementation Guide. The cross-vendor MCP comparison and the MCP specification recap live in MCP Server Implementation Reference. What follows assumes you can already build a tool server and write a Cedar policy, and focuses entirely on the interoperability layer: the two protocols, the broker, identity propagation, contracts, and the failure modes that span them.

A note on currency, scope, and honesty. The agent-interoperability surface area is moving quickly, and this article is careful to separate what is generally available today from what is announced as emerging. Every protocol fact, API field, and service capability below was verified against the official A2A specification and AWS documentation at the time of writing; re-verify model lifecycle, regional availability, and quotas before depending on them. This article contains no pricing figures by editorial policy — consult the official pricing pages for cost characteristics. It is a security-adjacent topic, so it treats authentication and authorization as defense-in-depth rather than guarantees, never implies that "the call succeeded, therefore it was safe," and contains no attack payloads.

2. The Reference Architecture at a Glance

The Cross-Runtime Agent Fabric is built from a small number of cooperating pieces. A client agent owns a user goal; a remote agent — on a different runtime, possibly a different organization — exposes a capability; A2A carries the task between them; MCP (consolidated by AgentCore Gateway) carries each agent's tool calls; AgentCore Identity carries the caller's identity through every hop; and Cedar decides what is allowed.
The Cross-Runtime Agent Fabric on AWS reference architecture
The Cross-Runtime Agent Fabric on AWS reference architecture
The components and their roles:
ComponentService / specRole in the fabric
Client agentAgentCore Runtime (A2A client)Owns the user goal; discovers and delegates to remote agents
Remote agentAgentCore Runtime (A2A server)Exposes a capability via an Agent Card; executes delegated tasks
Agent-to-agent protocolA2A v1.0.0 (JSON-RPC 2.0 over HTTP/SSE)Discovery, task delegation, status, artifacts between agents
Agent-to-tool protocolModel Context Protocol (MCP)Each agent's calls to tools, resources, and data
BrokerAgentCore GatewayOne governed endpoint: MCP aggregation, HTTP/A2A proxy, inference routing
IdentityAgentCore IdentityInbound auth, outbound auth, OAuth on-behalf-of token exchange, token vault
AuthorizationCedar (delegated)Default-deny policy on which principal may invoke which action
Discovery / governanceAWS Agent Registry (preview)A catalog of agents, tools, and skills as structured A2A/MCP records

Two structural facts drive everything downstream. First, the two protocols never overlap: A2A is the only thing that crosses the agent-to-agent boundary, MCP is the only thing that crosses the agent-to-tool boundary, and the Gateway is where the MCP edge is consolidated and governed. Second, identity flows along the call, not around it: the user's identity established at the front door is carried — re-scoped, never re-prompted — through the A2A hop, through the Gateway, and into the downstream tool, so every layer can make its own authorization decision against the real principal.

A third principle is implicit in the table and worth stating: every box is independently governed. The client agent, the remote agent, the Gateway, and each tool authenticate, authorize, and emit telemetry on their own — there is no shared trust whereby one component's success implies another's. That independence is what makes the fabric composable across organizational lines, where you control some boxes and not others, and it is the reason the same three controls — authenticate, propagate, authorize — recur at every hop in the sections that follow. The rest of this article walks one task through this architecture, component by component, and then covers the cross-cutting concerns — contracts, observability, and failure modes — that span them.

3. A2A and MCP: Two Protocols, Different Jobs

The single most common confusion in this space is treating A2A and MCP as alternatives. They are not. They solve different problems at different layers, and a mature system uses both at once. This section pins down what each one is responsible for, then details A2A — the protocol the existing articles in this series do not cover.
A2A and MCP responsibility matrix
A2A and MCP responsibility matrix

3.1 MCP: the agent-to-tool edge (delegated)

MCP standardizes how one agent connects to tools, resources, and prompts behind a uniform interface, so the agent does not need bespoke glue per integration. A client lists capabilities (tools/list), invokes them (tools/call), and reads resources, all over a JSON-RPC interface (Streamable HTTP transport in current servers). The full mechanics — primitives, transport, OAuth 2.1 authorization, and building a server on Lambda — are covered in MCP Server on AWS Lambda Complete Guide, and the cross-vendor comparison and specification recap in MCP Server Implementation Reference. For this article, the one thing that matters is the boundary MCP owns: the connection from a single agent to the capabilities it uses. It does not coordinate two autonomous agents — by design. That single-counterparty assumption is also why MCP authorization is about which tools a caller may use, whereas A2A's concerns — who the peer is, whether its card is authentic, and what task lifecycle applies — have no MCP equivalent.

3.2 A2A: the agent-to-agent edge

A2A is an open standard for communication between independent, potentially opaque agent systems. Where MCP assumes you know the tool's schema, A2A assumes the opposite: the remote agent is a black box built by someone else, on a different framework, that you cannot introspect. A2A gives the two sides a shared model for finding each other, agreeing on what can be done, and exchanging work — without exposing internal state or tools. It is built on widely used standards — HTTP(S), JSON-RPC 2.0, and Server-Sent Events — so it slots into existing stacks, and it is designed for enterprise authentication and authorization from the start.

The A2A specification reached version 1.0.0 and is governed under the Linux Foundation (Google donated the project in June 2025, and it is maintained as open source). Version 1.0 made the data models and protocol bindings stable, and added four production-grade capabilities worth naming: signed Agent Cards (a cryptographic signature lets a receiver verify the card was issued by the claimed domain owner, defeating card-forgery attacks), multi-tenancy (one endpoint can host many agents), multi-protocol bindings (the same logical agent can be exposed over JSON-RPC, gRPC, and HTTP+JSON/REST), and version negotiation (backward-compatible migration from the 0.x line). Verify the exact version your tooling targets, because A2A's version is still advancing.

The protocol defines a client–remote model with a small, stable object vocabulary:
  • Agent Card — a JSON metadata document each agent publishes to advertise its identity, capabilities (skills), service endpoints, and authentication requirements. This is the unit of discovery; a client reads a peer's card before delegating.
  • Task — the fundamental unit of work, with a unique ID and a lifecycle. Tasks can be long-running, multi-turn, and span several agents.
  • Message — a turn of communication between client and remote agent.
  • Part — the smallest unit of content within a Message or Artifact (for example a text part).
  • Artifact — the output a task produces: structured text, JSON, images, audio, or other multimodal content.

The request lifecycle, in the protocol's own roles: a User defines a goal; an A2A Client (client agent) acts on the user's behalf, discovers a suitable peer, and sends a task; an A2A Server (remote agent) exposes HTTP endpoints implementing A2A, accepts the task, executes it, and returns artifacts plus status updates, using JSON-RPC 2.0 over HTTP/S or SSE for streaming. Discovery is anchored at a well-known URI: every compliant agent serves its Agent Card at /.well-known/agent-card.json. A minimal message/send call is a plain JSON-RPC request:
{
  "jsonrpc": "2.0",
  "id": "req-001",
  "method": "message/send",
  "params": {
    "message": {
      "role": "user",
      "parts": [{ "kind": "text", "text": "Reserve 200 units of SKU-4471 for next week." }],
      "messageId": "12345678-1234-1234-1234-123456789012"
    }
  }
}
The remote agent decides how to fulfill that — including, often, calling its own MCP tools. That is the composition that makes the fabric work: A2A across the agent boundary, MCP behind each agent for its tools.

A2A is not limited to single request/response. Beyond message/send, the protocol defines message/stream for incremental delivery over Server-Sent Events, and a Task carries a status lifecycle so long-running or multi-turn work can report progress before returning the final Artifact; a server can also be configured to push a notification when a task completes for a client that has since disconnected. This is what lets an agent delegate work that takes minutes — a supplier confirming stock across its own systems — without holding a synchronous connection open the whole time. It is also why the failure modes in Section 8 include "task appears to hang": a long-running task is a state machine, not a blocking call, and the client has to consume its updates.

3.3 Why you need both, with one example

Consider an inventory-management agent that must reorder stock. It uses MCP to read its own product database and warehouse system — those are its tools, with known schemas, behind its Gateway. To actually place the order it must reach a supplier's agent, which it did not build and cannot introspect; that is an A2A interaction — discover the supplier agent's card, send a task, receive an artifact (an order confirmation). Neither protocol alone is sufficient: MCP cannot coordinate the two autonomous agents, and A2A is not how an agent talks to its own database. The responsibility split is the whole point, and on AWS each edge maps to a different AgentCore surface — MCP to a Gateway target, A2A to a Runtime-hosted server.

4. AgentCore Gateway as the Broker

In the in-process world, an agent's tools are function calls. In the cross-runtime world they are network endpoints scattered across teams, accounts, and vendors — each with its own authentication, its own availability, and its own blast radius. Amazon Bedrock AgentCore Gateway is the service that consolidates that sprawl into a single, governed entry point: one URL an agent connects to, behind which the Gateway routes to tools, downstream agents, and models, applying authentication, observability, and policy uniformly.

4.1 Three target types

A Gateway connects to backends called targets, and there are exactly three categories — this is the mental model to anchor on:
  • MCP targets operate in aggregation mode. The Gateway combines the capabilities of all its MCP targets into a single unified virtual MCP server: a client sees one consolidated tools/list that spans every attached target. MCP target types include Lambda functions, API Gateway REST APIs, OpenAPI specifications, Smithy models, remote MCP servers, and built-in connectors. MCP targets support capability synchronization, semantic tool search, and three-legged OAuth (3LO) at the target level.
  • HTTP targets send traffic directly to the target, without aggregation or protocol translation. HTTP target types explicitly include AgentCore Runtime agents, other agents (including A2A services), external MCP servers, and any HTTP endpoint reached through a passthrough target. Clients address each HTTP target individually through path-based routing; HTTP targets do not participate in capability synchronization or semantic tool search.
  • Inference targets route LLM traffic to one or more model providers through a unified endpoint, selecting the destination from the model field in the request — giving agents one interface across providers.

The split between MCP and HTTP targets is the key to where A2A fits today, covered in 4.3.

4.2 Registering an MCP target

The MCP edge is the one you wire most often: you expose a tool server (for example a Lambda-backed MCP server — see the MCP Server on AWS Lambda Complete Guide for building it and for registering Lambda targets specifically) and attach it to a Gateway, which folds it into the unified virtual MCP server. An MCP-server target with IAM (SigV4) outbound authorization is created against the bedrock-agentcore-control API:
aws bedrock-agentcore-control create-gateway-target \
  --gateway-identifier "your-gateway-id" \
  --name "InventoryMcpTarget" \
  --target-configuration '{
    "mcp": {
      "mcpServer": {
        "endpoint": "https://my-server.bedrock-agentcore.us-west-2.api.aws"
      }
    }
  }' \
  --credential-provider-configurations '[{
    "credentialProviderType": "GATEWAY_IAM_ROLE",
    "credentialProvider": {
      "iamCredentialProvider": {
        "service": "bedrock-agentcore",
        "region": "us-west-2"
      }
    }
  }]'
The service value for SigV4 depends on where the server is hosted: bedrock-agentcore for servers on AgentCore Runtime or another Gateway, execute-api behind API Gateway, lambda behind a Lambda Function URL. For OpenAPI or remote MCP-server targets you can instead attach an AgentCore credential provider that stores an API key or OAuth credentials. Each gateway also requires an inbound authorizer to control who may call the gateway itself, with four types: OAuth (JWT), IAM (SigV4), authenticate-only (validate the token, delegate authorization to the target), and none (development only).

What happens on a tool call is worth understanding because it is where identity and the Gateway meet. When a tools/call arrives for an MCP target, the Gateway validates the tool exists in its synchronized definitions, then performs an MCP initialize to open a session with the target server; if that target is configured with OAuth credentials, the Gateway first retrieves fresh credentials from AgentCore Identity before the initialize — so even if the cached tools/list carried stale credentials, the actual invocation uses valid auth. Identity is therefore not a side concern bolted onto the Gateway; it is consulted on the hot path of every authenticated call.

4.3 Where A2A fits today — and what is emerging

Here the article must be precise, because this is exactly the kind of fast-moving integration that invites overstatement. Two facts are established in the official documentation:
  • The Gateway's HTTP target type explicitly supports A2A services and AgentCore Runtime agents as direct-proxy backends. So the Gateway can already sit in front of a downstream A2A agent (or a Runtime-hosted agent) and proxy traffic to it — applying its inbound authorizer — without translating the protocol.
  • AgentCore's protocol support, per the official FAQ, is: "AgentCore supports Model Context Protocol (MCP) and Agent to Agent Protocol (A2A). A2A support is currently available in AgentCore Runtime, with broader A2A support across other AgentCore services coming soon."

Read together: today, the agent-to-agent edge is served by A2A running on AgentCore Runtime (Section 6), with the Gateway able to front an A2A service as an HTTP target (proxy, no aggregation or A2A-aware translation). Broader, native A2A handling across other AgentCore services — including any A2A-aware aggregation in the Gateway analogous to MCP aggregation — is announced as forthcoming, not shipped. This article therefore builds the fabric on the generally available pieces (Runtime A2A + Gateway MCP aggregation + Gateway HTTP/A2A proxy) and treats deeper native Gateway A2A as an explicit forward-looking item in Section 9.

4.4 Choosing a target type

The three target types are not interchangeable, and the choice follows the counterparty, not preference. Register a backend as an MCP target when it is a tool surface you want consolidated and searchable: the Gateway aggregates it into the unified virtual MCP server, so clients see one tool list and you get capability synchronization and semantic tool search across everything attached. Register it as an HTTP target when it is an endpoint you want reached as-is — a downstream A2A agent, another AgentCore Runtime agent, an external MCP server you do not want aggregated, or any passthrough HTTP service — addressed individually by path, with no capability merging. Use an inference target when the backend is a model and you want provider-agnostic routing by the request's model field. The litmus test for the agent-to-agent case is this: a peer agent is a counterparty, not a tool, so it belongs behind an HTTP target; forcing it into MCP aggregation would misrepresent an autonomous agent as a flat set of callable tools and lose the task lifecycle that A2A exists to carry.

5. Identity Propagation and Authorization

Cross-runtime interoperability fails closed if identity does not travel with the request. The hard requirement is this: a user authenticates once at the front door, and that identity must reach the deepest downstream tool — re-scoped at each hop, never re-prompted — so that every layer, including a tool owned by a different team, can enforce its own per-user authorization against the real principal rather than a service account. AgentCore Identity is the component that makes this work.

5.1 Inbound and outbound authentication

AgentCore Identity handles two directions. Inbound authentication controls who may invoke your agent or tool: AWS IAM (SigV4) for AWS-identity-based access, or OAuth 2.0 / JWT bearer tokens from an external identity provider (Amazon Cognito, Okta, Microsoft Entra ID), validated for issuer, signature, and expiry before the request proceeds. Outbound authentication lets your agent reach third-party services using OAuth or API keys, in either a user-delegated mode (acting on behalf of the end user) or an autonomous mode (acting with service-level credentials). A token vault stores users' resource-provider tokens and the agent's own OAuth client credentials, so neither the agent code nor the Gateway has to manage long-lived secrets; expired tokens are refreshed, or a fresh consent prompt is triggered, automatically.

For an A2A server hosted on AgentCore Runtime, the two inbound mechanisms map to two concrete access models. With IAM SigV4 — the default — a caller is authorized by holding the bedrock-agentcore:InvokeAgentRuntime permission, which for a cross-account peer means assuming an IAM role that grants it and signing the request; this is the natural fit when both agents live in AWS accounts you control. With OAuth 2.0 / JWT, you configure the runtime with the provider's discovery URL, the allowed audiences, and the allowed client IDs, and the caller presents a bearer token; this is the fit for cross-organization peers federated through an external IdP. There is also a user-scoped path for outbound flows — the X-Amzn-Bedrock-AgentCore-Runtime-User-Id header, which requires the separate bedrock-agentcore:InvokeAgentRuntimeForUser action — but for production the JWT path is preferred because it cryptographically proves the end-user identity rather than trusting the caller to assert it.

5.2 On-behalf-of token exchange — the propagation mechanism

The mechanism that carries identity across hops without re-consent is OAuth 2.0 on-behalf-of (OBO) token exchange, built into the AgentCore Identity OAuth credential provider. When an agent needs a downstream token, AgentCore Identity takes the inbound user token (the upstream caller) plus the stored client credentials and brokers a token exchange with the identity provider, returning a new token scoped to the downstream audience that binds both the user's identity and the agent's identity. The agent developer never handles the inbound token or client secrets directly — a single call to GetResourceOauth2Token with the workload access token returns the scoped downstream token. AgentCore Identity supports two standards for this, chosen per identity provider: RFC 8693 (OAuth 2.0 Token Exchange) and RFC 7523 (JWT Profile for OAuth 2.0 Authorization Grants).

Concretely, across a chain the original subject (sub: X) is preserved while the audience tightens at each hop: an MCP client authenticates to the Gateway with a token scoped aud: gw; when the Gateway calls a downstream MCP-server target, AgentCore Identity exchanges that for a token scoped aud: mcp; if that server then calls a further API, it obtains a token scoped aud: api. Every service receives a token minted precisely for it, carrying the real user identity, so it can make a fine-grained, per-user decision without a second consent flow. This is the zero-trust property that makes cross-team and cross-org tool access safe: a token captured at one hop is useless at the next, because its audience does not match.
# Inside a tool/agent: obtain a downstream, audience-scoped token bound to the
# caller's identity via AgentCore Identity OBO. The agent never touches the
# inbound user token or any client secret directly.
import boto3

identity = boto3.client("bedrock-agentcore")

resp = identity.get_resource_oauth2_token(
    workloadIdentityToken=workload_access_token,   # the agent's workload token
    resourceCredentialProviderName="downstream-hr-api",  # pre-configured OAuth provider
    scopes=["read:benefits"],                      # least privilege for this call
    oauth2Flow="ON_BEHALF_OF_TOKEN_EXCHANGE",      # on-behalf-of the authenticated user
)
downstream_token = resp["accessToken"]
# Use downstream_token only for the audience this provider is configured for.

5.3 Authorization is a separate decision (delegated)

Authenticating the caller is not the same as authorizing the call. The Gateway evaluates Cedar policy to decide whether a given principal may invoke a given action — and that evaluation is default-deny with forbid-wins, so the absence of an explicit permit is a denial, not a gap. The full Cedar model for AgentCore — the AgentCore::OAuthUser principal derived from JWT sub and claims-as-tags, the <Target>___<tool> action naming, parameter conditions, and the LOG_ONLY rollout pattern — is covered in Amazon Bedrock AgentCore Policy Implementation Guide and is not repeated here. The point for the fabric is the layering: inbound auth proves who is calling, OBO carries that identity downstream with a tightened audience, and Cedar decides — per principal, per action — whether the call is allowed. Authentication, propagation, and authorization are three distinct controls, and the cross-runtime boundary needs all three.

6. The End-to-End Flow of One Task

This section walks a single cross-organization task through the architecture, naming the exact call at each hop and showing where authorization can stop it. The scenario from Section 3.3: an inventory agent (organization A) must place a reorder with a supplier agent (organization B); the supplier agent fulfills it using its own MCP tools.
End-to-end flow of one cross-runtime task, with authorization-denied branch
End-to-end flow of one cross-runtime task, with authorization-denied branch
Step 1 — Discovery. The client agent resolves the supplier agent's Agent Card, either by fetching /.well-known/agent-card.json directly or by looking it up in a catalog (Section 6.1). The card tells it the endpoint, the skills offered, and — critically — the authentication the supplier requires. If the card is signed (A2A v1.0), the client verifies the signature against the claimed domain before trusting the endpoint, which is what prevents a forged card from redirecting the task to an impostor.

Step 2 — Delegation. The client agent sends an A2A message/send (JSON-RPC 2.0 over HTTP/S) to the supplier's endpoint, carrying a bearer token whose audience is the supplier. On AWS the supplier agent is an A2A server hosted on AgentCore Runtime; invocation goes through InvokeAgentRuntime, and AgentCore passes the JSON-RPC payload through to the A2A container unmodified while adding a session-isolation header, X-Amzn-Bedrock-AgentCore-Runtime-Session-Id.

Step 3 — Inbound authorization at the remote agent. The supplier's inbound authorizer (OAuth/JWT or SigV4) validates the token's issuer, signature, expiry, and audience. Denied branch: a missing, expired, or wrong-audience token is rejected here — the task never starts, and the client receives an error, not a partial result. This is the first place the deny path can fire.

Step 4 — Tool call. To fulfill the task the supplier agent calls its own tools through its AgentCore Gateway — an MCP tools/call against the unified virtual MCP server (for example, reserve_inventory).

Step 5 — Identity propagation. Before the Gateway reaches the backend, AgentCore Identity performs the OBO exchange (Section 5.2): the inbound token (aud: gw) becomes a downstream token (aud: mcp or aud: api) that still carries the original subject. The downstream tool now sees the real principal, audience-bound to itself.

Step 6 — Action authorization. The Gateway evaluates Cedar for this principal and this <Target>___<tool> action. Denied branch: under default-deny, if no policy permits the action — or a forbid matches — the call returns a 403 to the supplier agent, which surfaces it as a failed task step rather than silently doing nothing. This is the second deny path, and it is independent of Step 3: a caller can be authenticated yet unauthorized.

Step 7 — Result. The tool result returns through the Gateway to the supplier agent, which packages the outcome as an A2A Artifact (an order confirmation) and returns it to the client agent, which reports it to the user. For long-running fulfillment the task can stream status updates over SSE rather than blocking.

The two deny branches (Steps 3 and 6) are the operational heart of the design: authentication failure and authorization failure are distinct, surface at different hops, and produce different signals — which is precisely what makes a cross-runtime failure diagnosable instead of an opaque "the other agent didn't do it."

6.1 Implementing the remote agent (A2A server)

The remote agent is an A2A server hosted on AgentCore Runtime, which acts as a transparent proxy: your container runs a stateless, streamable HTTP A2A server on port 9000 at the root path (0.0.0.0:9000/), and AgentCore passes the JSON-RPC payloads from InvokeAgentRuntime through to the container unmodified while adding per-session isolation and enterprise authentication (SigV4 / OAuth 2.0). The differentiators from AgentCore's other protocols are the port (9000 vs 8080 for plain HTTP, 8000 for MCP), the mount path (/ vs /invocations for HTTP, /mcp for MCP), and the built-in Agent Card discovery. The AgentCore SDK's serve_a2a helper handles the /ping health endpoint, Agent Card serving, the AGENTCORE_RUNTIME_URL environment variable, Bedrock header propagation, and the port. The CLI scaffolds a project with agentcore create --protocol A2A and supports A2A projects built with frameworks such as Strands Agents, LangChain/LangGraph, and Google ADK (the broader set of hosting frameworks is listed in Section 9):
from strands import Agent, tool
from strands.multiagent.a2a.executor import StrandsA2AExecutor
from bedrock_agentcore.runtime import serve_a2a
from model.load import load_model

@tool
def reserve_inventory(sku: str, quantity: int) -> str:
    """Reserve quantity units of a SKU and return a confirmation id."""
    # Behind this tool, the supplier agent calls its OWN systems via MCP -
    # its database and warehouse - through its own AgentCore Gateway.
    return f"confirmed: reserved {quantity} x {sku}"

agent = Agent(
    model=load_model(),
    system_prompt="You fulfill supplier reorder tasks. Use tools when appropriate.",
    tools=[reserve_inventory],
)

if __name__ == "__main__":
    serve_a2a(StrandsA2AExecutor(agent))   # Bedrock-compatible A2A server on 0.0.0.0:9000
Deploying with agentcore deploy packages the code and dependencies, uploads the artifact to Amazon S3, creates the AgentCore runtime, and returns an agent runtime ARN of the form arn:aws:bedrock-agentcore:us-west-2:accountId:runtime/my_a2a_server-xyz123. The deployed agent serves its Agent Card — identity, skills, endpoint, and auth requirements — at the runtime's /.well-known/agent-card.json, behind whatever inbound authorizer you configured. The remote agent's tools (here reserve_inventory) are exactly the MCP edge delegated to the companion guides; the A2A server is only the agent-to-agent face the client sees.

6.2 Invoking from the client agent

The client side does two things: resolve the peer's Agent Card, then send the task. Against a deployed AgentCore runtime the A2A endpoint is the InvokeAgentRuntime path with the URL-encoded ARN, and the caller supplies a bearer token plus a session ID; because of AgentCore's path-based mounting, the resolved card already carries the correct URL, so no manual override is needed. The standard A2A SDK client (A2ACardResolver + ClientFactory) does the resolution and sending:
import asyncio, os
from uuid import uuid4
import httpx
from a2a.client import A2ACardResolver, ClientConfig, ClientFactory
from a2a.types import Message, Part, Role, TextPart

async def delegate(text: str):
    runtime_url = os.environ["AGENTCORE_RUNTIME_URL"]
    headers = {
        "Authorization": f"Bearer {os.environ['BEARER_TOKEN']}",
        "X-Amzn-Bedrock-AgentCore-Runtime-Session-Id": str(uuid4()),
    }
    async with httpx.AsyncClient(timeout=300, headers=headers) as http:
        # 1. Discover: fetch the remote agent's Agent Card
        agent_card = await A2ACardResolver(httpx_client=http, base_url=runtime_url).get_agent_card()
        # 2. Delegate: build a client from the card and send the task
        client = ClientFactory(ClientConfig(httpx_client=http, streaming=False)).create(agent_card)
        msg = Message(
            kind="message", role=Role.user,
            parts=[Part(TextPart(kind="text", text=text))], message_id=uuid4().hex,
        )
        async for event in client.send_message(msg):
            return event   # a Message, or a (Task, UpdateEvent) tuple for longer-running work

asyncio.run(delegate("Reserve 200 units of SKU-4471 for next week."))
Set streaming=True on the ClientConfig to consume incremental status updates for long-running tasks instead of a single synchronous result. The bearer token here is exactly what the remote agent's inbound authorizer validates at Step 3 of the flow; for a cross-account peer authorized by IAM, the caller instead assumes a role permitted to call bedrock-agentcore:InvokeAgentRuntime and SigV4-signs the request rather than carrying a JWT. Either way, discovery (the card) and invocation (the token or signature) are separate steps, which is what lets you publish a discoverable agent without making it callable by everyone who can see it.

6.3 Discovery at scale: the AWS Agent Registry

Fetching a single well-known URL works for two agents that already know each other's domains. At organizational scale — dozens of agents across teams, each needing to find the right peer — you need a catalog. AWS Agent Registry (preview), part of Amazon Bedrock AgentCore, is a single place to discover, reuse, and govern agents, tools, and agent skills across an organization: it stores a structured record for each agent/tool/MCP server/skill, capturing who published it, what protocols it implements, what it exposes, and how to invoke it, and it supports MCP and A2A natively (the Control API models an A2A record as an A2aDescriptor carrying an AgentCardDefinition). It works across agents built on AgentCore, other providers, or on premises. In the flow above, Step 1 becomes a Registry lookup rather than a hard-coded URL, which is what makes discovery governable — you can see and control which agents are discoverable and by whom.

7. Contracts, Versioning, and Trust Boundaries

In-process agents share a codebase, so their "contract" is just function signatures that change together. Cross-runtime agents share nothing but the wire, so the contract becomes a first-class artifact that must be explicit, versioned, and verifiable. Three concerns dominate.

The Agent Card is the contract. It is the machine-readable statement of what a remote agent is and how to use it — identity, skills, endpoints, supported transports, and authentication requirements. A client agent should treat the card as the source of truth and degrade gracefully when a peer advertises a capability it does not have, rather than assuming a shape. Because the card is fetched over the network from another party, its authenticity matters: A2A v1.0's signed Agent Cards let a receiver verify the card was issued by the claimed domain owner before trusting its endpoints or auth requirements. Treat an unsigned card from outside your trust domain as untrusted input.

Versioning is negotiated, not assumed. The A2A specification advanced through the 0.x line to v1.0.0, and v1.0 added explicit version negotiation so a client and server can agree on a mutually supported protocol version with backward-compatible migration from 0.x. The same discipline applies one layer down at the MCP edge, where the protocol version is part of the handshake (the MCP specification version and the cross-vendor compatibility picture are covered in MCP Server Implementation Reference). The practical rule for the fabric: pin the protocol versions you test against, prefer additive (backward-compatible) changes to capabilities, and advertise capabilities through the card and tools/list rather than through out-of-band documentation, so a peer can adapt at runtime instead of breaking.

Trust boundaries: reachable is not authorized. The most important security principle in a cross-runtime fabric is that network reachability and authorization are orthogonal. An agent that can resolve another agent's Agent Card and open a connection has proven nothing about whether it is allowed to delegate to it; that decision belongs to the inbound authorizer and Cedar (Section 5). Designing for this means: default-deny at every boundary; signed Agent Cards as the trust root for discovery; audience-scoped tokens (Section 5.2) so a credential leaked at one hop cannot be replayed at the next; and explicit allow-lists for which agents may invoke which peers. A2A v1.0's multi-tenancy (one endpoint hosting many agents) makes this boundary discipline more important, not less — co-tenanted agents must not be able to reach each other's tasks merely because they share an endpoint.

Across accounts and organizations the trust boundary is also an AWS access boundary, and the two halves are independent switches. Discoverability is whether a peer can resolve your Agent Card; invokability is whether it holds bedrock-agentcore:InvokeAgentRuntime (via an assumed role for SigV4) or presents a JWT your inbound authorizer accepts. Publishing a card without granting invoke leaves a peer able to see but not call — which is the correct default for a catalog entry awaiting an access grant. The practical consequence for cross-org design is that onboarding a partner agent is two deliberate acts: list it (or accept its card), then grant the specific invoke permission — never one implying the other.

8. Observability and Failure Modes

A request that crosses two runtimes, two organizations, and two protocols has many more ways to fail than an in-process call, and — without deliberate instrumentation — many fewer ways to see why. The operational goal is that each failure surfaces at the hop that caused it, with a signal specific enough to act on, instead of collapsing into "the other agent gave a bad result."

8.1 Tracing across runtimes and protocols

Agents hosted on AgentCore Runtime automatically emit OpenTelemetry-compatible traces, spans, and metrics to Amazon CloudWatch, viewable in the CloudWatch GenAI Observability console; built-in metrics include session count, latency, duration, token usage, and error rates, the metrics namespace is bedrock-agentcore, and runtime logs land under log groups beginning /aws/bedrock-agentcore/runtimes/. Viewing traces requires a one-time enablement of CloudWatch Transaction Search. The continuity challenge unique to interoperability is correlating a trace across the A2A hop: the client agent's span, the A2A task on the remote agent, and the MCP tool-call spans behind it are three separate traces unless you carry a correlation identifier. The AgentCore Runtime session header (X-Amzn-Bedrock-AgentCore-Runtime-Session-Id) and the A2A task ID are the anchors to propagate and tag on your own spans so a single user goal is reconstructable end to end. Instrument the discover / delegate / tool-call / result stages explicitly so each appears as a timed segment.

8.2 Failure modes and how to isolate them

* You can sort the table by clicking on the column name.
SymptomLikely root causeHow to isolateContainment / remediation
Task rejected immediately by peerInbound auth failure (missing/expired/wrong-audience token)Remote agent's authorizer logs; 401/403 at Step 3 before any task spanRefresh/scope the token to the peer's audience; check the Agent Card's stated auth requirements
Authenticated but tool call deniedCedar default-deny / no matching permit403 at the Gateway on a <Target>___<tool> action with a valid identityAdd the least-privilege permit; roll out with LOG_ONLY first (delegated guide)
Capability not found on peerProtocol/version mismatch or stale cardA2A version negotiation failure; advertised skill absent from the live cardPin and negotiate versions; re-fetch the card; treat capabilities as advertised, not assumed
Downstream call works for the agent but not per-userIdentity not propagated (service identity used instead of OBO)Downstream sees a service principal, not sub: X; per-user data missingUse OBO GetResourceOauth2Token; verify the downstream token's audience and subject
Forged or wrong peer answeredUnverified Agent Card / discovery spoofingCard signature absent or fails verificationRequire signed Agent Cards from outside the trust domain; resolve via Agent Registry
Long-running task appears to hangTimeout / streaming not consumedTask stuck in a non-terminal state; no SSE status updates consumedConsume task status over SSE; set client deadlines; design idempotent retries on the task ID
Trace breaks at the agent boundaryCorrelation ID not propagated across A2AThree disjoint traces; no shared session/task IDPropagate the session header and A2A task ID; tag custom spans at each hop
Credential refresh failuresToken vault entry expired without refreshOutbound auth errors on a previously working integrationConfirm refresh-token validity in the vault; re-trigger consent if the refresh grant is revoked

The pattern across every row is the same: because each hop authenticates, authorizes, and traces independently, a failure surfaces at the responsible hop with a specific signal — an inbound 401 is not a Cedar 403 is not a version-negotiation error is not a propagation gap. That separation is the operational payoff of building the fabric on explicit protocols and an identity-aware broker rather than on point-to-point glue.

8.3 What to alarm on

Tracing tells you what happened after the fact; alarms tell you while it is happening. Across the fabric, five signals are worth a CloudWatch alarm because each maps to a distinct failure class from the table above: the inbound 401/403 rate at each agent (credential or audience drift), the Cedar deny rate at the Gateway (policy too tight, or a caller probing for what it can reach), the Agent Card verification-failure rate (a forged card or an expired signing key), the task-timeout / non-terminal rate (a peer degrading, or clients not consuming status updates), and the trace-gap rate (correlation IDs not propagating across the A2A hop). Put anomaly detection on each rather than fixed thresholds, since a healthy baseline differs per integration, and use composite alarms so that several degrading together — a rising deny rate alongside rising timeouts, say — pages someone before any single signal would on its own. The discipline mirrors the failure table: each alarm is scoped to one hop and one cause, so the page tells you where to look instead of that something, somewhere, is wrong.

9. Outlook: What Is Stable Today vs Emerging

Because this topic moves quickly, the honest thing to do is separate what you can build on now from what is announced but not yet shipped.

Generally available today — the backbone this article is built on:
  • A2A servers on AgentCore Runtime. Hosting an A2A agent (port 9000, Agent Card discovery, JSON-RPC, SigV4/OAuth) is supported, with framework choices including Strands, LangGraph, Google ADK, OpenAI Agents SDK, and the Claude Agent SDK.
  • AgentCore Gateway MCP aggregation into a unified virtual MCP server, plus HTTP targets that can proxy to A2A services and Runtime agents.
  • AgentCore Identity inbound/outbound auth and OAuth on-behalf-of token exchange (RFC 8693 / RFC 7523) for cross-hop identity propagation.
  • Cedar authorization at the Gateway with default-deny semantics (delegated guide).
  • The A2A v1.0 specification itself — stable data models and bindings, signed Agent Cards, multi-tenancy, version negotiation — under Linux Foundation governance.

Emerging — design for it, do not depend on it yet:
  • Broader native A2A across AgentCore services. The official FAQ states A2A is available in AgentCore Runtime today, "with broader A2A support across other AgentCore services coming soon." Any A2A-aware aggregation or translation in the Gateway analogous to MCP aggregation falls here; today the Gateway fronts A2A as an HTTP proxy.
  • AWS Agent Registry maturity. The Registry exists and natively models A2A and MCP records; verify its availability stage and the discovery/governance API surface before building hard dependencies on it.
  • Signed Agent Card adoption. The capability is in A2A v1.0; ecosystem-wide issuance and verification are still spreading, so plan to handle both signed and unsigned cards during the transition.
  • Adjacent protocols. A payments-oriented companion protocol (Agent Payments Protocol) has been discussed in the A2A ecosystem; it is out of scope here and should not be assumed available on AWS.

The safe posture: build on the GA backbone, keep the A2A-vs-MCP responsibility split clean, push identity through OBO and authorization through Cedar from day one, and treat native-Gateway-A2A and a fully governed Registry as upgrades you adopt when they ship rather than architecture you presuppose. Concretely, your A2A servers and clients, your Gateway MCP targets, your OBO flows, and your Cedar policies are production-ready now; what you defer is leaning on the Gateway to understand A2A semantics natively, or on the Registry as a hard dependency for discovery — both of which you can adopt incrementally, as they mature, without re-architecting the edges you build today.

10. Frequently Asked Questions

Is A2A a replacement for MCP?
No — they own different edges. MCP standardizes how one agent reaches its tools and data; A2A standardizes how independent agents discover and coordinate with each other. A mature system runs both: MCP behind each agent for tools, A2A between agents. Treating them as alternatives is the most common modeling mistake in this space.

Do I need A2A if all my agents are built with one framework?
Usually not. If your agents share a runtime and a codebase, in-process patterns (agents-as-tools, swarm, graph, workflow) are simpler — see Strands Agents Multi-Agent Pattern Selection Guide. A2A earns its place precisely when agents cross a runtime, framework, or organizational boundary and cannot see each other's internals.

How does an agent discover another agent?
Through its Agent Card — a JSON document served at /.well-known/agent-card.json advertising identity, skills, endpoints, and auth requirements. At organizational scale, the AWS Agent Registry catalogs these records so discovery is governable rather than hard-coded. Verify card signatures (A2A v1.0) before trusting a card from outside your trust domain.

Where does the Gateway fit if A2A handles agent-to-agent?
The Gateway consolidates and governs the tool edge: it aggregates MCP targets into one virtual MCP server and applies a single inbound authorizer, credential management, and policy. It can also front a downstream A2A service as an HTTP target (direct proxy, no protocol translation). The agent-to-agent A2A server itself runs on AgentCore Runtime.

How is a user's identity carried to a tool owned by another team?
With OAuth on-behalf-of token exchange in AgentCore Identity. The inbound user token is exchanged for a downstream token scoped to the target's audience that still carries the original subject, using RFC 8693 or RFC 7523 — no second consent prompt. Each hop receives a token minted for it, so a leaked token cannot be replayed elsewhere.

Does a successful authentication mean the call is authorized?
No. Authentication proves who is calling; authorization (Cedar, default-deny) decides whether this principal may perform this action. They are separate controls that fail at different hops — a caller can be authenticated and still denied. See Amazon Bedrock AgentCore Policy Implementation Guide for the policy model.

Can I rely on native A2A inside AgentCore Gateway?
Today, build the agent-to-agent edge on AgentCore Runtime A2A, with the Gateway fronting A2A services as HTTP targets. AWS has stated broader A2A support across other AgentCore services is coming; verify its current scope before depending on Gateway-native A2A behavior.

11. Summary

In-process multi-agent orchestration ends at the runtime boundary; the moment agents must work across runtimes, frameworks, or organizations, you need a different set of primitives — discovery, delegation, and trust across parties that cannot see each other's code. The Cross-Runtime Agent Fabric on AWS assembles those primitives from open protocols and managed services: A2A for the agent-to-agent edge (Agent Cards, tasks, artifacts, JSON-RPC, signed-card trust), MCP for the agent-to-tool edge, AgentCore Gateway as the broker that aggregates MCP tools and fronts downstream agents behind one governed endpoint, AgentCore Identity carrying the user's identity across every hop via OAuth on-behalf-of exchange, Cedar deciding what is allowed under default-deny, and the AWS Agent Registry making discovery governable.

The through-line is separation of concerns at every boundary. A2A and MCP never overlap. Authentication, identity propagation, and authorization are three distinct controls that fail at three distinct hops with three distinct signals. Discovery, delegation, and trust are decoupled so that "reachable" never implies "authorized." That separation is what makes a cross-runtime system diagnosable — a failure surfaces at the hop that caused it — and safe — a credential is useful only at the audience it was minted for. Build on the generally available backbone (Runtime A2A, Gateway MCP aggregation and HTTP/A2A proxy, Identity OBO, Cedar), delegate the foundations to the companion guides, and treat native-Gateway-A2A and a fully governed Registry as enhancements to adopt when they ship — and you have an interoperability fabric you can extend to any agent, anywhere, without giving up control of who may do what.

12. References

Related Articles in This Series


References:
Tech Blog with curated related content

Written by Hidekazu Konishi