Quickstart
Enable authorization, set a verification key, and make your first authenticated request.
from agno.agent import Agent
from agno.models.openai import OpenAIResponses
from agno.os import AgentOS
agent = Agent(
id="my-agent",
model=OpenAIResponses(id="gpt-5.2"),
)
agent_os = AgentOS(
id="my-agent-os",
agents=[agent],
authorization=True,
)
app = agent_os.get_app()authorization=True enables JWT verification. AgentOS also needs a public key to verify tokens against. Generate one from the control plane and wire it in.
Generate a Verification Key from the Control Plane
Toggle JWT authorization
Enable JWT authorization when connecting a new AgentOS, or later from the OS Settings page.
Copy the public key
Copy the public key for your AgentOS from the modal.
Set the verification key
Set the JWT_VERIFICATION_KEY environment variable to your public key in your .env file or export it directly in your terminal:
export JWT_VERIFICATION_KEY="your-public-key"Or, if you manage keys via a JWKS file, point AgentOS at it instead:
export JWT_JWKS_FILE="/path/to/jwks.json"Set these variables before starting AgentOS, then start or restart the application. If you use a .env file, load it through your launch environment; setting a value in the file alone does not update a running process.
The control plane only issues RS256 keys, which is also the default. See authorization troubleshooting for common setup issues.
Sending Authenticated Requests
Authenticated requests carry a verified caller identity. AgentOS uses it for permissions and attribution. Enable user isolation to scope JWT callers' data to their identities.
Send the JWT in the Authorization: Bearer <token> header:
curl -H "Authorization: Bearer $TOKEN" http://localhost:7777/agentsWhere the token comes from depends on your issuer:
- Control plane: minted by
os.agno.comand copied from the OS Settings page. - Self-hosted: minted by your backend or a third-party IDP. See Self-Hosted for setup.
See JWT Tokens for the claim structure each token must include.
Protected requests without a valid credential return 401 Unauthorized. Insufficient scopes usually return 403 Forbidden; agent, team, and workflow listings can return a filtered or empty list.
Configurable Options
Configure JWT verification using AuthorizationConfig:
from agno.os import AgentOS
from agno.os.config import AuthorizationConfig
agent_os = AgentOS(
id="my-agent-os",
agents=[agent],
authorization=True,
authorization_config=AuthorizationConfig(
verification_keys=["your-jwt-verification-key"],
algorithm="RS256",
),
)Use a JWKS file instead:
authorization_config=AuthorizationConfig(
jwks_file="/path/to/jwks.json",
algorithm="RS256",
)Environment Variables
| Variable | Purpose |
|---|---|
JWT_VERIFICATION_KEY | Single public key or shared secret. Added to verification_keys. |
JWT_JWKS_FILE | Path to a static JWKS file. |
Env vars work alongside AuthorizationConfig. Pass keys in code, env vars, or both.
Excluded Routes
These routes bypass central authentication by default:
/, /health, /info, /docs, /redoc, /openapi.json, /docs/oauth2-redirect
AgentOS also excludes the configured prefixes of self-authenticating Slack, Telegram, and WhatsApp interfaces, MCP OAuth provider routes when mcp_auth is set, and the enabled MCP Server Card. A2A and AG-UI stay behind central authentication.
AuthorizationConfig.excluded_route_paths adds fnmatch patterns to these exclusions. Matching requests bypass authentication, not just permission checks. When installing JWTMiddleware manually, its excluded_route_paths replaces its defaults; preserve the required public and MCP provider paths yourself.
Error Responses
| Status Code | Description |
|---|---|
401 Unauthorized | Missing or invalid JWT token |
403 Forbidden | Insufficient scopes for the requested operation |
Next Steps
| Task | Guide |
|---|---|
| Understand JWT claim structure | Tokens |
| Issue tokens from your own backend | Self-Hosted |
| See the full scope reference | Scopes |
| Assign roles to users | Roles |