What Are User-Scoped Agents and Why Do They Matter for Multi-Tenant AI?
Updated
A user-scoped agent runs every request under the identity, permissions, and data boundaries of the person who made it, instead of a shared service account. This matters whenever more than one user touches the same agent: if the agent authenticates as itself rather than as the caller, it can read and act on data the caller was never allowed to see. Vanna 2.0 frames this as "user-scoped execution" and pairs it with access control, agent memory, and audit logs, which are the three places user scoping actually gets enforced.
The core problem: shared-credential agents
Most early agent demos connect to a database or API with one set of credentials baked into the environment. That works for a single-user prototype and breaks the moment you ship to a team or a customer base.
When the agent runs as a shared service account:
- Data leaks across users. A query the agent generates for User A can return rows that belong to User B, because the database only knows the service account, not the caller.
- Access is over-broad. The service account usually has more permissions than any individual user, so the agent can read tables or run writes no single user should trigger.
- Actions are unauditable. Logs show the agent's identity, not the human behind the request. You cannot answer "who asked for this?" after the fact.
User scoping fixes all three by making the caller's identity the thing the agent executes as.
How user scoping connects to access control, memory, and audit logs
User scoping is not a single feature; it is a property that has to hold in three layers.
| Layer | What it controls | What breaks without scoping |
|---|---|---|
| Access control | Which tables, rows, and columns a request can touch | Users see each other's data |
| Agent memory | What the agent remembers between turns | One user's conversation history bleeds into another's |
| Audit logs | Who did what, when | No attribution, no compliance trail |
Vanna's hosted admin features list these directly: Access Control ("control who sees what"), Agent Memory (a hosted vector database for learning), and Audit Logs (activity tracking and compliance). The point of listing them together is that scoping only works if all three respect the same user boundary. An agent with row-level access control but shared memory will still leak information through remembered context.
Practical steps to scope an agent to a user
The exact API depends on your framework, but the sequence is consistent.
- Pass identity into the agent at request time. The agent should receive the caller's identity (a user ID, a token, or a session) as part of the request, not read it from a global config. In Vanna's SQL Agent, access control is a first-class property of the agent, so the identity you pass determines what the generated SQL is allowed to reach.
- Enforce permissions at the data layer, not just the prompt. Row-level and table-level filters belong in the query path or the database itself. A prompt instruction like "only show this user's rows" is not enforcement.
- Isolate memory per user. If the agent stores conversation history or learned context in a vector database, partition it by user ID. Vanna's hosted Agent Memory is described as a hosted vector DB for learning, which is exactly the component that needs per-user isolation in a multi-tenant deployment.
- Log the acting user on every action. Audit logs should record the human identity alongside the agent action, so you can reconstruct who triggered what.
- Verify with a second account. The cheapest test: run the same request as two different users and confirm the results differ in the way permissions predict. If they match, scoping is not working.
Vanna works with any LLM provider and database (Anthropic, OpenAI, Gemini, Ollama; SQLite, PostgreSQL, MySQL, Snowflake, BigQuery, and others), so the scoping logic lives in your agent configuration and data layer rather than being tied to one vendor.
Common failure modes and how to detect them
- Credential reuse. The agent connects with one shared key. Detect it by checking whether your connection string or client is created once at startup versus per request.
- Missing tenant filters. The agent generates correct-looking SQL with no
WHERE user_id = ...clause. Detect it by logging generated queries and grepping for the filter. - Leaked conversation history. Memory is stored in one namespace. Detect it by asking the same follow-up question as two users and seeing whether the second user's answer references the first user's context.
- Audit gaps. Logs show the agent but not the user. Detect it by trying to trace a single action back to a person; if you cannot, the log is incomplete.
Each of these is a scoping failure at a different layer, which is why the fix is architectural rather than a single setting.
When user scoping is worth the work
If your agent serves exactly one user or runs entirely on data everyone is allowed to see, shared credentials are simpler and fine. The moment you have multiple users with different permissions, or you are shipping an agent to customers, user scoping stops being optional. Vanna's positioning—"build agents your users can actually use," with user-scoped execution and quota management built in—reflects that shift from demo to production, where identity is the first thing you have to get right.