Bifrost adds an Agent Gateway that proxies A2A agents beside model and MCP traffic
The open-source gateway's v2.3.0 release, out October 13, registers A2A agents by their agent cards, rewrites those cards to gateway endpoints, bridges transports, relays push notifications and gates every call on virtual-key grants. A v2.3.1 follow-up tightened destination and credential rules.
Bifrost, the open-source AI gateway from Maxim AI, can now sit in front of AI agents, not only in front of models and tools. Version 2.3.0, released on October 13, 2026, added a feature the changelog calls “Agent Gateway (A2A)”: operators register any agent that speaks the Agent2Agent (A2A) protocol, and client applications reach it through gateway routes that apply access grants, credential rules and logging. The feature was announced on the Bifrost blog on October 20, and a v2.3.1 release on October 19 had already tightened how the gateway builds public URLs and which destinations it will connect to. The release puts the three kinds of traffic an agent system generates (model calls, tool calls over the Model Context Protocol, and calls between agents) behind one control point.
TL;DR
- Bifrost v2.3.0 (October 13, 2026) proxies A2A v1 agents. An agent is registered by its agent card URL and exposed at
/agents/a2a/<name>/over JSON-RPC with server-sent events, REST, and an optional shared gRPC listener.- The gateway rewrites the agent card so clients discover gateway endpoints, and it bridges transports: a REST client can reach a JSON-RPC or gRPC agent.
- Access is per virtual key through
agent_grants, with anallow_by_defaultswitch per agent. Enterprise tier: grants can also come from access profiles and projects.- The caller’s Bifrost credential is stripped before forwarding unless the operator opts in. Outbound connections are checked against a private-network allowlist and, since v2.3.1, per-agent
credential_origins.- Push notifications are relayed through a durable, retried outbox, and every A2A operation lands in a new Agent Logs view that links to the agent’s own model and tool calls.
The release at a glance
| Item | Detail | Source |
|---|---|---|
| Shipped in | Bifrost v2.3.0, October 13, 2026 | v2.3.0 changelog |
| Announced | October 20, 2026, Bifrost blog post by Dhwanil Pithva | Announcement post |
| Protocol | Agent2Agent (A2A), version 1 | Agent Gateway docs |
| Client routes | /.well-known/agent-card.json, /json-rpc, /rest, under /agents/a2a/<name>/ | v2.3.0 changelog |
| gRPC | Optional shared listener, routed by <agent>.<a2a_grpc_base_domain>:<a2a_grpc_port> | v2.3.0 changelog |
| Registration | Dashboard, POST /api/agents, or a config.json agents array | v2.3.0 changelog |
| Access control | Virtual-key agent_grants, per-agent allow_by_default | v2.3.0 changelog |
| Enterprise additions | agent_grants on access profiles and projects, IdP user attribution, new RBAC resources for agents and agent logs | Enterprise v2.3.0 changelog |
| Required setting | client.a2a_external_client_url (the public base URL) | v2.3.0 upgrade notes; configuration docs |
| Follow-up | v2.3.1 (October 19): explicit public URLs, destination permissions, push-relay hardening | v2.3.1 changelog |
From models to tools to agents
AI gateways began as a proxy for model calls. A gateway in that sense is a service between an application and model providers that handles routing, failover, keys, budgets and logging; Bifrost exposes 25+ providers and 10,000+ models through one OpenAI-compatible API, and its published benchmark reports 11 µs of added overhead per request at 5,000 RPS on an AWS t3.xlarge. The second wave added tools. When agents started calling external systems through the Model Context Protocol (MCP), the same gateways grew MCP features: tool catalogs, per-key tool filtering and audit logs. This publication’s guide to the Model Context Protocol covers that protocol, and the MCP gateway comparison covers the products built around it.
Agents talking to agents is the third kind of traffic, and it has its own protocol. Google launched A2A in April 2025, and on June 23, 2025 the Linux Foundation announced it would host the project, saying A2A had “growing support from more than 100 leading technology companies” and would “remain vendor neutral” under foundation governance. The specification now lists 1.0.0 as its latest released version, and the a2aproject repository is licensed Apache 2.0.
The specification frames the split between the two protocols plainly. In its Appendix B, MCP is about how agents “connect to and interact with tools, APIs, data sources, and other external resources,” while A2A is about how “independent, often opaque, AI agents communicate and collaborate with each other as peers.” A server agent may use MCP to do the work an A2A task asks for; the A2A vs MCP explainer covers the division.
The release targets the problem that layering creates. The announcement post describes one agent handing work to another, which then calls a model and some tools and asks who started the request, whether they should have been allowed to call that agent, and which calls produced the answer. “Each service might have its own logs,” the post says. “Following the work across all of them is where things get tedious.”
How A2A works
A2A defines a small data model and a set of operations, then maps those operations onto three standard bindings. The pieces a gateway has to handle are these.
The agent card. An agent publishes a JSON document describing its skills, capabilities, endpoints and authentication requirements. Section 8.2 of the specification names the default location, https://{server_domain}/.well-known/agent-card.json. Its supportedInterfaces list declares each binding “in preference order.” Cards may be signed with JSON Web Signature (JWS).
Messages, tasks and contexts. A message is something a user or agent says. A task is a unit of work with an ID and a state such as working, input-required or completed. A context groups related tasks into one conversation.
Operations and bindings. The core operations include SendMessage, SendStreamingMessage, GetTask, ListTasks, CancelTask, SubscribeToTask and a set of push-notification configuration calls. Each can be carried over JSON-RPC 2.0, gRPC, or an HTTP+JSON binding the Bifrost docs label REST. Streaming over HTTP uses server-sent events (SSE), a one-way stream of data: events on a held-open response. A client signals its version with an A2A-Version header.
Push notifications. For long tasks, a client can register a webhook and close its connection. The agent then POSTs updates to that URL. Section 13.2 puts the security burden on both ends: agents “SHOULD validate webhook URLs to prevent SSRF (Server-Side Request Forgery) attacks” by rejecting private and link-local ranges, and receivers “SHOULD process notifications idempotently, as duplicate deliveries may occur.”
Each feature creates a job for an intermediary. A card pointing straight at the agent lets clients bypass the gateway. Three bindings mean three ways in. Push callbacks are outbound requests to client-supplied addresses, the classic SSRF pattern.
Registering an agent
An operator registers an agent by the full card URL, not the base domain. The registration guide shows three routes: the dashboard (Agents, then Agent Catalog, then New Agent, paste the URL and Fetch), the management API at POST /api/agents with a POST /api/agents/inspect call for previewing a card, and a declarative agents array in config.json or Helm values. A minimal declaration from the docs looks like this:
{
"agents": [
{
"name": "library-research",
"agent_card_url": "https://research.example.com/.well-known/agent-card.json",
"enabled": true,
"allow_by_default": false,
"virtual_key_ids": ["YOUR_VIRTUAL_KEY_ID"],
"forward_accepted_credential": true,
"runtime_auth": {
"type": "headers",
"headers": {"Authorization": "env.RESEARCH_AGENT_AUTHORIZATION"}
}
}
]
}
The registration name becomes part of every gateway URL and, for gRPC, a DNS label, so it is limited to 63 characters there. Declarations are reconciled by name at startup. Card fetching and request authentication are configured separately.
Nothing is reachable until the public base URL is set. The configuration page says that while client.a2a_external_client_url is empty, the card, JSON-RPC, REST and push-callback routes return 503 and gRPC returns UNAVAILABLE, though registrations can still be managed.
Card rewriting and transport bridging
The gateway serves its own version of each agent’s card. Per the registration docs, every request to the gateway card URL fetches the current card from the agent, then Bifrost “rewrites its endpoints and authentication requirements for gateway access before returning it.” There is no cached fallback: if the upstream card cannot be fetched, the request fails.
Rewriting has a side effect the transports page spells out: any JWS signature over the upstream card no longer matches, so the gateway removes the original signatures from the card it serves. The registration preview still shows them, so signature checks belong at registration time.
The client-facing and agent-facing transports are chosen independently. The overview says a client can call over JSON-RPC while the gateway calls the agent over gRPC, and the announcement gives the inverse example: a REST client reaching a JSON-RPC agent “without a custom adapter between them.” For the upstream leg, the gateway follows the specification’s rule. It keeps eligible v1 interfaces from supportedInterfaces and, at equal versions, takes them in card order. “There is no fixed rule that prefers gRPC over HTTP or matches the caller’s transport,” the docs say. To change the preference, the agent’s owner reorders the card.
Failover between those interfaces is deliberately conservative. The recovery rules separate failures where the request clearly never arrived from ones where it may have:
| Upstream failure | Current operation | Later operations |
|---|---|---|
| Dial failure before delivery | Tries the next interface | Starts from the advanced interface |
| HTTP 404, 405, 410 or 426 | Tries the next interface | Advances and refreshes the card in the background |
A2A method not found, gRPC Unimplemented | Tries the next interface | Advances |
| HTTP 5xx, broken response, ambiguous network error | Returns the error, no replay | May advance |
| Authentication or validation error | Returns the error | Not treated as transport failover |
An ambiguous failure “may happen after the agent started work. Replaying it could create a second task,” the docs say. Streams are never replayed automatically, and because the gateway does not copy task state between interfaces, an agent advertising several bindings needs one shared task store.
gRPC routing by hostname
gRPC needed a different design. HTTP routes carry the agent name in the path, but every A2A gRPC client calls the same service methods. The gRPC section explains that the gateway reads the HTTP/2 :authority instead: with server.a2a_grpc_base_domain set to a2a.example.com and server.a2a_grpc_port to 443, the agent library-research is reached at library-research.a2a.example.com:443. That requires wildcard DNS and its own Service and ingress. The listener speaks plaintext gRPC, so TLS terminates at the ingress, which must preserve the agent-specific authority.
Push notifications through the gateway
Push is where the gateway stops being a pass-through. When a client registers a callback through Bifrost, the push notification docs say the gateway “replaces your callback URL and credentials with its own callback URL and a separate notification token before calling the upstream agent.” The agent only ever learns <base-url>/agents/a2a/<agent-name>/push/callback and a gateway-issued token. The client’s real webhook address and credentials stay in the gateway’s configuration database, where get and list calls return the URL but treat callback credentials as write-only.
Deliveries run through an outbox in that same database, so an accepted update survives a crash. Retries stop after six attempts with a 30-second timeout each, and delivery is at least once, matching the specification’s advice that receivers be idempotent.
The SSRF guidance in the specification is enforced by default. Callbacks to loopback or private addresses are blocked unless server.a2a_allow_private_push_callbacks is turned on, a startup-only setting the docs say to keep “disabled in production.” Push configurations are not removed when a task finishes; applications are expected to delete them through the gateway.
Access: virtual keys and agent grants
Registration gives an agent an address; grants decide who can use it. In the open-source gateway, a virtual key, the credential Bifrost issues to an application or user, can be granted specific agents by name. The v2.3.0 changelog lists the semantics: agent_grants on a key, where omitting the field keeps current grants, an empty list clears them, and unknown agent names are rejected atomically. Each agent also has allow_by_default, which admits any valid key. Ungranted or disabled agents return 403; JSON-RPC callers see a protocol error such as -31403 in the response body.
Agent access does not imply model or tool access.
Permission to call the research agent doesn’t automatically grant access to the models or MCP tools it uses.
That line from the announcement describes a deliberate separation: the key still needs its own provider and MCP tool grants.
The docs flag one configuration that operators should not miss. Without authentication enforcement, “requests that present no identity can pass through anonymously; explicit grants do not make anonymous traffic private.” The fix is client.enforce_auth_on_inference: true, which the announcement’s own setup checklist includes.
Enterprise tier. Bifrost Enterprise v2.3.0 adds “Agent Access Grants”: access profiles and projects can carry agent_grants, A2A bearer calls resolve the user through the identity provider, and the agent log records that user with their team, customer and business unit. New RBAC resources scope who can manage agents and read their logs. A project scopes a single request through an x-bf-project-name header. The docs note a current behavior worth knowing: when the named project is unknown or the caller is not a member, the gateway falls back to the caller’s own agent grants, so those grants should be restricted too.
Credentials and destination controls
A gateway between agents handles several secrets: the caller’s gateway credential, the card-fetch credential, the agent’s runtime credential, and possibly a TLS client certificate. The authentication guide treats each as a separate boundary.
Caller credentials stay home by default. The gateway strips the caller’s Bifrost credential before forwarding “unless you explicitly configure that registration to receive it.” Forwarding (forward_accepted_credential) exists for agents that call back into Bifrost for models and tools: the agent reuses the caller’s x-bf-vk on those calls, so budgets and access rules follow the original caller. If the forwarded credential and the agent’s own credential need the same header, a per-agent policy decides which wins, with the configured agent credential winning by default.
Upstream auth is non-interactive. Supported upstream schemes are static headers, OAuth 2.0 client credentials and custom TLS including mutual TLS. The docs state that “interactive sign-in and per-user OAuth consent are not part of agent registration.”
Every outbound connection is checked. Before connecting for card discovery, OAuth discovery, token requests or runtime calls, the gateway resolves the destination and allows only public addresses or entries on client.a2a_private_allowlist. The destination rules add that “link-local and cloud metadata addresses remain blocked even if an entry matches them,” which closes the standard route for stealing cloud credentials through a proxy.
Credentials only go to approved origins. The v2.3.1 changelog’s “Agent Gateway Destination Permissions” entry extends the check from networks to credentials. Card discovery, OAuth and runtime connections over JSON-RPC, REST and gRPC “only reach approved destinations and only forward credentials to permitted origins, per agent credential_origins and require_public_target.” In practice, the card’s own origin is trusted automatically. If the card advertises a runtime endpoint on another origin, an operator must approve it under Additional agent endpoints, up to 32 per agent, matched on scheme, host and port. The check applies even with no credential configured because “callers can supply their own upstream credential headers.” The same release added a require_public_target column to agent registrations; the matching MCP flag introduced in v2.3.0 is set by the server when dashboard auth is off and holds every later dial to public addresses.
Public URLs no longer come from the request. Also in v2.3.1, the gateway “no longer builds agent-card endpoints … from the incoming Host header, which a caller controls.” A client that could influence Host could otherwise get a card advertising endpoints of its choosing.
Agent Logs and telemetry
Every A2A operation and stream event gets its own log row in a new Agent Logs view, stored relationally, in ClickHouse, or in a hybrid with object-store payloads, according to the v2.3.0 changelog. Session grouping uses the A2A context ID.
The link to the agent’s internal work depends on the agent’s cooperation. The integration guide asks agents to send two headers on each model and MCP call they make through Bifrost: x-bf-session-id set to the A2A context ID and x-bf-agent-correlation-id set to the A2A task ID. With those in place, a task’s detail page shows its model calls, with tokens and cost, and its tool calls.
For external tools, A2A spans go out through the OpenTelemetry connector with attributes including gen_ai.agent.name, a2a.method.name, a2a.task.id and bifrost.a2a.upstream.transport, plus an a2a.client.operation.duration metric. v2.3.1 adds request and response bodies and stream updates to those exports, and Enterprise v2.3.1 adds them to the BigQuery, Datadog, Kafka and Pub/Sub connectors. The telemetry docs note that a full distributed trace still needs W3C trace context propagated by each service.
How other gateways handle A2A
Bifrost is one of several gateway and API-management vendors adding A2A support. Each documents a different scope.
| Product | A2A approach, as documented | Notable stated limits |
|---|---|---|
| Bifrost Agent Gateway (v2.3.0) | Registers agents by card; JSON-RPC with SSE, REST and gRPC on both sides with bridging; push relay; per-key grants | gRPC needs wildcard DNS and its own listener |
| Kong AI A2A Proxy plugin | Detects A2A over JSON-RPC and REST, rewrites card URLs to the gateway, feeds A2A metrics to analytics and OpenTelemetry | Kong Gateway 3.14 or later; AI Gateway Enterprise only |
| Azure API Management A2A agent API | Imports an agent by card URL, mediates JSON-RPC, applies policies, rewrites the card to the gateway host and adds a subscription key requirement | Only JSON-RPC-based agents supported |
| AWS AgentCore Gateway | Fronts other agents through passthrough targets, including A2A, alongside MCP tools and model routing | Managed AWS service |
Kong’s plugin docs describe it as “a transparent proxy” that “does not modify request routing, aggregate responses, or manage task state,” with card rewriting covering the url field and any additionalInterfaces URLs. Microsoft’s Learn page says API Management rewrites the card to set JSON-RPC as the preferred transport and “removes all other interfaces,” and adds genai.agent.id and genai.agent.name attributes when Application Insights is on. AWS’s documentation describes AgentCore Gateway as a “single, secure entry point for agentic traffic,” fronting other agents “through passthrough targets (including Agent-to-Agent (A2A) traffic).”
Card rewriting is the common baseline. Bifrost’s documented scope extends to transport bridging, gRPC, push relay and per-agent credential origins. For a wider view of the platforms that orchestrate agents rather than proxy them, see the agent orchestration platforms survey.
Upgrade notes and open items
The changelogs list what operators need to do.
- Migrations.
add_agent_gateway_tablescreates the agent registration, virtual-key agent grant, push config and push delivery tables and addsconfig_client.a2a_external_client_url. v2.3.1 addsadd_a2a_private_allowlist_column(reversible) andadd_agent_destination_policy_columns, which the changelog marks non-reversible because “removing them would discard security policy.” - Public URL. Per the v2.3.1 changelog, deployments that relied on the request host must “set the public URL explicitly before upgrading, or clients receive no usable agent-card endpoint.”
- Version. v2.3.1, out October 19, adds the destination policy, explicit public URLs and push-relay hardening, and bounds the agent OAuth token cache at 5,000 entries. v2.3.2, out October 20, is a Go security rebuild with no new migrations.
- Grants under Helm. The access-control docs say Helm users declare grants on the agent’s
virtual_key_ids.
Two things remain on the agent’s side by design. Correlated model and tool logs appear only if the agent sends the two headers, and caller attribution survives only if the agent reuses the forwarded credential.
What the release means
The release is one of the clearer signs so far that the gateway category is following the protocol stack upward. Gateways took on model traffic first, MCP tool traffic second, and are now taking agent-to-agent traffic as A2A settles under the Linux Foundation at version 1.0. The hard part is not forwarding JSON-RPC but the edges A2A creates for an intermediary: cards rewritten without breaking discovery, signatures that rewriting invalidates, push callbacks that are SSRF by construction, and credentials that can travel further than intended. The documentation addresses each, and the v2.3.1 follow-up, which moved public URLs off the Host header and bound credentials to approved origins, shows the security model still being tightened in the first week. The larger question for the category is whether operators will want one policy plane across model, tool and agent calls, with the same key, budget and log tying them together. That is the bet this release makes, and the separation it keeps between agent grants and model or tool grants is the detail that makes the bet workable.
Sources
- Bifrost v2.3.0 changelog: Agent Gateway (A2A) (2026-10-13)
- Bifrost v2.3.1 changelog: Agent Gateway Destination Permissions (2026-10-19)
- Bifrost Enterprise v2.3.0 changelog: Agent Access Grants
- Introducing Agent Gateway in Bifrost: One gateway for models, tools and agents (Dhwanil Pithva, Bifrost blog, October 20, 2026)
- Bifrost docs: Agent Gateway overview
- Bifrost docs: Register your first agent
- Bifrost docs: Gateway settings and transports
- Bifrost docs: Transport selection and recovery
- Bifrost docs: Agent access
- Bifrost docs: Agent Gateway authentication
- Bifrost docs: Push notifications
- Bifrost docs: Connect model and tool calls
- Bifrost docs: Read Agent Logs
- Bifrost docs: Export agent telemetry
- Agent2Agent (A2A) Protocol Specification, version 1.0.0
- A2A specification, section 8.2: Discovery mechanisms
- A2A specification, section 13.2: Push notification security
- A2A specification, Appendix B: Relationship to MCP
- a2aproject/A2A repository (Apache 2.0)
- Linux Foundation launches the Agent2Agent Protocol Project (June 23, 2025)
- Kong docs: AI A2A Proxy plugin
- Microsoft Learn: Import an A2A agent API (Azure API Management)
Questions readers ask
What is the Bifrost Agent Gateway?
It is a feature added in Bifrost v2.3.0, released October 13, 2026, that lets the gateway proxy agents speaking the Agent2Agent (A2A) protocol. An operator registers an agent by its agent card URL, and clients then call the agent at gateway routes under /agents/a2a/<name>/ over JSON-RPC, REST or an optional gRPC listener, with access checks and logging applied on the way.
Does a client have to use the same A2A transport as the agent?
No. According to the Bifrost docs, the client-facing and agent-facing transports are chosen independently, so a REST client can reach an agent that only exposes JSON-RPC. The gateway picks the upstream interface from the order in the agent card's supportedInterfaces list.
Who is allowed to call a registered agent?
Callers whose virtual key holds an agent grant for that registration, or any valid key if the agent has allow_by_default turned on. Ungranted or disabled agents return 403. The docs warn that anonymous requests can still pass unless client.enforce_auth_on_inference is set to true. Enterprise deployments can also grant agents through access profiles and projects.
Does the gateway pass the caller's Bifrost key to the agent?
Not by default. The docs say the caller's Bifrost credential is stripped before the request is forwarded. Forwarding is an opt-in per registration, meant for agents that call back into Bifrost for model and tool requests so those calls stay attributed to the original caller.
What changed in v2.3.1 for the Agent Gateway?
The v2.3.1 changelog, dated October 19, makes agent-card URLs come only from an explicitly configured public URL rather than the request Host header, adds per-agent credential_origins and require_public_target destination policy, tightens the push relay and its token cache, and exports A2A operation bodies and metrics to OpenTelemetry.
