How it works
Inside the agent, tools are handles, never raw secrets. When the model callscards.charge($48):
- The runtime shim sends the call to the Naïve gateway — not to the card processor.
- The gateway authenticates the agent profile’s scoped token and loads policy, budget, balance.
- Policy check: allowed? under cap? crosses the approval threshold?
- Allowed → the gateway (which holds the real issuing credential, never the agent) calls the processor, records the action, and decrements the budget.
- Needs approval → the action is parked, a Slack/email ping is sent, and it returns
pending; it executes on approve. - Denied → one clean, structured denial, logged. No retry storm.
403 budget_exceeded; soft caps route to approval; exhausting a hard cap or the
company’s credit balance auto-stops the agent profile’s hosted runtime. Each agent profile
holds its own scoped key(s) — list / rotate / revoke them per agent profile
(/v1/agent-profiles/:id/keys) without touching the company key.
Why it can’t be bypassed
The agent holds a per-agent profile scoped key (sealed to the agent profile’stenant_user at provision time), never the company key and never the underlying
provider credentials (Stripe, Doola, Footprint, Resend, Surge) — those live behind
the gateway in the encrypted vault. So the agent can only ever ask; the gateway
decides, executes, and records. revoke() is absolute: it suspends the
agent profile (every subsequent call 403s), releases its runtime slot, and cascades to
sub-agents. Sub-agent kits are scoped-down derivations of the parent
(capabilities can only narrow; budget is shared), closing the confused-deputy hole.
This governance is constant regardless of where the agent runs — Naïve-hosted,
or a Vercel Eve / AgentCore / LangGraph agent on your own infra. Self-hosting the
runtime does not bypass it, because governance is at the tool-call boundary.
How it maps to the platform
| Concept | Implementation |
|---|---|
| Policy (allow/deny, caps, approvals) | AccountKit attached to each agent profile |
| Human-in-the-loop | The approvals queue (sensitive actions return pending_approval) |
| Enforcement point | Every per-agent profile primitive route + the MCP guard |
| Audit | Per-agent profile activity log (OpenTelemetry-shaped, exportable to Langfuse/Datadog) |
| Revoke | agentProfile.revoke() / POST /v1/agent-profiles/:id/revoke — suspends the agent profile; the gateway then denies all further calls |
Two planes, one policy
You declare one agent’scan / limits; the control plane routes it to two planes:
- Business-action governance (we own this) — budgets, spend caps (enforced at authorization), HITL approvals, capability allow/deny, audit, instant revoke — at the tool-call boundary, across the whole agent profile bundle. The differentiated layer the agent-payments and agent-runtime competitors don’t span.
- System governance (OpenShell-compatible) — the microVM’s network / filesystem / process isolation. Compatible with NVIDIA’s emerging standard, not a competitor.