AI Agents — first-class identity, audit, and revocation
Story 23.4 ships the Agents feature surface: AI agents are no longer
generic OAuth clients with a clientType='agent' discriminator buried in
the OAuth-clients UI — they get their own dashboard navigation entry, their
own activity timeline, their own rate-limit + token-TTL ceilings, and a
first-class per-user revocation primitive aligned with GDPR Art. 7(3)
consent withdrawal.
What you get
Section titled “What you get”| Surface | Where | Purpose |
|---|---|---|
Dashboard /app/{slug}/agents | Tenant owners | Register, list, observe, revoke agents |
/v1/auth/dashboard/tenants/{slug}/agents/** | Dashboard API | Programmatic admin (session auth) |
/v1/users/me/agents (GET / DELETE) | End users | List + revoke agents acting on my behalf |
client.users.me.agents.{list,revoke} | Node SDK | End-user revocation from your apps |
agent.* audit + webhook events | Tenant subscribers | Operational + compliance evidence |
When to register an agent vs. a regular OAuth client
Section titled “When to register an agent vs. a regular OAuth client”Register an agent when:
- The client acts on behalf of a specific user (the
actclaim identifies the agent;subidentifies the human). - You want per-user revocation to satisfy GDPR Art. 7(3) consent withdrawal without rotating the agent’s secret.
- The fleet of clients needs uniform rate limits, alerts, and an audit trail that survives admin handovers.
Register a regular OAuth client when:
- The client is a first-party app signing in human users via
authorization code (no
actclaim, no agent semantics). - You only need machine-to-machine access (
client_credentials) without any user delegation.
Three flows that issue agent tokens
Section titled “Three flows that issue agent tokens”Agents typically combine some of these grant types — the agent registration allowlists them all:
- RFC 8693 Token Exchange (Story 23.2) — the agent already holds a user’s access token and exchanges it for a scoped-down agent token. Inline and synchronous; no user prompt at exchange time.
- OIDC CIBA (Story 23.3) — the agent initiates a request; the user approves out-of-band on a separate device; the agent polls until issuance.
- RFC 8628 Device Authorization (Story 23.1) — CLI / IoT-style agents print a code and URL; the user signs in on a browser.
Every issued token carries an act claim identifying the agent client.
The Node SDK’s verifyToken() exposes this as payload.act and
Auth.isAgentToken(token) returns true for any agent-issued token.
Register an agent
Section titled “Register an agent”From the dashboard: Agents → Register agent. Enter:
- Name — human-readable label.
- Description (optional) — what the agent does.
- Class (optional) — free-form label (e.g.
mcp-server,voice,llm); surfaced in audit views. - Allowed scopes — space-separated list. Tokens issued for this agent are intersected against this allowlist.
- Grant types — check at least one of: token-exchange, CIBA, device-code, client-credentials.
- Max token TTL (seconds) — 60–900s ceiling. Lower = smaller blast radius if a token leaks. Default 300s.
The dashboard reveals the client_secret exactly once at the end of the
wizard — copy it to your secret store immediately.
Revoke an agent
Section titled “Revoke an agent”Tenant admin revoke (DELETE /v1/auth/dashboard/tenants/{slug}/agents/{agentId}):
- Sets
revoked_aton the agent row. - Inserts an
agent_token_denylistrow valid for the agent’s max TTL. - Bearer-auth middleware rejects every subsequent token whose
act.submatches the agent (immediate, not eventual). - Idempotent — re-revoking returns 200 with the existing
revoked_at.
End-user revoke (DELETE /v1/users/me/agents/{agentClientId}, GDPR Art. 7(3)):
- Inserts a
user_agent_revocationsrow keyed(tenant_id, user_id, agent_client_id). - Token-issuance gates in token-exchange + CIBA reject any future mint where
(act.sub, sub)matches a revocation row. - Already-issued tokens remain valid until their TTL expires (≤900s ceiling bounds the residual window). Tenants requiring instant per-token invalidation use the admin revoke path above.
- Idempotent — re-revoking returns 200 with the existing row, no duplicate audit / webhook events.
Activity timeline
Section titled “Activity timeline”Every agent action is recorded in agent_actions with: action type, actor
user, resource, JTI, scope, IP / user-agent SHA-256 prefixes (12 chars
surfaced; raw hashes never leave the server). The dashboard renders a
paginated timeline at Agents → {agent} → Activity; the API exposes it
via GET /v1/auth/dashboard/tenants/{slug}/agents/{agentId}/activity.
Retention: 180 days (operational feed). Critical events (issuance,
revocation, blocked-on-revocation) are dual-written to audit_log
(immutable archive, 3-year retention) for compliance.
Audit + webhook events
Section titled “Audit + webhook events”Eight audit event types fire on the agent lifecycle:
| Event | When | Severity |
|---|---|---|
agent.created | New agent registered | low |
agent.updated | Settings / scopes / grants changed | low |
agent.secret_rotated | Secret rotation | medium |
agent.revoked | Tenant admin revoke | high |
agent.user_revoked | End-user revoke | medium |
agent.rate_limited | Rate limit hit | medium |
agent.concurrent_token_limit_reached | max_concurrent_tokens cap hit | medium |
agent.token_blocked_user_revoked | Token mint blocked by per-user gate | high |
Four webhook event types are emitted to tenant subscribers:
agent.created, agent.revoked, agent.user_revoked,
agent.alert_triggered. Subscribe via the existing /v1/auth/dashboard/tenants/{slug}/webhooks family.
Tier requirement
Section titled “Tier requirement”Agents are a Pro+ feature. Free-tier tenants see a tier-locked CTA and cannot register agents. Pricing details: see your billing dashboard.