Keycloak, the open-source identity and access management platform, gives AI agents a solid authentication foundation: realms to segment identity populations, clients to register each agent as its own authenticatable principal, and OAuth 2.0 Token Exchange support for on-behalf-of flows. Per-tool authorization and delegation-chain scoping sit outside what an identity provider does — those have to be built on top, regardless of which OIDC-compliant IdP sits underneath.

What Keycloak provides for agent authentication

A realm in Keycloak is an isolated space of users, clients, and policy — the natural boundary for separating, say, a production agent population from a staging one, or one business unit's agents from another's, without them sharing configuration or credentials.

A client is a registered application or service that can authenticate against the realm. For agents, the client-credentials grant is the relevant flow: an agent registers as a client (or as a service account tied to a client), authenticates with its own credential, and receives an access token scoped by the client's configured roles and scopes — no human user session involved. This is a genuine improvement over agents sharing one integration's API key: each agent client is individually attributable, individually revocable, and individually auditable in Keycloak's own event log.

Keycloak also implements OAuth 2.0 Token Exchange (RFC 8693) as a standard flow, which matters for agent architectures specifically because it is the standard mechanism for on-behalf-of delegation: an agent holding a token can exchange it for a new token that names a different subject or a narrower audience, which is the building block for "orchestrator agent obtains authority, then exchanges for a narrower token before calling a sub-agent or tool." Confirm the support level in the Keycloak version you actually run — this feature's status has changed across releases. The general shape of the pattern, independent of which IdP implements it, is covered in OAuth 2.0 token exchange for agent-to-tool authorization.

Where the client model stops matching agent behavior

Keycloak's client and role model was built around a relatively stable population of applications and services, each with a role set configured by an administrator and changed infrequently. Agent fleets stress that model in a few specific ways:

Static roles vs. dynamic per-task scope. A Keycloak client's roles are configuration, changed through an admin action or a provisioning script — not something that flexes automatically per task. An agent that should hold a narrower scope for a specific low-risk task and a broader one for a different, higher-trust task needs either multiple pre-configured client roles selected at request time, or a policy layer in front of Keycloak deciding which scope to request per call. Keycloak issues tokens with the scopes it's configured to issue; deciding, at request time, which scope this specific task actually warrants is a decision for the layer in front of it.

Delegation-depth tracking is a layer you add. Token exchange lets an agent obtain a token for a different subject or narrower audience, but tracking "this is hop three of a delegation chain that started with user X's request, and hop four should be narrower still, or should be refused entirely" is logic you write around the exchange calls, not something the exchange mechanism itself expresses. Bounding delegation depth and ensuring each hop narrows rather than merely forwards is the pattern examined in scoped tokens for sub-agent delegation.

Tool-call granularity is finer than OAuth scopes usually go. Scopes in an OAuth/OIDC deployment are typically defined at the API or resource-server level — "read orders," "write invoices." An agent calling an MCP server needs authorization at the level of the specific tool and often the specific arguments — "may call the search tool, may not call the delete tool" on the same server. Modeling that granularity purely as Keycloak scopes is possible but becomes an explosion of narrow, single-purpose scopes to configure and maintain; most teams instead put a policy decision point in front of the MCP server that consults Keycloak for who the caller is, then makes the tool-level call itself. The tool-scoping question is covered independently in scoping MCP tool permissions and MCP server authentication: OAuth vs. API keys.

Continuous, behavioral authorization. Keycloak evaluates authorization at token issuance and, depending on token lifetime, again at each refresh — a point-in-time decision repeated periodically. An agent whose behavior drifts mid-task, under a prompt injection or a reasoning failure, is still holding a validly issued, unexpired token, and reconsidering that token before the next scheduled refresh is outside what a point-in-time issuance model does. Continuous re-evaluation against current behavior is a runtime governance function, not an identity-provider function — see continuous authorization and agent privilege abuse and continuous authorization.

Custom claims are where teams try to force the issue

A common pattern once teams hit the granularity limit is reaching for Keycloak's protocol mappers to stuff agent-specific context — the current task ID, the tool being called, a delegation depth counter — directly into the issued token as custom claims. This works up to a point: a resource server can inspect a custom claim and make a finer-grained decision than a plain scope allows. It breaks down as a long-term pattern for two reasons. First, the token is minted once at issuance (or refresh), so a claim describing "the tool being called" is frozen at that moment — useful for the first call the token is used for, stale for the fifth call made before the token's lifetime is up, unless you re-issue a token per call, which defeats much of the point of having a token at all. Second, every custom claim your resource servers depend on becomes implicit coupling between your IdP configuration and your authorization logic, spread across protocol mappers that are easy to lose track of as the agent population grows. Custom claims are a reasonable tactical bridge; they are not a substitute for a policy layer that evaluates the current request against current context at the point of the tool call itself, rather than baking a snapshot of that context into the token beforehand.

The layered build

Layer What Keycloak provides What you still build
Agent authentication Client credentials grant, per-agent client identity Provisioning workflow to register new agents as clients with an owner and purpose
On-behalf-of authority RFC 8693 token exchange support Delegation-depth limits and scope-narrowing logic at each exchange
Tool-level authorization Coarse OAuth scopes Per-tool, per-argument policy decisions in front of MCP servers or tool APIs
Continuous behavioral policy Token lifetime and refresh cadence Runtime evaluation of current action against current task and trust signals
Audit Realm event log of authentication and token events Application-level audit tying agent, principal, tool, and outcome together per call

What good looks like

  1. Every agent registers as its own Keycloak client (or dedicated service account), never sharing a client with other agents, so authentication events are individually attributable.
  2. Token exchange is used for every hop of agent-to-agent delegation, with each exchanged token's scope narrower than or equal to the token it was exchanged from — never broader.
  3. Tool-level authorization for MCP servers and sensitive APIs is evaluated by a policy layer that consults Keycloak for caller identity but makes the per-tool decision itself.
  4. Client roles and scopes are reviewed on the same cadence as the rest of the NHI population, per NHI credential lifecycle management, rather than left as whatever was configured at initial rollout.
  5. An application-level audit trail exists alongside Keycloak's own event log, recording the tool, task, and principal for every governed action.

Common questions

Should every AI agent get its own Keycloak client, or share one client with multiple service accounts? Give each agent its own client or dedicated service account wherever your agent count makes that operationally manageable. Sharing a client across agents collapses Keycloak's own audit trail into one undifferentiated identity, the same attribution loss covered in why agents need their own credentials.

Does Keycloak's token exchange support solve agent delegation on its own? It provides the mechanism — the ability to exchange a token for one naming a different subject or narrower audience — but not the policy: how many hops are allowed, how much narrower each hop must be, and what happens when a delegation request looks anomalous are decisions your application layer has to make around each exchange call.

Is a self-hosted IdP like Keycloak a reasonable choice for agent identity versus a managed IdP? Both are reasonable technical foundations; the choice usually comes down to operational ownership. A self-hosted deployment gives full control over realms, extensions, and token exchange configuration at the cost of running and patching the IdP yourself, similar to the trade-offs described generally in SSO, SAML, and OIDC for AI agent management. Either way, the agent-specific gaps above — delegation scoping, tool-level authorization, continuous evaluation — need a layer above the IdP regardless of which one you run.