Skip to content
This documentation covers the kagent 1.0 alpha. For the latest 0.x release, see the 0.x docs.

For the complete documentation index, see llms.txt. Markdown versions of all docs pages are available by appending .md to any docs URL.

Identity

Page as Markdown

Understand how kagent resolves a caller’s identity, scopes a Session to its creator, and how Agent Substrate identifies its own components.

A kagent installation identifies three different kinds of caller, and each one is handled by a different system. This page describes what each layer establishes, and what it does not.

  • An operator applying a HarnessHarnessA Kubernetes custom resource defining how an agent is allowed to run: its runtime, workload image, and WorkerPool and snapshot storage. An Agent pairs it with the AgentTemplate it runs.Learn more is authenticated by Kubernetes.
  • A caller creating or talking to a SessionSessionA running conversation with one Agent. Unlike the resources it is built from, a Session is not a Kubernetes resource: kagent's gRPC API creates it and its PostgreSQL database tracks it.Learn more is assigned a principal by kagent’s own gRPC API.
  • The components inside Agent Substrate authenticate each other.

The Kubernetes plane

Harness, AgentTemplate, and AgentAgentA Kubernetes custom resource that pairs one AgentTemplate with one Harness. Each side takes either an inline spec or a reference to an existing resource, and the controller compiles the pair into a revision.Learn more are Kubernetes custom resources. Kubernetes role-based access control (RBAC) therefore governs who can create, read, edit, or delete them with kubectl. A cluster’s existing roles and bindings decide who authors an agent’s runtime, its behavior, and the pairing of the two on that path.

kagent’s gRPC API reaches the same resources by a second path. The AgentTemplate service creates, updates, and deletes AgentTemplates, and the Harness service creates and deletes Harnesses, both through the kagent controller. The kagent apply -f command calls the AgentTemplate service, and any client that reaches the gRPC endpoint can call either service. The controller writes these resources with its own service account rather than the caller’s, so Kubernetes RBAC never evaluates the caller. The kagent control plane authorizes this path instead.

Warning

By default, kagent neither authenticates nor authorizes this path. The insecure authenticator admits every request, and the authorizer it installs permits every check. Any caller that reaches the gRPC endpoint can author an agent’s runtime and behavior, whatever their Kubernetes permissions are. Do not expose port 8083 outside the cluster. For the identity that this mode gives an anonymous caller, and for the mode that changes it, see The kagent control plane.

Because neither a Harness nor an AgentTemplate names the other, the Agent resource carries the pairing, and RBAC on Agents governs it. Whoever can write Agents in a namespace controls which template runs on which Harness, even without edit access to the Harnesses and AgentTemplates that those Agents name. For more information about the pairing, see the Agent core concept.

The kagent control plane

A Session is not a Kubernetes resource. kagent’s gRPC API creates the Session, and kagent’s database tracks it. Kubernetes RBAC therefore does not reach it. kagent resolves a principal for these calls itself.

Every call on the Session API carries a principal. An authenticator resolves one before the request reaches the service, and a call that the authenticator declines is rejected as unauthenticated before any other check runs.

Controller authentication modes

The controller.auth.mode Helm value selects which authenticator the controller installs. The chart defaults to insecure, and enabling the bundled oauth2-proxy does not change it, because browser sign-in and controller authentication are separate boundaries. To authenticate both, enable oauth2-proxy and set controller.auth.mode to trusted-proxy.

ModeHow a principal is resolved
insecureEvery request is admitted. The caller’s identity is read from the X-User-Id header, or from a user_id query parameter that takes precedence over it. A caller that supplies neither is named admin@kagent.dev.
trusted-proxyThe request must carry a bearer token in the Authorization header. The identity comes from the claim that controller.auth.userIdClaim names, defaulting to sub. A missing custom claim falls back to sub, and a request with no identity is rejected.

Any other value fails controller startup rather than falling back to a default.

Warning

trusted-proxy decodes the token without verifying it. The authenticator reads the bearer token’s payload and checks neither its signature nor its expiry, because it assumes that an upstream boundary already validated the credential. A caller that reaches the controller directly can therefore present a token that it wrote itself. This mode is safe only where ingress validates every token before forwarding it, and network policy stops anything else from reaching port 8083.

Warning

insecure lets a caller select its own principal. It verifies neither the header nor the query parameter, and the same authenticator guards the controller’s /mcp endpoint. Treat the principal on a call as a label that the caller chose, and restrict network access to both endpoints rather than relying on it.

Authorization is separate from both modes. kagent installs an authorizer that permits every check regardless of the authentication mode, so neither mode constrains what an authenticated caller may do.

Creator ownership

kagent records a creator on every Session, taken from the principal on the call that created it. That creator is then part of the database query for every read, so a caller who asks for a Session that another principal created receives a not-found response rather than a permission error.

Listing behaves the same way. A list returns the caller’s own Sessions by default. A caller that sets the request’s all-creators flag asks to widen that to every creator in the namespace, and kagent authorizes that request separately from an ordinary list.

Important

Creator ownership separates callers without containing them. kagent calls an authorizer before every Session operation, and the authorizer it installs permits every check, so any caller can widen a list. In insecure mode a caller also names its own principal, so a caller that presents another creator’s identifier reads that creator’s Sessions. Creator scoping keeps one user’s conversations out of another user’s list. It is not a security boundary.

Shares

A share lets a Session’s owner give another account access to that one conversation. Creating a share produces a token, and a caller presenting that token reaches the shared Session without becoming its creator.

A share carries one of two permissions.

  • READ_ONLY: The holder can read the conversation. kagent refuses any call that is not a read before the request reaches the service.
  • READ_WRITE: The holder can also send messages to the Session.

A share widens what the holder can reach to what the owner can see, and the underlying record is read as the owner rather than as the visitor. Revoking the share withdraws that access.

The Agent Substrate plane

Agent SubstrateAgent SubstrateThe runtime that kagent runs agents on. It multiplexes many sandboxed Actors onto a smaller pool of pre-started Workers, suspending idle ones to snapshots.Learn more authenticates its own components rather than authenticating end users. Its API server accepts Kubernetes ServiceAccount tokens issued for its audience, and the components that carry traffic to an Actor authenticate each other with mutual Transport Layer Security (mTLS). The kagent installation guide covers creating the certificate authority pools and the JSON Web Token (JWT) authority pool that these identities are issued from, which is a required step that no Helm chart performs.

Each Actor also carries an identity of its own, addressed as its atespaceAtespaceThe isolation boundary that an Actor belongs to, and the first half of its identity. Global-scoped in Agent Substrate, not a Kubernetes namespace.Learn more and name together. Sandboxing covers how the router uses that identity to reach the right Worker over mTLS.

Important

Agent Substrate authenticates callers but does not authorize them. Any provider that you configure as an authenticated caller can reach every remote procedure call, including destructive ones, so configure only providers whose users require full access to Agent Substrate.