Kits live in a project
A kit belongs to one project (account_kits.project_id), and
so does every child project it governs. Assignment does not cross the boundary:
pointing a child project at a kit from another project is a 404. Kits that predate
the projects layer belong to the organization’s default project, where every un-scoped
call still lands. Each project provisions its own default kit and default child
project.
App filter — three modes
allowlist and blocklist are mutually exclusive — modeled as
toolkits: { enable } vs { disable }.
Per-tool filter
Within an allowed toolkit, restrict to specific tools withtools.<toolkit>.enable or .disable (mutually exclusive). E.g. allow Gmail but only
read + send.
White-label
custom_auth_configs.<toolkit> pins your own provider auth config id for an app, so
the OAuth consent screen shows your brand instead of Naive’s or the provider’s.
Governance — require approval
Each gated primitive acceptsrequiresApproval, and connections accept
requiresApproval / approvalToolkits. When on, an agent’s sensitive action is
frozen as a pending approval (HTTP 202) until a human
approves it.
What requires approval by default
The built-in set (DEFAULT_APPROVAL_ACTIONS) covers every action that spends,
registers with a regulator, creates a real third-party account, or destroys knowledge:
Sending email and SMS are not gated by default. Set
requiresApproval per
primitive to opt in or out.
Two callers bypass the gate entirely: a signed-in human, and an agent acting on the
company’s default tenant_user. Only an agent (API key / MCP) acting on a
non-default tenant user is gated — see Approvals.
How it maps to the connections provider
Naive translates a kit to the provider’s session config:
The default kit on signup is
mode: "open" with every native primitive enabled.