Skip to content
Console
Browse documentation
Guide

Scope recipes for agent jobs

The minimum scope set for each common agent job, what each scope buys, and what to add when a job needs more.

On this page

Every MCP tool is gated twice, and both gates must pass:

  1. the umbrella for that side of the endpoint — mcp:read for every read, mcp:write for every mutation;
  2. the domain scope in that tool's own row of the MCP tool reference.

A key holding an umbrella and nothing else authenticates and is served an empty tool list. That is the single most common "the server does not support this" report, and it is a scope problem.

A person creates and changes keys in the Console, in Agents and keys (/agents), or with the CLI. The recipes below name the scopes; the Console and the CLI both take the same scope names. See The Console.

Start from a bundle

anectico apikey create --scope-profile <name> and anectico agent bootstrap --scope-profile <name> materialize a bundle into explicit scopes, stored on the key. The key records the scopes, never the bundle name, so its authority is fixed at mint time and is auditable by reading it back with anectico apikey list -o json.

Bundle Scopes What it is for Mintable by
investigate 34 Default investigation reads, model costs and stored evaluation scores; no configuration changes or evaluation execution any member
incident 57 Investigation plus incident response owner or admin
agent-observability 13 Agent operations, governance and evaluation writes owner or admin
admin 2 (the two umbrellas) Exact administrative permissions added with --scope owner or admin

investigate includes llm:read and evals:read. It can read model spend and stored scores without a second key. It cannot change prices or evaluation settings or start a paid evaluation.

Three properties of that table are decisions rather than accidents:

  • incident contains investigate in full. Incident response is investigation plus a lifecycle surface, not a different way of looking at the same data.
  • agent-observability does not. It covers agent runs, transcripts, cost, and person context, plus an evaluation write loop: mcp:write, evals:write, and scores:write allow release-gate creation and evaluation and annotation submission through the matching actions. Annotation writes additionally require an authenticated user to attribute the judgment to; scope alone does not make an unattributed API key a human reviewer. It is not a read-only monitoring bundle. Add --scope traces:read for raw spans behind a run.
  • admin refuses to stand alone. It buys the two umbrellas and a statement of intent; the authority is typed out one --scope at a time. anectico apikey create --scope-profile admin with no --scope is a usage error, and a key holding only the umbrellas is served nothing.

No bundle ever materializes a *:delete scope. Deletion is the one class of write that cannot be undone, and the preview-then-confirm gate that makes it survivable lives in the MCP write framework — a key used against the REST API gets no such gate. Every delete scope must be named explicitly.

Two things about who can mint. A key can never carry a scope its creator lacks — the mint is refused by name, so incident, agent-observability and admin are owner-or-admin work because all three carry mcp:write. And a viewer cannot mint a key at all, of any shape: key creation is itself a privileged act, and the refusal comes before the scope list is read, so hunting for the missing scope is a dead end.

Recipes

Let the agent read its own documentation

Add docs:read alongside mcp:read when an agent must discover procedures with search_docs and read them with get_doc through the read gateway, or use the compatible search/fetch tools. These two scopes alone are enough for documentation-only MCP access; no organization-data scope is needed. The investigate and incident bundles already include docs:read; the agent-observability and admin bundles do not. Add --scope docs:read explicitly to those bundles or to a custom recipe. Counts below describe the minimal recipes without that optional addition.

The URL's ?profile= filter is separate from the mint-time scope bundle. In particular, ?profile=agent-observability excludes docs even with docs:read; omit the filter or select a profile that allows docs. See Connect MCP and Machine-readable documentation.

Project selection and counts

Each row is the minimum that makes the job work end to end. Every one also needs the umbrella already shown.

These recipes assume a project-bound key — what anectico agent bootstrap mints unless you pass --org-wide. A project-bound key carries its project signed into the credential; it supplies that project on every call, and an explicit different one is denied. It therefore needs no projects:read: there is no project for it to discover.

An organization-wide key adds exactly one scope: projects:read. Without a binding, it must pass a project id to every project-addressed read and write, and list_projects is the only way an agent finds one. That is the whole difference — everything else in each row is the same. Counts below are for the project-bound form, derived from the current capability catalog and registration rules on 2026-10-10. Server tests pin the published bundle and served-tool counts, but catalog or profile changes can alter them; verify the surface served to your own key before automating against a count.

Read-only jobs (mcp:read)

Job Add these scopes Tools
Triage an error issue errors:read logs:read traces:read persons:read services:read 16
Answer "what happened to this customer" persons:read persons:profile:read errors:read logs:read traces:read analytics:read replay:read replay:content:read groups:read agents:read 27
Watch AI agents and their spend agents:read llm:read 4
Everything an investigation needs the investigate bundle 34

The triage row is the smallest genuinely useful read key: it gets search, fetch, list_issues, get_issue, get_affected_users, search_logs, get_log_patterns, search_traces, get_trace, get_person_timeline, resolve_person, search_persons, search_issues and get_service_health, plus the two read-action doors list_read_actions and execute_read_action. Drop persons:read and it falls to 13: no person timeline, no identity resolution, and search stops having a people source to search.

The agent-watch row looks too small, and is not. Four tools is right: run metadata is list_agent_runs, fleet posture is list_agent_fleet, and everything else this key can do is a read action reached through list_read_actions and execute_read_action, which is why none of it adds an entry to the tool list. Behind those two doors the same key gets all three LLM-cost capabilities — the summary, the series and the top spenders — plus list_agent_sessions (which conversations happened), list_agent_turns (the exchanges within one of them), get_agent_run_graph (one run's step structure), list_context_events (the context assembly evidence), get_telemetry_completeness (how current the agent telemetry itself is), and verify_receipt_chain (whether the agent's action receipts still verify). The same key reads the same answers from a terminal: anectico agent-sessions list|get|turns, anectico agent-runs graph and anectico agent-runs completeness. Two scopes are commonly added to the row, and each should be a decision rather than a reflex:

Add What it buys What it also exposes
agents:content:read get_agent_run — one run's detail The verbatim transcript: the prompts, completions and tool messages the model exchanged. If the agent under observation handled customer data, this is that data
persons:read get_person_timeline, resolve_person, search_persons — tying a run or a bill to the person behind it The people surface generally, and a search that now has a person source

Neither is required to watch runs or to read spend. Add them when correlation to a person, or reading what a run actually said, is the job.

Jobs that change something (mcp:read + mcp:write)

Job Add these scopes What it unlocks
Triage and resolve issues errors:read errors:write logs:read traces:read persons:read set_issue_status, snooze_issue, merge_issues, unmerge_issue
Take a page and run the response alerts:read alerts:acknowledge alerts:resolve incidents:read incidents:respond channels:read oncall:read members:read acknowledge_alert, unacknowledge_alert, resolve_alert, comment_incident, add_incident_evidence, set_incident_status, plus delivery receipts and who is on call. Add alerts:rules:write for evaluate_alert_rule, which fires and notifies
Silence a storm silences:read silences:write silences:delete create_silence, update_silence, delete_silence
File a ticket from an issue connections:read errors:read tickets:read tickets:write create_ticket, list_tickets_for_issue, get_ticket. Add tickets:delete for unlink_ticket
Build and maintain dashboards dashboard:read dashboard:write dashboard:delete the seven dashboard and widget actions. dashboard:delete covers delete_dashboard and delete_widget. A person opens the result as a proof page
Wire feature flags or product events into an application and check the sample docs:read projects:read query:read analytics:read, plus flags:read for flags. Add flags:write for an approved flag, api_key:read and api_key:write for keys (the key's creator must also hold the scope the new key carries: analytics:write for a capture key, flags:read for the flags key), projects:write for a new project, and persons:read, tracking_plans:read and agents:content:read for the identity, plan and property checks verify_integration, verify_integration_events, verify_flag_integration, create_flag, create_intake_key, create_api_key, revoke_api_key, create_project. Without persons:read, tracking_plans:read or agents:content:read, the check that needs it is withheld, never absent. See the integrate skill
Build a program you host on the REST API (a status board, support page, bot or nightly script) docs:read mcp:read projects:read services:read to read the contract, the guides and the evidence. The program's own key is a separate project key with only what it calls: services:read for a board, persons:read for a support page, oncall:read projects:read members:read for an on-call bot, errors:read for the nightly issues, and analytics:read persons:read with the result's source scopes for a saved result. Add api_key:read and api_key:write (and mcp:write over MCP) to create or revoke that key, which also needs every scope the new key carries; activity:read and audit:read to watch it get_rest_contract, search_docs, get_doc, get_service_health, create_api_key, get_api_key, revoke_api_key, get_agent_budget, get_agent_usage, list_agent_activity. The program itself calls REST and never MCP. See the build-an-app skill
Export data for offline analysis export:read export:write export:download plus the read scope of every signal exported (logs:read, traces:read, …) create_export_job, export_logs, cancel_export_job, retry_export_job, and the three export reads
Delete exact telemetry on request logs:delete, traces:delete or errors:delete — project-bound only delete_log, delete_trace, delete_error_group. Add persons:read for delete_person_errors, which erases one person's errors under every identity they have. An org-wide key is not served these at all
Publish a live screen live:read live:write live:publish plus the read scope of every panel's source (analytics:query, analytics:read, insights:read, persons:read, errors:read, services:read, alerts:read, logs:read) create_live_screen, preview_live_screen, publish_live_screen, and the pause, resume, rotate and revoke actions

Export is the row where a key most often "sees a tool it cannot call", and it is deliberate. export:write alone commissions nothing: creating a job also requires the exported signal's own read scope, so a key cannot export data it may not read. retry_export_job re-checks that against the stored job, so a key that has since lost the read scope cannot regenerate the file. And get_export_download re-checks it and requires being the job's creator or an organization owner or admin — so a key with only export:write can create a job and can neither poll it nor download it, and a key that did not create a job is answered as though the job does not exist.

Publish a live screen

A live screen is published on a project API key and keeps running on that key's current permissions, rechecked on every refresh. The key therefore needs the Live scopes and the read scope behind every panel it publishes — publishing without one is refused by name, and losing one later turns that panel into Denied on the display rather than removing it.

The full recipe, for a key that composes a screen from any template and publishes it:

anectico agent bootstrap --host claude --name 'live publisher' --scope-profile '' \
  --scope mcp:read --scope mcp:write \
  --scope live:read --scope live:write --scope live:publish \
  --scope analytics:query --scope analytics:read --scope insights:read \
  --scope persons:read --scope errors:read \
  --scope services:read --scope alerts:read --scope logs:read

That is thirteen scopes: the two umbrellas, the three Live scopes, and the eight source reads. Trim the source reads to the panels you actually publish — a screen of saved-insight trends and nothing else needs analytics:query, analytics:read, insights:read and persons:read beside the Live three.

Two scopes in that list do more than they look like they do, and both are deliberate:

Scope Why a publisher needs it
persons:read Trend panels require it alongside the analytics and saved-insight permissions. People-affected panels require errors:read
live:read publish_live_screen replaces the revision a link is already serving, and the revision about to be replaced can only be learned by reading the screen first

live:publish is the scope to withhold by default. live:write builds screens and shows nobody anything; live:publish mints a link that anyone can open without signing in. A key that drafts screens for review does not need it. And because live:publish is not a :read scope, a key frozen to its read permissions stops serving its display — which is the intended behaviour, not a bug to work around.

An agent connected over OAuth rather than an API key can read live screens and can never publish one, at any role. A person lists and revokes Live links in the Console, in Published links (/published-links). See Live viewing links and access.

A signed-in member session can publish through MCP or the CLI with the required Live and source scopes and api_key:write. Confirmation creates a dedicated project publisher key; the viewing link uses that key's authority after the session ends. Delegated OAuth remains ineligible.

What to add, and why

projects:read, only for an organization-wide key. It buys exactly one capability, list_projects, which is how an unbound agent discovers the project ids the rest of the surface takes as an argument — without it such a key fails on the first call an agent makes. A project-bound key gains nothing from it: adding projects:read to the customer recipe above changes the tools served from 27 to 27. It is in the investigate bundle because that bundle has to work either way.

The read that matches the write. A write scope without its matching read scope is what turns an ordinary edit into an unrecoverable one: the credential cannot capture what it is about to overwrite, so the preview can only tell you it is unable to show you — and the action is graded destructive for precisely that reason. escalation:write without escalation:read cannot list the policy it is about to replace. evals:write without evals:read can replace a sampling rule or a budget it never saw, and setting a rate to zero turns automatic evaluation off. If an agent should be able to undo its own edits, give it the read.

A content scope, only when verbatim customer content is genuinely needed. persons:profile:read (profile properties), replay:content:read (session playback and its console and network payloads) and agents:content:read (prompts, completions, tool arguments, reasoning transcripts) each name recorded content rather than a summary of it. The investigate bundle grants all three, because that detail is what makes an investigation possible — if an agent should not see it, name scopes individually instead of taking the bundle. traces:read, logs:read and metrics:read used to be second routes to model prompts and completions recorded as attributes by third-party instrumentation, and are not any more: those attributes are withheld from a credential without agents:content:read — on spans, on log records (including the live tail) and on metric exemplars — and the response comes back carrying an anectico.content.withheld attribute naming what was removed. An agent with the signal read scopes and no content scope reads latency, status, token counts and log messages, never model bodies.

Your project's content policy can withhold the same bodies from an agent that does hold agents:content:read. Those responses carry anectico.content.policy_withheld instead, and the difference matters to whoever is debugging: the first is fixed by minting a key with the content scope, the second only by changing the project's policy. One more thing to know before you blame a key: a content policy belongs to a project, so a read that does not name one — the MCP trace and log searches on an organization-scoped key, or an API call without project_id — comes back without content for that reason alone. Name the project and the bodies return.

A delete scope, one at a time and never by reflex. --scope logs:delete, --scope traces:delete, --scope dashboard:delete, and so on. Typing it out is the point.

Nothing for the organization itself unless the job is administration. members:write, projects:write, settings:write, connections:write and api_key:write all belong to the admin privilege class. A key that investigates does not need them, and the wildcard platform-admin permission is not grantable to any key.

Narrow a session without minting a key

Adding ?profile=<name> to the endpoint URL narrows one connection. It takes tools away for that whole connection — an excluded tool is not listed and cannot be called — but it can only ever subtract from what the key's scopes already permit, and the key's authority is unchanged.

The useful case is turning a write-capable key into a read-only session:

https://app.anectico.com/mcp?profile=investigate

investigate declares no mutation at all, so a write-capable key connecting that way is served no write gateway whatsoever — an incident key drops from 49 tools to 34, and cannot invoke a mutation for the life of that connection. Reconnecting without the parameter restores everything, which is why this is a focus control and not an authorization boundary: the caller chooses it.

Watch for the side effect. investigate also excludes reads that are native to other bundles, so an incident key connected this way loses get_incident, list_incidents and the on-call and delivery reads too, despite holding their scopes. For a genuinely narrower authority, mint a narrower key; see How agent access is enforced for exactly where that line falls.

Support contact facts

Read and recover selectively recorded contacts with errors:read and persons:read. Recording also requires errors:write; withdrawal also requires errors:delete. MCP requires mcp:read and, for either mutation, mcp:write. Preview, confirmed apply and recovery all require the same current grants. Use a scoped write credential and explicit user approval. See the contact guide.

Read one support requester

Use an OAuth read credential or a scoped read key with persons:read. Add errors:read, traces:read and replay:read only for the evidence sources needed; complaint selection requires errors:read. MCP also needs mcp:read. get_support_story through execute_read_action, and native support story, share the same source coverage. Follow-up content retains its separate permission and current project policy. No write scope or support-provider credential is needed.

Optional issue-impact support evidence uses the same two read grants. get_error_impact requires errors:read and MCP mcp:read; add persons:read for include_support_contacts=true. Without it the support block is withheld and baseline impact remains available. This is a read, with no complaint-write permission or approval.

Recorded support and subject export

Keep the existing read credential for investigation. Select an explicitly scoped API key for an approved record (errors:write, errors:read, persons:read) or withdrawal (errors:delete, errors:read, persons:read). MCP adds mcp:read and mcp:write; preview and recovery have the same current grants. Subject export additionally uses persons:export; inclusion of recorded support facts needs both reads. These are selected steps, never blanket grants to a triage or weekly-review session. See the bridge guide.