Guide/connections1 min read

OAuth for AI Agents: Per-User Connections

OAuth for AI agents should be per-user: each tenant connects their own apps — scoped by Account Kit, stored as connections, not shared tokens.

Read the docs →

Guide/connections
TL;DR
  • OAuth for AI agents in a multi-tenant product means each end-user authorizes their own apps not one shared integration account for everyone.
  • Naïve stores OAuth grants as connections on the tenant user Gmail, Slack, GitHub, and 1,000+ apps (per published docs).
  • The Account Kit controls which apps a user may connect open, allowlist, or blocklist — enforced when the agent calls connect or execute.
  • Connecting a new app defaults to requiring human approval for agent calls (per published docs).
  • Tokens never enter the model context; the agent calls governed tools and the platform uses the connection server-side.
  • White-label the OAuth consent screen with your brand via connections_config on the kit.

When builders add tool use to a multi-tenant product, the first OAuth mistake is sharing one integration account across all customers. Customer A's agent reads Customer B's inbox. The fix is per-user connections: each tenant user completes OAuth for their own apps, and grants live on their agent identity.

Naïve implements this as the /connections primitive — 1,000+ apps (per published docs), Account Kit–gated, approval-routed for agent-initiated connects.

Shared OAuth vs per-user connections

Shared integration accountPer-user connection
Grant lives onYour server's env varsOne tenant user
Cross-tenant riskHigh — one token, all customersStructural — forUser(id) scopes grants
Revoke one customerRotate shared token → everyone breaksRevoke that user's connection only
Kit policyCustom if-checks in app codeAccount Kit allowlist enforced server-side

How the connect flow works

1. Your app: forUser(user_id).connections.connect("gmail")
2. End-user: completes OAuth in browser (your branded consent)
3. Naïve: stores encrypted grant on tenant user
4. Agent: calls governed email/connections tools — tokens used server-side

Agent calls to connect a new app default to human approval (per published docs).

Wire it up

const user = await naive.users.create({ email: "customer@acme.com" });
const client = naive.forUser(user.id);
 
const { redirectUrl } = await client.connections.connect("slack");
// redirect customer to redirectUrl — grant attaches to this tenant user only

Restrict apps on the kit:

connections_config: {
  mode: "allowlist",
  allow: ["gmail", "slack", "github"],
}

Where to go next

Frequently Asked Questions
How does OAuth work for AI agents on Naïve?+
Each tenant user connects third-party apps through Naïve's connections primitive. You generate a connect URL scoped to that user; after OAuth completes, the grant is stored encrypted on the tenant user record. The agent invokes tools through the governance gateway — it never receives raw OAuth tokens to paste into prompts.
Why must OAuth be per-user in a multi-tenant SaaS?+
A shared integration account means every customer's agent reads the same inbox or posts to the same Slack workspace — a privacy disaster and a single point of compromise. Per-user connections attach OAuth grants to one tenant user so Customer A's Gmail stays Customer A's.
How does the Account Kit restrict which apps agents can connect?+
connections_config on the kit sets mode: open (all apps), allowlist (only listed toolkits), or blocklist (all except listed). You can also enable or disable individual tools within an allowed app. Policy is checked server-side on connect and execute.
Does connecting an app require human approval?+
For agent (API-key/MCP) calls, connecting a new app defaults to requiring approval — the connect action returns pending_approval (HTTP 202) until a human approves (per published docs). Human callers from your dashboard are not subject to this gate.
How many apps can Naïve connect?+
1,000+ third-party apps via the connections catalog (per published docs). When an app is not available, fall back to the browser primitive for direct UI automation and vault the resulting credentials per user.
Can I white-label the OAuth consent screen?+
Yes. Account Kit connections_config supports branding fields so end-users see your product name on the consent screen, not a generic vendor label — important when your SaaS owns the customer relationship.
NT
Naïve Team

Building the agent-native backend.

Keep reading