The fastest way to ship an AI feature is to hand it a service account with broad access. Everything works immediately. Every retrieval succeeds, every tool call goes through, nothing fails in the demo.
It also means the assistant can read everything, for everyone, and the audit log shows one identity doing all of it. When somebody asks six months later who authorised a particular change, the honest answer is "the app did".
Three identities are in play, not one
Every AI action carries three separate claims, and collapsing them is where authorisation goes wrong.
The user identity answers on whose behalf the work is being done. The service identity answers which deployment is running. The agent identity answers which workflow and which run, so a specific trace can be pulled back later.
Requests need to carry all three. If the retrieval layer only sees the service identity, it cannot filter documents by what the user is allowed to see, and you have built an expensive way to leak internal files between teams. Permission filtering belongs in the query rather than in a post-hoc instruction asking the model to be discreet.
Scope the verb, not only the data
Read and write are really four settings, and splitting them makes approval proportional to the risk.
| Level | What the agent may do | Gate |
|---|---|---|
| Read | Fetch only what the signed-in user could open themselves | Session auth |
| Suggest | Draft a change in the interface, nothing persisted | Session auth |
| Stage | Write to a pending queue with a visible diff | Policy check |
| Execute | Commit to a system of record | Human approval, logged |
Most workflows never need to leave the first three. The ones that do should say so explicitly in configuration, because "this workflow can execute" is a decision worth someone's name against it.
Deciding policy and enforcing it are different jobs
Keep the decision point separate from the enforcement point. Policy gets evaluated in one place, against a request that names the user, the resource, the action and the context. Enforcement happens at the tool boundary, in code, before the call goes out. The model is never the enforcement point, because anything a model can be talked out of is a preference rather than a control.
Two useful things fall out of that split. Audit logs become meaningful, since every allow and deny records who asked, what was requested, which rule fired and whether a human approved. And exceptions become manageable: a break-glass path with a stated reason, an expiry and a review, instead of a permanent widening of scope that nobody remembers granting.
An agent with standing privileges of its own is a second staff account that never sleeps and never gets offboarded.
More on these topics
Checklist · · 29 checks
Security review checklist for an AI feature
What to check before an assistant, RAG app or agent goes in front of real users. Grouped by area, ticked off locally; progress stays in your browser.
Deep dive · · 5 min read
One MCP server is an integration. Thirty is why you need a gateway
Notes from building an MCP gateway. The protocol standardised how agents call tools, then stayed silent about credentials, context budgets and who may call what. That silence gets expensive as the servers multiply.
Explainer · · 2 min read
Your tool registry is an access control list wearing a different name
A list of tools is documentation. A registry decides who may act, as whom, and leaves proof behind.
Discussion