Guide7 min read

Building AI Agents Into Your SaaS: The Multi-Tenant Playbook

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.

Read the docs →

/building /building /building /building /building /building /building /building /building /building
/building /building /building /building /building /building /building /building /building /building
/building /building /building /building /building /building /building /building /building /building
/building /building /building /building /building /building /building /building /building /building
/building /building /building /building /building /building /building /building /building /building
/building /building /building /building /building /building /building /building /building /building
/building /building /building /building /building /building /building /building /building /building
/building /building /building /building /building /building /building /building /building /building
/building /building /building /building /building /building /building /building /building /building
/building /building /building /building /building /building /building /building /building /building
/building /building /building /building /building /building /building /building /building /building
/building /building /building /building /building /building /building /building /building /building
/building /building /building /building /building /building /building /building /building /building
/building /building /building /building /building /building /building /building /building /building
Guide
TL;DR
  • Building AI agents into a multi-tenant SaaS means every customer gets their own isolated, governed agent not one shared agent with a big system prompt.
  • The hard part isn't the model; it's the surrounding infrastructure: per-user identity, permissions, secrets, spend control, and revocable access.
  • Six building blocks make it work: identity, permissions (Account Kits), secrets (vault), spend (cards + approvals), delegated sessions, and runtime.
  • Naïve's model is Operator → Account Kit → tenant user → resources, with `naive.forUser(customerId)` scoping every call to one customer.
  • Governance is enforced server-side: sensitive actions gate on approval, secrets never reach the model, and sessions are short-lived and revocable.
  • Start by creating a tenant user and assigning an Account Kit then add primitives one at a time.

If you're adding AI agents to a SaaS product, the interesting question isn't "which model?" It's "what happens when a thousand different customers each have an agent acting on their behalf?" Building multi-tenant AI agents means giving every customer their own isolated, governed agent — one that can act in the real world without ever touching another customer's data, money, or credentials.

That surrounding infrastructure — identity, permissions, secrets, spend, and revocation — is the actual work. This playbook walks through the building blocks, the pitfalls teams hit when they roll their own, and how Naïve's developer platform turns each block into a primitive you configure instead of build.

What does it mean to build AI agents into a multi-tenant SaaS?

A multi-tenant AI agent is an agent that exists per customer, not per app. Each of your users gets an agent with its own identity, its own permissions, its own secrets, and its own spending authority — all isolated from every other tenant.

The tempting shortcut is one shared agent with a big system prompt that says "only act for customer X." That works in a demo and fails in production: a single prompt-injection, a logging mistake, or a mixed-up variable can leak one tenant's data or spend into another's. Isolation has to be structural, enforced below the model, not requested in natural language.

Why is per-user isolation the hard part?

The model is the easy part. The hard part is everything an agent needs to act: an identity to act as, a boundary on what it may do, somewhere to hold secrets, a way to pay, and a way to pull its access back. Each of those is a small distributed-systems problem, and you have to solve all of them before the first agent touches a real customer.

Teams that build this in-house usually end up assembling a payments integration, a secrets manager, an OAuth broker, an approvals queue, an audit log, and a session service — then maintaining the seams between them. It's months of undifferentiated work that has nothing to do with your actual product.

What are the building blocks?

Six concerns show up in every multi-tenant agent product. Here's the DIY version versus the primitive that replaces it.

ConcernThe DIY stackThe Naïve primitive
IdentityPer-tenant user records + custom scoping everywhereTenant user + naive.forUser(customerId)
PermissionsHand-rolled policy checks per requestAccount Kit (policy template, enforced server-side)
SecretsSecrets manager + careful redactionPer-tenant KMS-encrypted vault the model never reads
SpendCard issuing integration + limit logicPer-user virtual cards with fixed limits
Approvals & auditApprovals queue + append-only log serviceApproval gates + per-user audit log, built in
Delegated accessToken service + rotationShort-lived, revocable MCP sessions

The rest of this playbook takes them one at a time.

How do you give each customer their own agent identity?

Start with a tenant user per customer. On Naïve, the model is Operator → Account Kit → tenant user → resources: you're the operator, you create a user for each customer, and you address that customer's agent with naive.forUser(customerId). Every call made through that scoped client is isolated to that tenant.

This is the difference between "the agent promises to stay in its lane" and "the platform enforces the lane." Isolation lives in the scoped client, so a bug in your prompt or your app code cannot cross tenants through forUser.

How do you control what an agent is allowed to do?

Give the tenant user an Account Kit — a policy template that defines which primitives the agent may call and the limits that apply. You define the kit once and assign it; the platform enforces it on every request, server-side, at execution time.

That's the key property: permissions are configuration, not per-request code you write and re-audit. If a kit doesn't grant the cards primitive, no prompt can talk the agent into spending. Naïve's governance primitive covers this enforcement layer — permissions, approvals, and audit together.

How do you keep customer secrets out of the model?

Put them in a vault the agent can use but never see. Naïve's vault is KMS envelope-encrypted per tenant, and the raw secret is consumed server-side to complete an action — it never re-enters the model's context or the client.

This closes the exfiltration path that makes DIY secret-handling risky: if a credential never enters the prompt, a prompt-injection attack has nothing to steal. The agent logs into a service or calls an API on the customer's behalf without the secret ever passing through the LLM. (See the vault docs for the mechanism.)

How do you let an agent spend money safely?

Give it a per-user virtual card with a hard limit, and gate the sensitive steps on a human. Naïve cards come in two types — a prepaid card with a $150 maximum and no cardholder required, and a managed virtual card with cardholder controls and no fixed cap — with limits set in cents (per published docs).

Spending authority is per tenant, so one customer's agent can never draw on another's card. And because issuing or funding a card can freeze as pending until a human approves, the risky moments stay under human control while the routine work stays autonomous. (Details in the cards docs.)

How do you hand out access without leaking your master key?

Never give a runtime your long-lived API key. Instead, mint a short-lived, scoped session. A Naïve MCP session (sessions.create) has a default TTL of 15 minutes and a maximum of 24 hours, is scoped to one tenant user, and is instantly revocable (per published docs).

That combination is what makes delegated access safe: the credential expires on its own, it can only act as one customer, and if anything looks wrong you revoke it immediately — without rotating the key your whole platform depends on. It's the "short-lived, scoped, revocable delegated token" pattern as a single call. (See the sessions docs.)

How does it all fit together?

Put the blocks in order and the architecture is small:

  1. Create a tenant user for the customer.
  2. Assign an Account Kit that defines their agent's permissions and limits.
  3. Scope every call with naive.forUser(customerId) so identity, vault, cards, and connections are isolated to that tenant.
  4. Hand the agent a session, not your key, when a runtime needs to act.
  5. Let approvals and audit catch the sensitive moments and record everything per user.

In code, the first three steps are a few lines:

import { Naive } from "@usenaive-sdk/server";
 
const naive = new Naive({ apiKey: process.env.NAIVE_API_KEY! });
 
// 1. one identity per customer
const user = await naive.users.create({ email: "customer@acme.com" });
 
// 2. scope every call to that tenant — cards, vault, connections all isolated
const agent = naive.forUser(user.id);
 
// 3. hand a runtime a short-lived, revocable session, not your long-lived key
const session = await agent.sessions.create({ ttlMs: 900000 });

The result is an agent that can genuinely act in the world — sign up for services, hold credentials, spend within limits, operate as the customer — while staying inside a boundary you defined and can revoke. The same model runs one agent or a hundred thousand.

What are the common pitfalls?

A few mistakes show up again and again when teams first add agents to a multi-tenant product:

  • Isolation by prompt, not by platform. "Only act for customer X" in a system prompt is a suggestion, not a boundary. Scope with a tenant identity so crossing tenants is blocked by the platform, not merely discouraged.
  • Secrets in the context window. The moment a raw API key or password enters the prompt, a prompt-injection attack can exfiltrate it. Keep secrets in the vault and let them be used server-side only.
  • One long-lived key everywhere. Handing your master key to every runtime means one leak compromises every tenant. Issue scoped, short-lived sessions instead.
  • No human gate on money and identity. Fully autonomous card issuance or company formation is where costs and liability escape. Keep the sensitive steps approval-gated and let the rest run.

Where to start

Pick one customer flow and make it multi-tenant end to end: create a tenant user, assign an Account Kit, and have the agent do one real thing through forUser — read a connected inbox, make a small card purchase behind an approval, or use a vaulted credential. Once one primitive works cleanly per tenant, the rest follow the same shape.

The multi-tenancy docs are the source of truth for the model, and the Naïve SDK gets you to the first forUser call in a few minutes. Build the agent product; let the platform be the payments, secrets, and governance company for you.

Frequently Asked Questions
How do I build multi-tenant AI agents into my SaaS?+
Give each customer their own isolated agent instead of one shared agent. That means a per-user identity, a policy that limits what the agent can do, isolated secret storage, scoped spend, and revocable access. Naïve packages these as primitives behind one API, scoped per customer with `naive.forUser(customerId)`, so you don't build the identity, payments, and governance layers yourself.
How do I give each user their own AI agent identity?+
Create a tenant user per customer and address the agent through that user. On Naïve the model is Operator → Account Kit → tenant user → resources: you create the user, assign an Account Kit that defines their limits, and every resource that agent touches — cards, vault, connections — is isolated to that tenant user, so one customer's agent cannot reach another's data through the scoped client.
How do I keep API keys and secrets out of the LLM?+
Store them in a per-tenant encrypted vault the agent can use but never read. Naïve's vault is KMS envelope-encrypted per customer; the raw secret is used server-side to complete an action and never leaks back into the model context or the client, which closes the prompt-injection exfiltration path that plagues DIY secret handling.
How do I put spending limits on an AI agent?+
Issue the agent a per-user virtual card with a fixed limit and gate the sensitive steps on human approval. Naïve cards support a prepaid type with a $150 maximum and a managed type with cardholder controls, limits are set in cents, and issuing or funding a card can freeze as pending until a human approves (per published docs).
What is an Account Kit?+
An Account Kit is a policy template that gates which primitives an agent can use and the limits that apply. You define kits once, assign one to each tenant user, and the platform enforces them server-side on every call — so permissions are configuration, not per-request code you have to write and audit yourself.
How do I give an AI agent delegated, revocable access?+
Hand it a short-lived scoped session instead of your long-lived key. A Naïve MCP session (`sessions.create`) has a default TTL of 15 minutes and a maximum of 24 hours, is scoped to one tenant user, and is instantly revocable (per published docs) — so a leaked or misbehaving runtime can be cut off immediately without rotating your master credential.
Do I have to build all of this myself?+
No — that's the point of using a platform. Identity, permissions, encrypted secrets, spend controls, approvals, audit logs, and scoped sessions are the parts teams usually rebuild for every agent product. Naïve ships them as primitives behind one key, so you assemble the agent product instead of becoming a payments, secrets, and compliance company first.
NT
Naïve Team

Building the agent-native backend.

Keep reading