Getting started

The governance model

Roles, policies, and halts — how Authoric decides what any caller is allowed to do.

Everything Authoric does about access reduces to one sentence:

A principal holds roles. Roles are bound to policies. A policy names an action on a resource. Every request is checked against the policies of the principal making it, at the moment it happens.

There is no second mechanism, no bypass for internal callers, and no per-caller special case. An AI agent is governed by the same sentence as a human user.

Policies

A policy grants one action on one resource. Policy keys read as resource:action:

KeyGrants
notes:read_listList rows in notes
notes:createInsert into notes
orders:deleteDelete from orders
sdk:queryRun raw SQL from inside a handler

Because table APIs are generated, their policies are too — a new table arrives with the same five actions as every other, and nothing is reachable until a policy grants it.

Roles

A role is a named bundle of policies: support-agent, billing-admin, read-only. You bind policies to roles, and roles to principals. Principals never hold policies directly, which keeps "what can this person do" answerable by looking at one thing.

Roles are per-app. A role in one app has no meaning in another.

Checking happens per request

Authorization is resolved for each request from that request's own principal. It is not cached onto a shared object, not computed once at sign-in, and not carried in module-level state.

Why this is stated so plainly

The alternative — resolving authorization once and holding it somewhere shared — is a known and repeatedly-shipped class of bug in which one request's privileges leak into another's under concurrency. Per-request isolation is an invariant here, and it is tested as one.

This is also why a token can never widen its own reach. What a caller may do is decided from the caller's roles at request time, not from anything the caller sends.

Risk, and The Halt

Some actions are more consequential than others. Authoric classifies actions by risk level, and high-risk actions behave differently when an agent attempts them.

A normal action executes. A high-risk action halts:

The agent reaches the step

It has decided to issue a refund, delete a record, or change a schema.

The run pauses

Nothing is executed. The run's status becomes pending_approval, and the intended action — the tool and its exact arguments — is recorded.

A human decides

The pending step appears in the approval inbox. A person with authority to approve sees precisely what the agent wants to do.

The run resumes, or does not

On approval, the run continues from exactly where it stopped, with the approved step executed. Otherwise it stops there.

The person who approves is never the agent that asked. An external caller can tighten this — it may force human approval even for an agent configured to auto-approve — but it can never loosen it.

A halt is not a failure

A halted run has not errored and has not timed out. It reached a boundary you set, recorded its intent, and waited. Treat pending_approval as a normal outcome and poll for the result.

Where an agent's abilities come from

An agent has no tool list. You do not enumerate what it may do.

Instead, its tools are derived from the policies bound to its role. Grant refunds:create and the ability to create a refund appears in its toolbox. Revoke it and the tool disappears — for the orchestrated loop, for direct tool calls, and for any MCP client connected to it, all at once, because all three read the same derivation.

This is why governing an agent here is the same work as governing a user, rather than a parallel system that has to be kept in step.

Next

On this page