Every agent call -- Gmail send, Drive read, database query, browser click -- is checked against a per-user, per-tool permission map before it reaches the downstream system. This page is what that looks like in practice.
Per-tool permission keys, scoped to the user. Checks happen in the logic layer, not the transport. No path bypasses the check.
Issue a bearer token scoped to a subset of your own permissions, with a TTL and usage tracking. Revocation is immediate.
Pre-execution, real-time, and post-execution checks: injection, PII redaction, sensitive-topic filtering, human-in-the-loop for high-risk actions.
Every action, token use, and permission change is logged with append-only semantics and optimistic locking at the data layer.
OAuth refresh tokens stored encrypted per user, rotated on a timer, never shared across tenants.
Web, REST, and MCP all pass permissions down to the same logic layer. One enforcement point, three entry points, identical semantics.
Each protected module declares its permission keys and uses the AccessControlled macro. Every transport -- Web, REST, MCP -- passes the user's permission map down to that module. If the key is missing, the call returns {:not_allowed, reason} and every transport translates that into its own response format.
Permission keys never leave the server process. They are not serialised into responses, cookies, or logs.
A sub-token (prefix st_) is a bearer token scoped to a strict subset of the owner's permissions, with a TTL, usage counter, and audit trail. At authentication time the sub-token's scope intersects with the owner's current permission map before anything downstream sees it.
Revocation is immediate: strip the owner of a key, and every sub-token scoped to it stops working on the next request.
Pre-execution blocks injection, path traversal, and malformed requests before they reach your systems. Real-time requires human approval for high-risk operations. Post-execution redacts PII and strips credentials before outputs reach the agent.
Every tool call, every permission change, every sub-token use is logged with user, agent, inputs, outputs, and cost. Append-only. Optimistic locking at the database layer means concurrent writes fail loud rather than silently corrupt.
Primary keys are millisecond timestamps, so id / 1000 is the creation Unix second. Creation time is free on every row.
No framework rewrites. No new SDK. Three transports, one enforcement point.
| Transport | Typical client | Shape of call |
|---|---|---|
| MCP (Model Context Protocol) | Claude, Cursor, MCP-aware agents | tools/call over JSON-RPC with bearer token |
| REST / HTTPS | Scripts, backend services, legacy agents | Conventional JSON over HTTPS |
| WebSocket (WSS) | Long-lived agents, browser extensions | Message-framed bidirectional channel |
One virtual machine, one process tree, one SQLite per module. Runs on the Erlang VM (BEAM), the same runtime that powers RabbitMQ.
Runs in fully isolated networks. Credential encryption is local. No telemetry, no phone-home, no third-party services required.
We run it for you on a dedicated instance. No multi-tenancy. Your data never touches another customer's process tree.
Every agent call routes through AI Agent Gateway before it reaches its target. Per-user, per-tool permissions; configurable guardrails; one row per request in the audit log; the agent never holds the credentials.