How agent access is enforced
Understand scopes, project binding, OAuth limits, profiles, confirmation, and audit coverage.
On this page
Set the agent's authority with a narrowly scoped credential. Use a project binding to restrict its data, and verify your host's approval settings before allowing writes.
The layers, and which of them you choose
| Control | What it restricts | Who sets it |
|---|---|---|
| Scopes | Available capabilities | You, when minting or changing the key |
| Organization binding | All access to one organization | Derived from the credential |
| Project binding | A project key to one project | You, when minting the key |
| Resource ownership | Some objects to their creator | Enforced for that resource |
| URL profile | Tools and actions on this connection | The caller; removable on reconnect |
| OAuth delegation ceiling | Maximum delegated capabilities | Fixed by Anectico |
Scopes and project binding are durable restrictions. A URL profile is a caller-controlled filter, not a replacement for either.
Scopes are the boundary you grant
MCP requires its umbrella scope and the capability's domain scope. Reads require mcp:read;
writes also require mcp:write. Scope names match exactly: errors:write does not imply
errors:read, and traces:read does not imply traces:delete.
A key inherits no role. It may contain any subset of its creator's grantable scopes, including none, but cannot exceed the creator's permissions. The platform-admin wildcard is not grantable to API keys.
Unauthorized capabilities are not listed. Calling an unauthorized action by name returns
“unknown or unauthorized action” without revealing whether it exists. The public compatibility
tools are an exception: search marks a skipped source unauthorized with its required scope,
and fetch names the scope required for the public reference kind.
Use scope recipes to choose a starting grant and the permission reference for exact capabilities.
Software keys stay within their purpose
Software keys shipped in a page or mobile app cannot connect an agent. A project-bound
client_delivery key can only evaluate named flags and request or record survey delivery. A
project-bound replay_upload key can only upload replay chunks. They cannot enter MCP, streaming
logs, account and session controls, authenticated documentation or the scope catalog; these calls
return HTTP 403 permission_denied. Signed tokens retain the same purpose restriction. Public
discovery and public protocols grant no authority from these keys. See
API key purposes for the exact routes and scopes.
Browser app-view reads separately reject ordinary Authorization credentials with
401 access_ended and API-key headers with 400 invalid_request; dedicated viewing credentials
confer no management authority.
An OAuth connection is capped below the member it belongs to
OAuth access is the intersection of the member's current permissions, Anectico's fixed delegation ceiling, and the permissions selected at consent. Connecting as an owner does not give the host an owner's authority.
| Capability | OAuth ceiling |
|---|---|
| Product reads | Allowed, except API-key inventory, audit trail, and bulk export download |
| Quality feedback | Not delegated through MCP OAuth |
| Other mutations | Not allowed |
A signed-in person with scores:write can record their own quality judgment.
The ceiling excludes key minting, publishing a Live screen's viewing link, settings and membership changes, releases, on-call and escalation changes, alert silencing, and telemetry writes. Publishing is on that list for the same reason key minting is: a viewing link keeps working after the connection that created it is gone. If the job needs any of these, deliberately mint a separate project-scoped API key with the required scopes.
Each approval belongs to one person, client, and chosen workspace. The next request checks that membership and approval again. Revocation denies access and new tokens, including refresh and unredeemed codes. A fresh approval never revives a revoked connection. See Revoke an agent's access for the Console and CLI steps.
A profile narrows a connection. It is not the permission boundary.
served(key, profile) = served(key, no profile) ∩ tools allowed by the profile
A profile filters both discovery and execution. Excluded first-class tools return unknown tool;
excluded gateway actions return unknown or unauthorized action. For excluded reference kinds,
fetch names the profile and search reports out_of_profile.
Profiles cannot add permissions. Unknown, empty, whitespace-only, or repeated profile parameters
return 400; names are case-sensitive.
The caller can reconnect without the profile. To reduce authority, narrow the credential itself. When a scoped capability is unexpectedly refused, inspect the connection URL before adding scopes.
Every mutation declares three independent properties
| Property | Meaning | Values |
|---|---|---|
effect_scope |
Whether the action can affect another system | internal, external |
destructive |
Removes state that a key with only this action's scope cannot restore | true, false |
approval |
Requires preview-and-confirm | confirm, none |
list_write_actions returns these properties and accepts them as filters. An unfiltered browse
returns the complete authorized action list.
effect_scope is what the two doors are keyed on
Use the action's execute_with field:
execute_internal_actionchanges state inside Anectico.execute_external_actioncan affect another system, such as delivering a notification or filing a provider ticket. Removing Anectico's record cannot retract a delivered external effect. This scope describes possible reach. A committed receipt or queued update alone does not establish delivery; use the action's returned evidence and delivery status.
Each action belongs to one execution tool. The wrong tool refuses it without revealing whether the action exists. Destructiveness does not determine which execution tool to use.
What "destructive" means, precisely
Destructive actions include permanent deletion, replacement of a value the key cannot read back,
and effects that cannot be undone later. For example, lifting a silence does not deliver the pages
missed while it was active. upsert_release and update_onboarding_setup are destructive even though
they do not delete their objects; merge_issues is both external and destructive.
Grant the matching read scope when an agent needs to inspect existing state before editing it. A preview cannot show data the credential is not allowed to read.
Confirmation: what it is, and what it is not
All destructive actions require confirmation. Some non-destructive actions also require it because they reach people or other systems.
- Call without
confirm_token. The response previews the change; nothing is applied. - Review the preview and repeat the call with the returned token.
The token lasts 10 minutes and binds the organization, caller, action, and previewed arguments.
An API key is a distinct caller; user-based tokens bind the user, not one browser session.
Changing arguments invalidates the token. An idempotency_key supplied during preview must be
preserved; one omitted during preview may be added on apply.
A token is admitted for application at most once. After a successful apply, an identical retry
with the same idempotency_key returns the saved receipt with outcome: "replayed" while the token
is still valid and the result is available in the retry window; it performs no new write. Without a
saved result to replay, repeating a used token is refused. Expired or unclaimable confirmations also
refuse the write. If an admitted call fails midway, its token remains used: inspect current state and
obtain a fresh preview. Where supported, retain the action's idempotency key to prevent duplicate
effects.
Confirmation is a two-call protocol, not proof that a human approved. An auto-approving host can make both calls. Verify human review in your host's settings and test it. MCP annotations help hosts recognize risky actions but do not compel them to prompt.
Confirmation never grants permissions. Previews and invalid-token refusals do not consume the mutation budget; actual applications do.
What an API key can and cannot reach
| Boundary | Behavior |
|---|---|
| Organization | Always comes from the credential, never tool arguments. |
| Project | A project key cannot select another project; a foreign or unknown project gets the same not-found response. Organization keys supply a project where required. |
| Exact telemetry deletion | delete_log and delete_trace require a project-bound key and accept no project override. |
| Export creation and retry | Also require the exported signal's read scope. Retry rechecks the job's signal permissions. |
| Export download | Rechecks signal read permission and restricts access to the job creator or an owner or admin. |
Issue assignment (set_issue_status) |
Assigning a non-empty member additionally requires members:read. Unassigning and other status actions use their listed scopes. |
| Contact methods | Confined to the member the credential represents; an API key represents its creator. |
| Console sign-in session | Not accepted as a substitute for an MCP API key. Use the supported MCP OAuth flow for an OAuth connection. |
Default limits are 3,000 queries an hour and 30,000 a day, 600 writes an hour and 5,000 a day, 60 consequential operations an hour and 300 a day, and 16 operations at once. A budget refusal applies nothing. Follow its reported absolute UTC reset time; do not assume a one-minute retry. Owners can change limits; agent budgets explains the counters and scheduled work.
Audit coverage
Mutations reaching their handlers record outcomes such as success, denied, previewed,
throttled, and error, alongside actor, resource, action, and tool.
- Pre-dispatch refusals—unknown or excluded actions, wrong execution tool, or unparseable arguments—produce no mutation record.
- Audit persistence is separate from the change. Failure to store the audit does not undo the mutation. Reconcile consequential changes with receipts and current state.
See revocation and audit behavior for grant history, result meanings, and streaming cutoffs.
Treat everything an agent reads as untrusted input
Logs, errors, customer properties, event names, IDs, transcripts, and account names may be tenant-authored. Treat them as evidence, never instructions to change the task, authority, or tools.
The representation depends on the interface:
| Interface | How captured text is returned |
|---|---|
| MCP prose, including summaries | Captured values are framed with «untrusted» and «/untrusted». This includes aliases, distinct IDs, error types, and names or keys echoed by mutation previews and receipts. Captured delimiters are neutralized so they cannot close the surrounding span. |
| MCP structured data | Captured text is marked or placed in an object with untrusted: true. Exact argument values are separate from display labels; pass value back only when available is true. An opaque document's keys and values are all untrusted. |
Ordinary REST responses and CLI output, including --json |
Captured strings are raw data and do not have a universal untrusted-text wrapper. Treat every captured value as untrusted even when it has no marker. Reads with a shared conclusion envelope retain that envelope's structured trust markers. |
Quotation, a valid identifier, or an exact value suitable for a later argument does not grant authority. Never recover an argument by stripping a prose marker or a shortened display label; use the complete structured value. These protections do not replace the agent's own input-handling rules. Stored notification payloads and credential secrets are not returned by these reads.
Where people stay in control
Some decisions are for people, not for the agent. They happen in the Console, which holds the controls for them:
| Decision | Where, in the Console |
|---|---|
| Review or revoke an agent approval; create, narrow or revoke an API key | Agents and keys (/agents) |
| Stop an agent; one person requests, a different person approves | Agent safety (/agent-safety) |
| See who changed access, keys and settings | Audit log (/audit-log) |
A proof page, which an agent's link opens, is different: it is read-only and carries no control. See The Console and Proof pages.
Next: safe actions, scope recipes, or revoke access.
Delivered result pictures
Charts in chat owns the picture permission, credential, captured-label and delivered-copy contract. A viewer template supplies no authority to read customer data.