A2A · kagent · agentgateway

Authenticating agent-to-agent traffic in kagent

A2A auth is not first-class in kagent itself — the built-in HTTP server only forwards headers, it does not validate them. Authentication is delegated to the layer in front of the agent's A2A port. Here are the three shapes that actually work.

TL;DR

For internal platform agents, use Istio mTLS + AuthorizationPolicy. For agents called by users or external systems, put agentgateway in front of the A2A service with a jwtAuth policy. kagent's own A2A handler does not verify tokens — your verifier must be upstream.

What kagent gives you natively

go/core/internal/httpserver/auth/authn.go currently ships an UnsecureAuthenticator. It reads X-User-Id and the Authorization header and forwards them to the downstream agent. It does not validate the JWT, the user ID, or anything else.

That means out-of-the-box A2A traffic into a kagent agent is unauthenticated. Anything that can reach the agent's Service IP can call message/send and message/stream. You bring your own identity verifier — and the agent runtime is fine with that, because the headers reach the downstream code as advisory identity.

Design intent
kagent is deliberately auth-agnostic so the same agent runs behind a service mesh, behind agentgateway, behind oauth2-proxy, or behind nothing. The authentication boundary is configurable — and is your responsibility.

What agentgateway gives you

The upstream agentgateway repo at examples/a2a/ proxies A2A with a single policy that marks the route as A2A and handles agent-card URL rewriting:

policies:
  a2a: {}
backends:
  - host: localhost:9999

That policy alone does not authenticate. It stacks with the generic route policies — which is where the auth lives:

PolicyWhat it doesFit for A2A
jwtAuth Validate JWT on each call — issuer, audience, JWKS URL, claim requirements. Primary
mcpAuthentication Built for MCP, but is JWT validation underneath (issuer / JWKS / audience / mode: strict|optional|permissive). Works on A2A routes too. Compatible
oidc Full OIDC authorization-code flow with session cookies. Overkill for service-to-service; useful when a browser-UI agent is on the path. UI only
extAuthz Delegate to an external authorizer (OPA, custom service). Slower; use when authz logic is too rich for CEL. Optional
cors Required if a browser-side A2A client calls the gateway directly. Browser only

JWT validation supports Auth0, Keycloak, generic OIDC, or a static JWKS file/URL. See schema/config.md:160-180 and examples/mcp-authentication/ in the upstream agentgateway tree for the full surface.

The shape, visually

Caller agent user-or-workload Authorization: Bearer … A2A message/send agentgateway enforcement point policies: a2a: {} jwtAuth: issuer: … jwksUrl: … audience: … accessLog: ✓ verified + identity headers kagent Agent A2A :8080 UnsecureAuthenticator (forwards headers) IdP / JWKS (Auth0, Keycloak, …)

The caller agent attaches a bearer token. agentgateway validates it against the IdP's JWKS, then forwards the request — usually re-attaching identity claims as headers that the downstream agent can read. kagent's internal handler accepts those headers as advisory; the enforcement already happened upstream.

Three practical patterns

1

agentgateway as A2A ingress

Front each agent's A2A Service with agentgateway. Stack a2a: {} + jwtAuth. Caller sends Authorization: Bearer <JWT>; gateway validates and propagates. Agent-card URL rewrite handled for free — callers can't bypass.

Best for: user-facing or external A2A Cost: per-route gateway policy Identity: end-user + workload
2

Istio RequestAuthentication + AuthorizationPolicy

Use the mesh you already have. RequestAuthentication validates the JWT; AuthorizationPolicy scopes which workload identities (SPIFFE IDs) can call which agent. No agent-side code change. You already have an example at platform/agentgateway/istio-authorization-policy.yaml.

Best for: mixed in-cluster + user JWT Cost: needs Istio Identity: workload + end-user
3

Service-mesh mTLS only

For fully in-cluster A2A graphs where workload identity is enough. PeerAuthentication: STRICT + AuthorizationPolicy keyed on source.principal. No JWT plumbing, no token rotation, no IdP dependency for the data path.

Best for: internal platform agents Cost: cheapest Identity: workload only

Pick your pattern

Question Pattern 1 (gateway) Pattern 2 (Istio + JWT) Pattern 3 (mTLS only)
End-user identity propagated to the agent? yes yes no
Workload-only identity sufficient? overkill overkill yes
Requires Istio? no yes yes
Per-agent routing / agent-card rewrite? yes no no
External callers across cluster boundary? yes with east-west gateway no
Operational cost medium medium low

What's missing today

Sketch: agentgateway JWT policy for an A2A route

A minimal route policy that pairs a2a: {} with JWT validation. Caller attaches a bearer token; gateway verifies issuer, audience, and JWKS before letting the request reach the kagent agent's A2A port.

binds:
  - port: 3000
    listeners:
      - routes:
          - policies:
              a2a: {}
              jwtAuth:
                issuer: https://idp.example.com/realms/platform
                jwksUrl: https://idp.example.com/realms/platform/protocol/openid-connect/certs
                audiences:
                  - platform-knowledge-agent
                mode: strict
            backends:
              - host: platform-knowledge-agent.kagent.svc.cluster.local:8080
Note
mode: strict means missing or invalid tokens get 401. Use optional only while migrating callers from anonymous to authenticated; never in production for sensitive agents.

Recommendation

Internal

Pattern 3 — mTLS + AuthorizationPolicy

For platform-internal agents that only talk to other in-cluster agents, this is the cheapest credible answer. No JWTs to rotate, no IdP on the data path, identity is the workload's SPIFFE ID. Pair with NetworkPolicy to deny everything not on the mesh.

User-facing

Pattern 1 — agentgateway + jwtAuth

For agents reached by users, by external systems, or across trust boundaries, put agentgateway in front of the A2A Service and verify a JWT from your IdP. Agent-card rewrite, A2A-aware logging, and per-route policy all land in the same layer.

A useful next deliverable: a concrete a2a-auth-discovery-demo.yaml sibling to the existing mcp-tool-auth-discovery-demo.yaml, showing the catalog → grant → gateway policy projection specifically for agent-to-agent calls. That closes the documented gap.