- ›
AI agent permissions decide which capabilities an agent can use— and they should be enforced by the platform, not requested in a prompt. - ›A prompt-level 'don't do X' is bypassable; permissions have to live server-side, checked at execution time.
- ›On Naïve, an Account Kit is the policy template: it enables specific primitives and specific third-party apps per tenant user.
- ›You can gate down to individual tools (e.g. allow Gmail read + send only) and require human approval on sensitive actions.
- ›Cards, domains, verification, formation, and connecting apps default to requiring approval; agent calls are gated, human dashboard/session calls are not.
- ›Author a few kits (Starter/Pro/Enterprise) and assign them, instead of configuring every user by hand.
An AI agent that can act in the real world needs a hard answer to one question: what is it allowed to do? Get that wrong and the agent can spend money, connect accounts, or touch data it shouldn't. AI agent permissions are the controls that answer it — and the only version worth trusting is enforced by the platform at execution time, not written into a system prompt the model can be talked out of.
This is the enforcement layer of the multi-tenant playbook, sitting right on top of per-customer isolation. Here's how policy templates make least-privilege the default.
Why not just put the rules in the prompt?
Because a prompt is advisory. "Never issue a card without approval" holds right up until a crafted document, a jailbreak, or a plain model mistake convinces the agent otherwise. You cannot audit a natural-language instruction, and you cannot prove it will hold under adversarial input.
Enforcement has to happen where the action actually executes. If the platform checks permissions on every call, then a forbidden action fails no matter what the model decided — enforcement comes from code, not persuasion.
What is the policy template?
On Naïve, permissions live in an Account Kit — a reusable policy template you assign to a tenant user. It controls two things: which native primitives are enabled, and which third-party apps a user may connect.
{
"name": "Pro",
"primitives_config": {
"cards": { "enabled": true, "defaults": { "spending_limit_cents": 250000 } },
"email": { "enabled": true },
"vault": { "enabled": true },
"social": { "enabled": false }
},
"connections_config": {
"mode": "allowlist",
"toolkits": ["gmail", "slack", "stripe", "hubspot", "notion", "linear"],
"tools": { "gmail": { "enable": ["GMAIL_FETCH_EMAILS", "GMAIL_SEND_EMAIL"] } }
}
}Because the kit is enforced server-side, social being false here means no prompt can make this agent post — the capability simply isn't available to it.
How granular can permissions get?
Three levels, from coarse to fine:
- Primitives — enable or disable each native capability (cards, email, vault, social, …), with defaults like a card
spending_limit_cents. - Apps — choose a mode:
open(every app),allowlist(only listed apps), orblocklist(all except listed). - Individual tools — within an allowed app, enable or disable specific tools. Allow Gmail, but only
GMAIL_FETCH_EMAILSandGMAIL_SEND_EMAIL, for example.
That range is what makes real least-privilege possible: a Starter tier can be tightly boxed while an Enterprise tier opens up, all from the same mechanism.
How does approval fit in?
Some actions are too consequential to run unattended. Each gated primitive accepts requiresApproval; when it's on, the agent's action freezes as a pending approval (HTTP 202) until a human approves it.
Sensible defaults ship out of the box: cards, domains, verification, formation, and connecting a new app default to requiring approval. You can opt a primitive out with requiresApproval: false. And the gate is smart about who's calling — human callers from the dashboard or a session are not subject to it; only agent (API-key or MCP) calls are gated (per published docs). Naïve's governance primitive covers this approval-and-audit layer in depth.
How does this compare to rolling your own?
| Concern | Hand-rolled permissions | Naïve Account Kit |
|---|---|---|
| Where enforced | Scattered if checks per request | Server-side, on every call |
| Granularity | Whatever you remember to code | Primitive → app → individual tool |
| Approvals | Custom queue + freeze/replay logic | requiresApproval + HTTP 202, built in |
| Scaling to many users | Per-user config drift | Assign a shared kit; edit once, applies to all |
| Auditability | Prompt text you can't verify | Declarative policy you can read and diff |
Where to start
Author one kit for your most common tier — enable the handful of primitives that tier needs, set an allowlist of apps, and leave the sensitive primitives on their default approval gate. Assign it to a tenant user and watch a forbidden action fail cleanly. For the full definition and the exact config surface, see what is an Account Kit? and the Account Kits docs.
What are AI agent permissions?+
Why can't I just tell the agent what it's allowed to do in the prompt?+
How do Account Kits enforce permissions?+
Can I restrict an agent to specific tools within an app?+
Which actions require human approval by default?+
Do I configure permissions per user?+
Building the agent-native backend.
Building multi-tenant AI agents into your SaaS means giving each customer an isolated, governed agent. Here's the full architecture and how to ship it.
Multi-tenant AI agents give every customer their own isolated agent. Here's the operator, tenant-user, and Account Kit model behind per-user isolation.
An Account Kit is a reusable policy template that governs what a tenant user's AI agents can do — which primitives are enabled and which apps they can connect.
Human-in-the-loop approvals that freeze sensitive actions until you say yes, a per-user audit trail of everything an agent did, short-lived scoped MCP sessions, and unified async job tracking — the controls that make an autonomous fleet safe to run.