- ›
Human approval for AI agents means sensitive actions freeze until a person approves— not a suggestion in the prompt. - ›On Naïve, gating is configured per primitive on the Account Kit; the API returns 202 pending_approval instead of executing.
- ›Cards, domains, verification, formation, and new app connections default to requiring approval for agent calls.
- ›Your app surfaces the pending action; a human approves; the API replays the frozen call.
- ›
Human dashboard/session callers bypass the gate— only agent (API-key/MCP) calls are gated. - ›Five steps: assign a kit, attempt a gated action, handle pending, approve, verify executed.
Human approval for an AI agent means a sensitive action freezes until a person decides — issue a card, connect a new app, form a company — instead of executing immediately. The unsafe pattern is asking the model to "check with a human first"; the safe pattern is the platform returning pending_approval and replaying only after approve.
This is a step-by-step guide using Naïve's approvals primitive, scoped to one tenant user. For the full spend/audit/revoke picture, see spend caps, approvals & revocation for AI agents.
What counts as "sensitive"?
Naïve gates these by default for agent calls (per published docs):
| Action | action_type |
|---|---|
| Issue a virtual card | cards.create |
| Create a cardholder | cards.cardholder.create |
| Top up a card | cards.topup |
| Purchase a domain | domains.purchase |
| Start verification | verification.start |
| Form a company | formation.create |
| File the formation | formation.submit |
| Connect / sign up for a 3rd-party service | connections.connect |
Override any primitive in the Account Kit with requiresApproval: true (force) or false (opt out).
Step 1 — Assign an Account Kit with gating
Ensure the tenant user has a kit that enables the primitive you want to gate. Default kits gate the actions above; a Pro tier might opt out of card approval but keep domain purchases gated.
// The kit is assigned at provision or via account-kits API — see docs for your flow
const alice = naive.forUser("alice-tenant-id");AI agent permissions explains how kits enforce policy server-side.
Step 2 — Agent attempts a gated action
The agent calls the primitive normally. If gated, execution stops:
import { isPendingApproval } from "@usenaive-sdk/server";
const res = await alice.cards.create({
name: "Ads",
spendingLimitCents: 50000,
});
if (isPendingApproval(res)) {
console.log(res.approval_id, res.title);
// → surface to your UI: "Agent wants to issue card 'Ads' — approve?"
}The response is HTTP 202, not an error — the action is parked, not failed.
Step 3 — Surface the pending approval
Your product shows the human who can decide: the developer, the customer's admin, or the end-user — depending on your model. Include title, action_type, and approval_id so the decision is informed.
List pending items:
naive approvals list --status pending --user alice-tenant-idStep 4 — Approve or deny
A human approves; the API replays the frozen call:
await alice.approvals.approve(res.approval_id);Or deny with a reason:
naive approvals deny <approval-id> --reason "not authorized" --user alice-tenant-idOn approve, status becomes executed with the action's result. On deny, denied — the action never ran.
Step 5 — Verify the outcome
const a = await alice.approvals.get(res.approval_id);
// a.status === "executed" → inspect a.resultCheck the per-user audit log if you need the full trail — gateway decision, approval, execution.
How do you know it worked?
- Agent call on a gated primitive →
pending_approval, not a completed resource. - Approve → same resource exists as if the agent had succeeded directly.
- Deny → no side effect; agent receives denial on retry.
- Human dashboard action on the same primitive → executes without the gate (per published docs).
Why this matters in multi-tenant apps
One shared approval queue for all customers is a data-leak waiting to happen. Scope approvals to the tenant user: naive.forUser(customerId).approvals.* so Customer A's pending card issue never appears in Customer B's inbox. That's structural isolation — the same pattern as multi-tenant AI agents.
Where to go next
That's the approval loop: kit gates → agent pending → human decides → replay or deny. Wire one primitive first (card issue is the classic demo), then expand. The approvals docs are the source of truth; the governed agent profile shows where approval sits in the full lifecycle.
How do I add human approval to an AI agent?+
Which AI agent actions should require approval?+
What happens when an agent hits an approval gate?+
Do human operators go through the approval gate?+
Can I require approval for custom actions?+
Building the agent-native backend.
Spend caps, human approvals, and instant revoke for AI agents must be enforced server-side — Naïve's governance gateway applies all three on every call.
A governed agent profile is an AI agent with identity, spend limits, approvals, audit, and instant revoke — enforced on every action. Here's the full lifecycle.
AI agent permissions should be enforced server-side at execution time, not prompted. Here's how policy templates gate primitives, apps, and approvals.
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.