> ## Documentation Index
> Fetch the complete documentation index at: https://agno-v2.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Per-User Data Isolation

> Scope user-owned AgentOS data and resources to the caller's user ID.

Authorization controls which operations a caller can perform. Per-user data isolation controls which rows a caller can see and write. User isolation applies throughout AgentOS to user-owned data and resources. Opt in with `user_isolation=True`:

```python theme={null}
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",
        user_isolation=True,
    ),
)
```

When enabled, AgentOS uses the JWT `sub` claim as the `user_id` for every non-admin caller:

| Operation | Behavior with `user_isolation=True` |
| - | - |
| User-owned reads | Scoped to the caller's `user_id`. Other users' rows are not returned. |
| User-owned writes | `user_id` is coerced to the caller's `sub`. A caller cannot persist rows attributed to another user. |
| Cancel / resume / continue routes | Require `session_id` and verify the caller owns the run. |
| WebSocket reconnect | Requires `session_id` (and `workflow_id`) for non-admins. |

A caller holding `admin_scope` (default `agent_os:admin`) bypasses isolation and sees all data. Set a custom override with `admin_scope="ops:admin"`.

> [!NOTE]
>
> Isolation is off by default. JWT and scope checks still apply when `user_isolation=False`, but routes operate on the unscoped database and add no per-user ownership gates on top of authorization. Per-user isolation requires a database that records `user_id` (PostgreSQL recommended for production).

## Service Accounts

[Service account](https://agno-v2.mintlify.site/agent-os/security/authorization/service-accounts.md) principals (`sa:<name>`) are always scoped to themselves, regardless of the `user_isolation` flag. The scoping decision runs in this order:

1. A caller holding the admin scope is never scoped. This is checked first, so an admin service account reads across users.
2. A service account is scoped to its own `sa:<name>` principal, even when `user_isolation=False`.
3. JWT callers are scoped to their `sub` only when `user_isolation=True`.

A machine token stamps its sessions and memories with its own principal, so an unscoped default would read every user's history. If you need a token that reads across users, mint one with the admin scope.

## Next Steps

| Task | Guide |
| - | - |
| Issue tokens with the `sub` claim | [Tokens](https://agno-v2.mintlify.site/agent-os/security/authorization/tokens.md) |
| Mint machine tokens | [Service Accounts](https://agno-v2.mintlify.site/agent-os/security/authorization/service-accounts.md) |
| See the user isolation cookbook example | [user\_isolation.py](https://github.com/agno-agi/agno/blob/main/cookbook/05_agent_os/07_security/user_isolation.py) |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.