authorize() before acting, and every decision lands in the audit trail. Everything else is detail on top of that loop.
User vs agent
A user is a human. They have email, password, sessions, OAuth accounts. theAuth can run human auth for you (see Authentication) or plug into Clerk, Auth.js, better-auth. An agent is a program acting on a user’s behalf. One human can own many agents. Agents do not sign in. They authenticate with a bearer token (kv_...) that is issued once and hashed at rest. No password, no session, no OAuth.
If you reach for password reset, email verification, or social sign-in on an agent, you want a user, not an agent. Agents are non-interactive by design.
Permission model
Permissions are strings that describe what the agent may do, scoped to resources it may touch.kind:namespace:id), the action list (read, write, execute, domain-specific verbs), and constraints (rate, approval, IP, time, argument patterns). authorize() evaluates all three. allowedArgPatterns are regular expressions, and every string argument must match every pattern.
Delegation
An agent can hand a subset of its permissions to a sub-agent. Every hop carries a depth counter, an expiry, and can be revoked independently. Revoking a delegation cascades: every delegation made onward from that link is revoked too, so those agents lose the delegated permissions the next time they callauthorize().
authorize() call. maxDepth limits chain length: the new link’s depth must be less than or equal to it (default 3).
Audit trail
Whenagents.auditAll is on (the default), every authorize() and authorizeByToken() call against a known agent writes one row:
The IP address and user agent are stored too, when the request carried them. Nothing in the API edits entries;
theauth.audit.cleanup({ retentionDays }) deletes entries older than the retention window. Export as JSON or CSV for compliance.
Agent types
autonomous
autonomous
Acts on its own. No human approval unless a permission constraint says so. Background jobs, cron, assistants that run unattended.
delegated
delegated
Gets permissions from a parent agent via delegation. Use for ephemeral sub-agents created to finish one task, then discarded.
service
service
Long-lived infrastructure identity. MCP servers, internal microservices, anything service-account-shaped.
Trust scoring
Every agent can have a score from 0 to 100, computed from its audit log when you calltheauth.trust.computeScore(agentId) (it is not recomputed on each authorize() call). The score starts at 50 and moves with successful calls (up), denials (down), flagged denials (down more), and agent age (up).
The score maps to a level: untrusted (below 40), limited (40-59), standard (60-79), trusted (80-94), elevated (95+).
See Trust scoring for the full formula and Policy templates for policies you can pair with the level.
MCP OAuth
theAuth ships an OAuth 2.1 authorization server for Model Context Protocol tool servers. Your MCP servers register as OAuth clients, and they get scoped JWT access tokens. The OAuth server comes fromcreateMcpModule in @glinr/theauth/mcp; token validation is separate from agent authorize() and does not write audit entries.
Three relevant standards: PKCE S256 (RFC 7636), Protected Resource Metadata (RFC 9728), Dynamic Client Registration (RFC 7591). Full details in MCP OAuth 2.1.
What to read next
Quickstart
Five minutes to a working agent.
Add to an existing app
Drop theAuth next to Clerk, Auth.js, or better-auth.
Permissions
Resource strings, constraints, approval gates.
Delegation
Chains, depth limits, revocation.