Agent door
Capabilities & grants
A grant lists the exact capabilities an agent may exercise. Capabilities are the door's first authority layer; row-level security is the independent second.
Every tool the door exposes names a capability — a dotted
resource.verb string — that a caller's grant must hold. A workspace admin
issues a capability grant listing exactly which capabilities an agent may
exercise. The capability gate is the first authority layer; row-level security on
ctx.db is a second, independent one, so a bug in either cannot read or write a
row the other forbids.
The capability namespace
The grantable capabilities are derived from the live tool registry — a capability is
grantable if, and only if, some tool actually gates on it. There are thirteen today — they back
the fourteen tools in the Tools reference, because
action_item.update backs two: the write (update_action_item) and its
read-only status poll (get_approval_status).
| Capability | Kind | Grants access to |
|---|---|---|
diagnostic.list | read | List diagnostics |
diagnostic.read | read | Read a diagnostic |
report.read | read | Read a completed forensic report |
action_item.list | read | List action items |
action_item.read | read | Read an action item |
action_item.update | write | Request an action-item update (held for approval), and poll its status |
action_item.comment | write | Request a comment on an action item's activity timeline (held for approval) |
diagnostic.run | write | Request a re-run of an existing diagnostic, optionally with different numeric inputs (always held for approval; metered against the organization's wallet). Limited availability — see below |
usage.read | read | Read workspace usage / quota |
strategic_assessment.list | read | List published strategic assessments |
strategic_assessment.read | read | Read a published strategic assessment |
infrastructure_audit.list | read | List published infrastructure audits |
infrastructure_audit.read | read | Read a published infrastructure audit |
Each capability maps to one or more tools in the Tools reference, which is generated from the same registry.
Reads: verb wildcards
For read tools, the gate honours a verb wildcard: a grant holding
diagnostic.* satisfies both diagnostic.list and
diagnostic.read. The wildcard is a convenience for read scopes only.
Writes: exact match, opt-in, never default
The write capabilities — action_item.update,
action_item.comment and diagnostic.run — are
exact-match: a verb wildcard never
unlocks one. Holding action_item.* for reads does not grant either
action-item write, and neither implies the other: changing an item's state and posting to its
timeline are separate authorities, grantable separately. Likewise
diagnostic.* reads never reach diagnostic.run — reading the
diagnostics and spending the workspace's wallet are not the same authority. A workspace opts
into a write deliberately,
one capability at a time, and no code path adds a write capability to a grant
automatically. The approval poll (get_approval_status) is exact-match too — any
write capability admits it, so an agent can always see the outcome of a write it was allowed
to request, while a read-only or wildcard grant can never even see the write queue.
Even with the write capability granted, the write itself is held for a human by default — see Write approvals.
Limited availability: diagnostic.run
diagnostic.run is the one capability that costs money per use — it asks us to
run a fresh Diagnostic, which is metered against the workspace's wallet at its plan rate. It
carries two extra constraints the other writes do not. It is always held
for a human: unlike every other write, no auto-approve setting can make it apply directly.
And it is not generally available — it can only be granted to organizations
we have explicitly enabled for agent-initiated runs, so a grant request that includes it is
refused for everyone else. Both constraints are enforced in code, not in policy.
The target is never the agent's to choose. A re-run replays an existing
diagnostic's stored intake, and the business, website URL and account always come from that
stored run — there is no argument that names, moves or redirects any of them. What an agent
may vary is the run's numeric inputs: the per-pillar self-assessment
(side_a_scores, whole numbers 1–10) and the monthly spend figures. Those merge
over the stored intake per field, so anything omitted keeps the earlier run's value, and every
override is frozen onto the approval and shown to the approving admin next to the value it
replaces. Numbers are the whole reason that half is open: the fixed target and the fixed
field list are what keep an agent from pointing a billed audit somewhere new.
Grants are org-scoped
A grant authorises exactly one organization. Every tool binds its query to that org in addition to row-level security, so a grant issued for one workspace can never reach another's rows — even if the underlying identity happened to have membership elsewhere.