Network-layer controls (rate limiting, WAF, IP allowlists, mTLS) live at your reverse proxy or API gateway layer.
Authentication
A production AgentOS sits behind JWT-validating middleware. Tokens can come from the AgentOS control plane, your own backend, or a third-party identity provider. Your service verifies them with the matching public key. See Self-Hosted for BYO and third-party setup.authorization=True drives both layers:
- Authentication (this section): requires a valid JWT on every request.
- Authorization (below): enforces the token’s scopes per endpoint.
/, /health, /info, /docs, /redoc, /openapi.json, /docs/oauth2-redirect.
Generate a Verification Key from the Control Plane
Toggle JWT authorization
Open os.agno.com → Add OS → Live → paste your URL. Enable JWT authorization when connecting a new AgentOS, or later from the OS Settings page.
Configure JWTs from Your Backend or IDP
If you’re issuing JWTs from your own backend, or from a third-party identity provider like WorkOS, Auth0, or Okta, pass anAuthorizationConfig:
verification_keys is a list. AgentOS tries each key in order until one verifies the token, so you can accept tokens from multiple issuers at the same time. For key rotation, use a JWKS file instead.
With verify_audience=True, AgentOS rejects tokens whose aud claim doesn’t match the expected audience. That expected value defaults to the AgentOS id; set audience to override it when your provider mints a different value.
JWT claim names (scopes, sub) are configured on the JWT middleware itself, not on AuthorizationConfig. The defaults (scopes for the scopes claim, sub for the user id claim) match the tokens minted by the control plane.
For the full self-hosted setup including multi-issuer, see Self-Hosted.
Authorization
Every JWT carries a claim listing the caller’s permissions (scopes by default; configurable via scopes_claim if your provider uses a different name, like WorkOS’s permissions). Endpoints are gated on those scopes.
| Scope | Grants |
|---|---|
agents:read | List agents and read their config |
agents:<id>:run | Run a specific agent |
agents:*:run | Run any agent (same pattern for teams, workflows) |
agent_os:admin | Full access including session, memory, and trace queries |
Request isolation
Every request gets a fresh copy of the agent, team, or workflow it’s hitting. AgentOS callsdeep_copy() on the registered component per request, so mutable state (session-scoped variables, tool execution context, run metadata) never bleeds between concurrent calls.
Heavy resources (the DB connection, the model client, MCP tool handles) are shared by reference; only the mutable per-run state is isolated. You get cheap concurrency without the footgun of two requests racing on the same in-memory agent instance.
This is on by default for every run endpoint. There’s nothing to configure.
User isolation
Per-user data isolation is opt-in. Authorization stays in force without it, but routes operate on the unscoped DB. A caller withagents:my-agent:run could read another user’s sessions if they know the IDs. For multi-tenant deployments, turn it on:
user_isolation=True, every non-admin caller gets:
| Guarantee | How |
|---|---|
| No cross-user reads | The JWT sub is threaded as user_id on every user-scoped read (sessions, memory, traces). Callers only see their own rows. |
| No cross-user writes | user_id is coerced on every write, so a non-admin can’t persist a session, memory, or trace attributed to another user. |
| Run ownership | Cancel, resume, and continue routes require session_id and verify the run belongs to the caller’s session. |
| WebSocket reconnect | Reconnecting to a workflow run requires session_id and workflow_id, then verifies the caller owns the run. |
admin_scope, defaulting to agent_os:admin) bypass all of the above and see the full unscoped view: service accounts, internal tooling, the control plane.
Per-user isolation requires a database that records user_id (PostgreSQL recommended for production).
Defaults
| Concern | Default behavior |
|---|---|
| Authentication | authorization=False. Opt in with authorization=True and JWT_VERIFICATION_KEY for production. |
| Request isolation | On. Every run endpoint deep-copies the component. |
| User isolation | Off. Opt in via AuthorizationConfig(user_isolation=True) for multi-tenant. |