A verified end user is part of the request, and an agent is in the path. Two authority shapes apply per call — agent-as-principal (the agent’s grant signs the call) or delegation (the user’s grant signs the call, via the agent). Identity is the same handle either way; only the authority changes.Documentation Index
Fetch the complete documentation index at: https://docs.alterauth.com/llms.txt
Use this file to discover all available pages before exploring further.
Identity verification is an app-level primitive.
app.verify_user_token(...) / app.authenticate(...) runs in application code and is independent of whether an agent is involved on any given call. This page covers the combined shape — an agent and a verified user in the same request, with either authority per call. The adjacent shapes have their own pages:- App + verified user, no agent. JWT identity — user-principal calls with no agent in the path.
- Agent, no verified user.
grant_idresolution — autonomous workloads where the agent runs without per-request user context.
When this applies
| Situation | Pattern |
|---|---|
| Agent + verified user in the request — agent’s grant signs the call | This page (agent-as-principal) |
| Agent + verified user in the request — user’s grant signs the call (agent mediating) | This page (delegation) — see also Delegation for the standalone reference |
| Verified user in the request, no agent in the path | JWT identity |
| Agent in the request, no verified user | grant_id resolution |
Where the verified identity goes
Identity is verified once (via the configured IDP) and produces a stable handle: a verifiedapp_user_id plus JWT claims. That handle then resolves to many destinations:
| Destination | Resolved by | Purpose |
|---|---|---|
| OAuth grant (delegation or JWT identity) | Alter | Credential authority for the call |
| Managed-secret grant (user- or group-principal) | Alter | Credential authority for the call |
| Group memberships | Alter | Group-principal access, policy inputs |
| Wallet view of “my connections” | Alter | User self-service |
| Database row filters | Application code | Scope DB reads to this user |
| Tool inventory filtering | Application code | Gate LLM tool list by JWT role |
| Audit context metadata | Application code | Correlation via context= |
| Tenant isolation gates | Application code | Verify org claim matches |
| Policy attributes referencing the verified user identifier | Alter | Per-call rule branching |
app_user_id is established once and flows into every destination above on every call — that part does not change. What varies per call is which authority signs the request, not who “owns” identity. Two authority shapes:
- User authority — Alter resolves a user-owned credential. The call routes identity into Alter’s credential-resolution path; the user is the principal on the wire. Two sub-shapes: delegation (agent mediating — covered on this page) and JWT identity (no agent).
- Agent authority — no user-credential lookup happens. The agent’s credentials sign the call. Identity is still the same handle and still flows into DB scoping, tool gating, audit context, and tenant gates — it just does not enter Alter’s credential lookup, because no user-credential lookup is performed. This is the agent-as-principal pattern.
NoDelegatedGrantError. JWT verification succeeded; consent resolution found no edge. Verification and authorization stay independent.
Delegation — what it is and isn’t
Delegation = a user has authorized an agent to use the user’s own credentials. Alter supports exactly two flavors today, one per credential type:| Flavor | Backing grant | Established when |
|---|---|---|
| OAuth delegation | A user-owned OAuth grant plus a separate delegation binding from the user to this agent | The user completes Connect with this agent named on the consent screen |
| Managed-secret delegation | A user-principal managed-secret grant (the user binding on the grant itself is the delegation; no separate join table) | An operator (or the user, via the Wallet) provisions the managed-secret grant against the user’s identity |
user_token= on agent.request(...) (or wire a user_token_getter on the constructor) and the backend picks whichever flavor the resolved user + provider pair has.
The call site
The call-site decision is whether to include the user’s JWT on the call. Including it routes through delegation; omitting it routes through agent-as-principal. Same method, same client — the kwarg is what picks the authority.app.verify_user_token(...) or app.authenticate(...) — is supplied per call. Identity verification happens once in middleware; whether the JWT then accompanies a given outbound call is a per-call authority decision.
What application code owns
- Database scoping. Every read against user-owned tables must filter by the verified user’s identifier. A query that returns “all tickets” instead of “tickets for
ctx.end_user_id” leaks across the user boundary; Alter has no signal that would catch it. - Tool gating. Filter the agent’s tool inventory by JWT role (
org_role, etc.) before the LLM sees the list. - Response filtering. When the agent’s grant returns data spanning multiple users (shared KB, multi-participant channel), filter to what the current user is permitted to see.
- Tenant isolation. For multi-tenant IDPs, verify the
orgclaim matches the expected tenant before materializing the user. - Conversation hygiene. Scope cross-turn state by user identifier; discard it on conversation end.
What Alter does
Some of Alter’s work is the same regardless of which authority a given call uses; some of it differs. Always (both authority shapes):- JWT signature, issuer, audience, and expiry validation when
verify_user_tokenis called. - AppUser materialization on successful verification (visible in the Users tab, marked JWT-sourced).
- Audit log entry for the call, attributed to whichever principal signed it.
user_token):
- Grant resolution for the agent’s own grant (from the API key, not the user identity).
- Per-grant policy enforcement on the agent’s grant.
user_token present):
- Identity resolved into a user-owned credential via the user’s grant — either an OAuth grant the agent has been delegated, or a user-principal managed-secret grant. If neither exists for the resolved (user, provider) pair, the SDK raises
NoDelegatedGrantError. - Per-grant policy enforcement on the user’s grant; agent appears as the mediating actor in audit.
Mixed-mode handler
A single inbound message often produces calls in more than one pattern.agent is the module-level Agent(api_key=AGENT_API_KEY) from above; ctx is the per-request context the application’s middleware builds after app.verify_user_token(...); db is the application’s database handle.
ctx) across all three operations. What differs is the authority each call runs under and which destinations the identity flows into: the Discord call uses agent authority and identity does not enter Alter’s credential lookup; the storage call uses no Alter authority and identity flows into DB row filtering; the Linear call uses user-delegated authority and identity flows into both Alter’s credential resolution and Linear’s actor attribution. The patterns coexist because they are orthogonal — authority is per-call, identity is cross-cutting.
Naming the user in audit
Audit events for agent-principal calls are attributed to the agent. To surface the verified user without changing authority, pass identifiers throughcontext=:
context payload is recorded as structured audit metadata and is searchable. It does not change authorization, policy, or grant resolution.
When to switch patterns
- Switch to delegation when the third-party resource is user-owned, the user should appear as the actor in the third-party system, or the user must consent and revoke per-agent independently. The right flavor depends on the credential: OAuth delegation for OAuth providers (Gmail, Linear, Notion, …); managed-secret delegation for user-principal managed secrets (a per-user API key the user provisioned via the Wallet, for instance).
- Drop the user-identity layer and use grant-id resolution when the agent runs autonomously (scheduled jobs, batch enrichment) with no per-request user.
See also
Principals and grants
The taxonomy this page extends.
Identity resolution
The three resolution modes the SDK uses at the call site.
Delegation
The path that lets an agent act as the user.
JWT identity
The user-principal flow without an agent.