AI & agent access
Agents are not special actors.
An agent authenticates, resolves to a service-account identity with a role, and then travels the same permission, approval, and audit path as any human admin. The key and role govern agent access.
One key, one boundary — the authz trace
Agent key → service-account identity → role → the same /api/graphql authz check a human dashboard click crosses; owlie_whoami returns the identity id.
An MCP server is not a backdoor
Trace one call.
Agent calls follow the same authorization path as human calls. Creating an API key and granting its service account a role delegates that role’s permissions.
- 01
An agent authenticates.
An API key over the MCP server, or the signed-in human’s session cookie in chat. Nothing is minted specially for AI.
- 02
The credential resolves to an identity.
A service account or the human themselves — an ordinary identity carrying an ordinary role. The key plus the role is the delegation.
- 03
Every call crosses one authz boundary.
The same per-actor check at /api/graphql that governs a dashboard click governs the agent’s call.
- 04
The actor is never hidden.
owlie_whoami returns the exact identity id the agent is running as. What it can touch is what that identity’s role already permits — nothing more.
Agent access has no separate inbox, per-key approval modes, or control plane.
Two ways in, one core
A third-party MCP client and Owlie’s own assistant dispatch through the same registry.
An external agent connecting over MCP and the chat at /admin/airoute through one 34-tool registry, over the one typed SDK underneath. The assistant runs as a durable agent — one per signed-in user — so a paused mutation resumes cleanly instead of starting over.
Two ways in, one core
An external MCP client and the /admin/ai chat both dispatch through the identical 34-tool registry, over the single typed SDK (26 namespaces) an external developer imports directly.
The capability core
Four building blocks, one shared client.
The access layer is a small set of composable pieces sitting on the typed SDK. Each one is bounded the same way — by the caller’s identity and role — because none of them adds a capability the SDK doesn’t already carry.
- 01
The MCP server
34 discrete tools from one in-process registry.
What it does
A stateless JSON-RPC endpoint over HTTP exposes owlie_whoami, owlie_describe, owlie_execute, plus 15 single-object get/create/update tools and 16 single-target action tools. There is no list or search tool by design — anything that spans a collection or a multi-step workflow belongs in code-mode. External MCP clients and Owlie’s own chat dispatch through this identical registry.
How it’s bounded
Every tool call resolves to the caller’s identity and role. A tool exists only where the underlying SDK operation does; the registry adds no capability of its own.
- 02
Code-mode — owlie_execute
Model-authored TypeScript, run in a network-isolated sandbox.
What it does
The model writes a short TypeScript program that runs inside a V8 sandbox with outbound networking switched off — fetch and connect throw. The only way out is a typed owlie.* connector spanning 230 methods across every SDK namespace: reads, aggregate counts, core mutations, and a raw-query escape hatch. One program does a whole multi-step job instead of round-tripping a tool call per step.
How it’s bounded
The API key never enters the sandbox — it lives host-side only. A per-run data budget caps a single run at 50 tool calls and 10,000 rows; a breach throws a steering error that tells the model to narrow, count, or sample rather than silently drain partial data and treat it as complete.
- 03
The typed SDK
@owlieapp/sdk — 26 domain namespaces, one shared client.
What it does
A typed TypeScript client over 26 namespaces — identities, groups, policies, sync, reviews, provisioning, and the rest — mirroring the service layer, with rawQuery as the sole raw-GraphQL escape hatch. This is the same artifact both agent surfaces run on and the same one an external developer constructs directly with an API key.
How it’s bounded
The SDK carries no elevated path. It issues the same GraphQL a human session issues and is bounded by the same per-actor authz.
- 04
owlie_describe
A discovery tool, so the model plans real code.
What it does
owlie_describe returns the live method catalog — each method’s name, one-line description, canonical input schema, and whether it requires approval — alongside 17 cross-cutting domain guides (grants, reviews, campaigns, policies, integrations, sync, provisioning, and more). The model reads the real shapes and writes against them instead of guessing.
How it’s bounded
Discovery reflects only what the caller can already do; describe surfaces the catalog, it does not widen it.
One tag, three behaviors
One sensitivity tag. Three surface behaviors.
Every mutating operation is tagged once on the SDK. That tag determines how each surface handles confirmation.
Chat
An approval card.
A single well-known mutation pauses as an inline card the human answers in one click. The card reads the sensitivity tag straight off the SDK to render a Required or Recommended badge — the same source of truth, not separately-authored UI copy.
Code-mode
A durable pause-and-replay.
An open-ended run pauses the whole durable execution and resumes by replaying it. Steps already applied are never re-run, so a mid-run approval never double-applies work.
MCP
A service-account posture.
The same tag informs the external MCP surface, where mutations run under the service account’s role. Every surface reads the same SDK flag.
One tag, three behaviors
A single sensitivity flag on the SDK fanning out to a chat approval card (Required/Recommended badge), a durable code-mode pause-and-replay, and an MCP service-account posture.
The agent shows you the queue
You make the call.
For reviews, tickets, and policy exceptions, the assistant renders the queue — but it never decides. The decision cards submit directly to Owlie under your own session, and the assistant is handed only the outcome. There is no decision-mutation on the model-callable surface at all: the model has no callable capability to make these decisions.
“These decisions are yours — they submit directly to Owlie; the assistant only sees the outcomes.”
Coverage tracking
Coverage you can count, guarded by CI.
Every product write has a row in a coverage map, and a test fails the build the moment a new mutation ships without one. Today roughly 90% of product GraphQL writes are reachable from the agent surface, and each exclusion has a written reason.
The coverage ledger
The parity map + CI guard: product GraphQL writes marked covered vs. a named-exclusion list (credential ceremonies, file pickers, tenant deletion, self-state, bulk affordances that keep a human confirm step, the whole RPC lane); the build fails on any untracked mutation.
Boundaries
What it deliberately won’t do.
Current limitations and deliberate exclusions are listed below.
No unattended sessions.
Every action still requires the interactive human whose authority is being spent to be present. This is a self-confirmation model, not remote oversight — there is no run-this-agent-overnight mode, by choice.
MCP mutations run under the role alone, today.
On the external MCP surface, mutations execute under the service account’s role without a per-call human prompt — only chat has approval cards. Per-operation approvals are deferred to a separate, actor-agnostic operation-approvals program, and that is not shipped yet.
Documented exclusions.
Every write that sits out has a row and a written reason: credential and identity-link ceremonies, privileged admin enrollment, browser-inherent file pickers, UI-local self-state, tenant deletion, a few bulk affordances that keep their human confirm step, and a deprecated alias — along with the entire internal RPC lane the SDK’s transport does not even reach. Most are lines we drew on purpose; a handful name the approval flow they’re waiting on.
Decisions never move to the model.
The agent can render a review, ticket, or policy-exception queue, but it never commits the outcome. That exclusion is categorical — independent of how much of the write surface is reachable.
AI that goes through the same door as everyone else.
Sign up free. Bring the workflows you want assisted and see the same controls govern them.