Skip to main content
Securing an agent isn’t one thing. It’s layers: auth at the edge to keep strangers out, RBAC to scope what each caller can run, request isolation so users can’t see each other’s data, schema enforcement so even a misbehaving agent can’t write where it shouldn’t, sandboxes for tools that touch the outside world, and human approval for actions that should never run unsupervised. AgentOS gives you defaults at every layer. The rest of this page covers each one and where you’d want to override the default. Network-layer controls (rate limiting, WAF, IP allowlists, mTLS) live at your reverse proxy or API gateway, not here.

Authentication

A production AgentOS sits behind JWT-validating middleware. Every request carries a token signed by the control plane; your service verifies it with a public key.
When authorization=True, every endpoint except /health and /openapi.json requires a valid JWT.

Setup flow

  1. Deploy AgentOS with authorization=True and JWT_VERIFICATION_KEY set. The app crash-loops until the key is valid. That’s expected.
  2. Open os.agno.comAdd OSLive → paste your URL.
  3. Go to SettingsGenerate key pair.
  4. Copy the public key. Paste into your env (JWT_VERIFICATION_KEY).
  5. Redeploy.
The control plane keeps the private key. Your service only ever sees the public key. JWTs are signed by the control plane and verified by your service. This is the flow Dash and Coda walk through end-to-end.

Custom JWT configuration

If you’re issuing JWTs from your own auth provider, pass an AuthorizationConfig:
verification_keys is a list, so you can rotate keys without downtime. Old tokens validate against the old key, new tokens against the new one. Drop the old key once tokens have aged out.

Authorization (RBAC scopes)

Every JWT carries a scopes claim. Endpoints are gated on scopes. A typical end-user gets agents:my-agent:run. An internal service gets agent_os:admin. The control plane mints both with appropriate scopes. See RBAC for the full setup.

Request isolation

Every request runs in its own context. State doesn’t bleed between users, agents, or sessions. This is the baseline for multi-tenant deployments. Combined with agent_os:admin for service-level callers, it gives you per-user data isolation without a separate per-tenant runtime.

Schema enforcement

For agents that touch databases, API-level auth isn’t enough. A model can decide to write DROP TABLE users regardless of what its instructions say. Stop it at the engine, not the prompt.
  • Read-only roles. PostgreSQL connections opened with default_transaction_read_only=on reject any write attempt no matter what SQL the model generates. This is what Dash uses on the Analyst agent.
  • Schema-scoped writes. A SQLAlchemy event listener that blocks DDL/DML targeting forbidden schemas. Dash uses this on the Engineer agent: writes go to the dash schema, never public.
These are infrastructure guardrails, not prompt instructions. They hold even if the model goes off-script.

Tool sandboxing

Most tools are pure functions. The ones that aren’t (HTTP calls, shell commands, code execution, file I/O) need their own guardrails. Coda uses a git worktree sandbox for code-writing tools. The Coder agent can write anything it likes, but only inside an isolated worktree. Main is never touched.

Human approval

The last layer. Some actions should never run unsupervised — refunds, deletes, prod deploys, anything irreversible. AgentOS pauses the run, surfaces the pending approval, resumes when a human signs off. Two patterns: requires_confirmation for the user asking the agent, @approval for a designated admin with policy authority. Full details on the Human Approval page.

Defaults

Next

Interfaces →