From 208837df6fa0c2c1d116e15d754aacf96dedfcd0 Mon Sep 17 00:00:00 2001 From: Abhinav Gupta Date: Fri, 15 May 2026 17:33:32 +0530 Subject: [PATCH 1/2] docs: add agent control auth reference --- core/authentication.mdx | 173 +++++++++++++++++++++++++++++++ core/configuration.mdx | 3 + docs.json | 2 + how-to/enable-authentication.mdx | 2 +- 4 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 core/authentication.mdx diff --git a/core/authentication.mdx b/core/authentication.mdx new file mode 100644 index 0000000..1deeb06 --- /dev/null +++ b/core/authentication.mdx @@ -0,0 +1,173 @@ +--- +title: Authentication +description: Auth modes, HTTP upstream authorization, namespace scoping, and runtime JWT claims. +icon: "shield-check" +--- + +Agent Control keeps authentication and authorization provider-neutral. The server asks a +configured provider whether a request may perform an operation, then scopes all data access with +the returned `Principal`. + +## Operations + +Operations are stable strings. Deployers map them to their own permission model. + +```text +controls.read +controls.create +controls.update +controls.delete +policies.read +policies.create +policies.update +agents.read +agents.create +agents.update +evaluators.read +observability.read +observability.write +control_bindings.read +control_bindings.write +runtime.token_exchange +runtime.use +``` + +## Principal + +Providers return a generic principal. Agent Control treats `namespace_key`, `caller_id`, +`target_type`, and `target_id` as opaque strings. + +```json +{ + "namespace_key": "tenant-a", + "is_admin": false, + "caller_id": "user-or-key-id", + "target_type": "session", + "target_id": "target-123", + "scopes": ["runtime.use"], + "expires_at": "2026-05-11T15:00:00Z" +} +``` + +`namespace_key` is the tenancy boundary. Server queries filter by it, and namespace-aware foreign +keys prevent cross-namespace references. + +## Auth Modes + +Management auth is selected by `AGENT_CONTROL_AUTH_MODE`. + +| Mode | Meaning | +| --- | --- | +| `none` | No credentials required. Intended for local development only. | +| `api_key` | Validate caller credentials locally with `AGENT_CONTROL_API_KEYS` and/or `AGENT_CONTROL_ADMIN_API_KEYS`. Requires `AGENT_CONTROL_API_KEY_ENABLED=true`. `header` is accepted as a backwards-compatible alias. | +| `http_upstream` | POST each management authorization decision to `AGENT_CONTROL_AUTH_UPSTREAM_URL`. | + +When `AGENT_CONTROL_AUTH_MODE` is unset, startup selects `api_key` if local API-key validation is +enabled and `none` otherwise. + +Runtime auth is selected by `AGENT_CONTROL_RUNTIME_AUTH_MODE`. + +| Mode | Meaning | +| --- | --- | +| unset | Use `jwt` when `AGENT_CONTROL_RUNTIME_TOKEN_SECRET` is set. Otherwise runtime requests fall through to management auth. | +| `none` | No runtime credentials required. Intended for local development only. | +| `api_key` | Validate runtime requests with the same local API-key mechanism. | +| `jwt` | Require target-bound runtime tokens minted by `/api/v1/auth/runtime-token-exchange`. | + +Common combinations: + +| Management | Runtime | Use case | +| --- | --- | --- | +| `api_key` | unset | Existing standalone deployments. | +| `api_key` | `jwt` | Local management keys with short-lived target-bound runtime tokens. This does not perform per-target authorization; any valid local API key can exchange for any target in the local namespace. | +| `http_upstream` | `jwt` | External identity or authorization service for management, local token verify for high-volume runtime calls. | +| `none` | `none` | Single-process local development. Do not use in production. | + +## HTTP Upstream Contract + +When `AGENT_CONTROL_AUTH_MODE=http_upstream`, the server sends: + +```text +POST {AGENT_CONTROL_AUTH_UPSTREAM_URL} +``` + +```json +{ + "operation": "control_bindings.write", + "context": { + "target_type": "session", + "target_id": "target-123" + } +} +``` + +The provider forwards inbound `X-API-Key`, `Authorization`, and `Cookie` headers. Add +deployer-specific header names with `AGENT_CONTROL_AUTH_UPSTREAM_EXTRA_FORWARD_HEADERS`, for +example: + +```text +AGENT_CONTROL_AUTH_UPSTREAM_EXTRA_FORWARD_HEADERS=Vendor-API-Key,X-Workspace-Id +``` + +If `AGENT_CONTROL_AUTH_UPSTREAM_SERVICE_TOKEN` is set, it is forwarded on +`AGENT_CONTROL_AUTH_UPSTREAM_SERVICE_TOKEN_HEADER` or `X-Agent-Control-Service-Token` by default. + +A successful upstream response is: + +```json +{ + "namespace_key": "tenant-a", + "is_admin": false, + "caller_id": "user-or-key-id", + "target_type": "session", + "target_id": "target-123", + "scopes": ["runtime.use"], + "expires_at": "2026-05-11T15:00:00Z" +} +``` + +Only `namespace_key` is always required. `target_type` and `target_id` must be returned together +when present. `expires_at` must include timezone information. + +Status handling: + +| Upstream status | Agent Control result | +| --- | --- | +| `200` | Parse the principal grant. | +| `401` | Authentication error. | +| `403` | Forbidden error. | +| `404` | Not found error. | +| `429` | `503` with a rate-limit detail and `Retry-After` hint when present. | +| Other statuses or upstream network errors | Fail closed with `503`. | +| Malformed `200` principal response | Fail closed with `502`. | +| `200` target grant that conflicts with request context | Fail closed with `403`. | + +## Runtime JWT Claims + +`/api/v1/auth/runtime-token-exchange` is a management-style request. The configured management +provider authorizes `runtime.token_exchange` for the requested target. Agent Control then mints +its own HS256 JWT with `AGENT_CONTROL_RUNTIME_TOKEN_SECRET`. + +The token payload contains: + +```json +{ + "iss": "agent-control/server", + "domain": "runtime", + "namespace_key": "tenant-a", + "actor_id": "user-or-key-id", + "target_type": "session", + "target_id": "target-123", + "scopes": ["runtime.use"], + "iat": 1778509800, + "exp": 1778510100, + "jti": "opaque-token-id" +} +``` + +Verification requires the expected issuer, `domain="runtime"`, a valid signature, an unexpired +`exp`, and `runtime.use` in `scopes`. The token is accepted only for requests whose `target_type` +and `target_id` match the bound target. + +The expiry is the earlier of `AGENT_CONTROL_RUNTIME_TOKEN_TTL_SECONDS` and the upstream grant's +`expires_at` when supplied. Runtime token TTLs are capped at 86400 seconds. diff --git a/core/configuration.mdx b/core/configuration.mdx index 3d64381..da49801 100644 --- a/core/configuration.mdx +++ b/core/configuration.mdx @@ -67,6 +67,9 @@ For server database configuration, use the `AGENT_CONTROL_DB_*` variables in the Agent Control supports API key authentication for production deployments. +For pluggable management auth, HTTP upstream authorization, namespace scoping, and runtime JWT +claims, see the [Authentication reference](/core/authentication). + ### Configuration | Variable | Default | Description | diff --git a/docs.json b/docs.json index 41a28f7..650966b 100644 --- a/docs.json +++ b/docs.json @@ -119,6 +119,7 @@ "pages": [ "core/reference", "core/configuration", + "core/authentication", "sdk/python-sdk", "sdk/typescript-sdk", "testing", @@ -183,6 +184,7 @@ "pages": [ "core/reference", "core/configuration", + "core/authentication", "sdk/python-sdk", "sdk/typescript-sdk", "testing" diff --git a/how-to/enable-authentication.mdx b/how-to/enable-authentication.mdx index 4906f11..f58659e 100644 --- a/how-to/enable-authentication.mdx +++ b/how-to/enable-authentication.mdx @@ -106,4 +106,4 @@ Agent Control accepts multiple comma-separated keys per variable, making zero-do 2. Your key is present in the correct variable (`AGENT_CONTROL_API_KEYS` for regular, `AGENT_CONTROL_ADMIN_API_KEYS` for admin operations) 3. The `X-API-Key` header (or SDK `api_key` argument) matches exactly — no trailing whitespace or quotes -See the [Authentication reference](/core/reference#authentication) for the full configuration table. +See the [Authentication reference](/core/authentication) for auth modes and provider contracts. From 56d0c6f16b1b039aa342ef35f7da1d0dcbf73580 Mon Sep 17 00:00:00 2001 From: Abhinav Gupta Date: Fri, 15 May 2026 17:35:24 +0530 Subject: [PATCH 2/2] docs: satisfy auth reference style lint --- core/authentication.mdx | 4 ++-- core/configuration.mdx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/authentication.mdx b/core/authentication.mdx index 1deeb06..9c3372f 100644 --- a/core/authentication.mdx +++ b/core/authentication.mdx @@ -10,7 +10,7 @@ the returned `Principal`. ## Operations -Operations are stable strings. Deployers map them to their own permission model. +Operations are stable strings. Teams map them to their own permission model. ```text controls.read @@ -170,4 +170,4 @@ Verification requires the expected issuer, `domain="runtime"`, a valid signature and `target_id` match the bound target. The expiry is the earlier of `AGENT_CONTROL_RUNTIME_TOKEN_TTL_SECONDS` and the upstream grant's -`expires_at` when supplied. Runtime token TTLs are capped at 86400 seconds. +`expires_at` when supplied. Runtime token lifetimes are capped at 86400 seconds. diff --git a/core/configuration.mdx b/core/configuration.mdx index da49801..4771915 100644 --- a/core/configuration.mdx +++ b/core/configuration.mdx @@ -67,7 +67,7 @@ For server database configuration, use the `AGENT_CONTROL_DB_*` variables in the Agent Control supports API key authentication for production deployments. -For pluggable management auth, HTTP upstream authorization, namespace scoping, and runtime JWT +For provider-based management auth, HTTP upstream authorization, namespace scoping, and runtime JWT claims, see the [Authentication reference](/core/authentication). ### Configuration