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, with the one exception of diagnostic.start (below). There are twenty today — they back twenty-three of the twenty-five tools in the Tools reference, because three capabilities each back two tools: action_item.update backs the write (update_action_item) and its read-only status poll (get_approval_status), portfolio.read backs list_portfolio and get_portfolio_changes, and diagnostic.read backs get_diagnostic and get_run_status. Of the other two, describe_yellowhead describes Yellowhead and its plans, reads no account data and gates on no capability, and start_diagnostic gates on diagnostic.start, which is never issued in a capability grant (see below).

CapabilityKindGrants access to
diagnostic.listreadList diagnostics
diagnostic.readreadRead a diagnostic
report.readreadRead a completed Diagnostic report
action_item.listreadList action items
action_item.readreadRead an action item
action_item.updatewriteRequest an action-item update (held for approval), and poll its status
action_item.commentwriteRequest a comment on an action item's activity timeline (held for approval)
diagnostic.runwriteRequest 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.readreadRead workspace usage / quota
strategic_assessment.listreadList published strategic assessments
strategic_assessment.readreadRead a published strategic assessment
infrastructure_audit.listreadList published infrastructure audits
infrastructure_audit.readreadRead a published infrastructure audit
citation_scan.listreadList the organization's Citation Scans
citation_scan.readreadRead a Citation Scan and, once completed, its results
crawlability_scan.listreadList the organization's Crawlability Scans
crawlability_scan.readreadRead a Crawlability Scan and, once completed, its run summary
accessibility_scan.listreadList the organization's Accessibility Scans
accessibility_scan.readreadRead an Accessibility Scan and, once completed, its results
portfolio.readreadList the organization's client workspaces with their latest scores and open high-priority items, and which moved since a date. Team accounts on an Agency plan, Business Enterprise or a custom plan

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.

Given at sign-in only: diagnostic.start

diagnostic.start backs start_diagnostic, which starts a free Diagnostic from inside an AI assistant's conversation. It is never issued in a capability grant: grant management refuses it by name. A connection receives it only when a person connects an AI assistant through its sign-in and approves the consent screen, on every plan, and the run is that person's, as if they had started it in the app. Like a write capability it is exact-match, so diagnostic.* never reaches it. It is not held for approval: the first call returns a preview and starts nothing, and only a second call with the preview's confirmation token starts the run. It uses only the account's included monthly Diagnostics and never the wallet; when none are left, nothing is charged. The run is recorded with the same five choices as the app (the person's own business, a client, a competitor, research or a prospect) and filed by the same workspace rules: a competitor or research run of a website no workspace holds is filed in no workspace and creates none.

What the consent screen says it may do follows the account's plan. On a plan with workspaces, it can file the run in one of them. On an Agency plan (Consultant, Studio or Firm) or a custom plan, it can also create a new prospect or client workspace for the business when the person asks for one, provided that person is an owner or admin of the team account.

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.