Skip to content
Console
Browse documentation
Guide

Run an agent end to end

Take an AI agent from no credential to a confirmed change, from a terminal and the agent itself, and open the proof.

On this page

This is the whole loop — connect, discover, investigate, act, check the proof. You mint a credential from the terminal, and the agent finds its own way around from two entry-point tools. The only pages you open are a sign-in page and the proof pages that the agent's links lead to. For a shorter first run that also sends a test customer, see Quickstart.

One browser step is needed and it is a sign-in page rather than the Console: anectico login runs a device-code flow. You can skip even that by exporting an existing key as ANECTICO_API_KEY — but it must hold api_key:write and every scope you are about to grant, because a key can never mint a scope its creator lacks. Signing in is simpler precisely because your org role supplies them.

That first anectico login is also the explicit provisioning and linking step required before a direct OAuth MCP connection can represent you. An OAuth access token alone never creates an Anectico organization or membership. If you are joining someone else's organization, have an owner invite your address with anectico invitations create person@example.com --role ROLE_MEMBER, then accept that invitation after signing in; this still requires no visit to the Console.

1. Mint the agent a credential

anectico login
anectico projects list
anectico agent bootstrap --project <project-id> --host claude

anectico agent bootstrap mints a narrow, project-scoped, expiring key, stores the secret in your OS keychain, merges the Anectico server into the host's MCP configuration, and connects with the new key, exactly as the host will, to check what it can see. --host is required and accepts claude, codex, cursor, gemini or muse. See MCP client compatibility for what each host needs.

By default it grants the investigate bundle — 34 scopes for investigation, model costs and stored evaluation scores; no customer configuration changes or paid evaluation execution — and expires in 30 days. Every one of those 31 is a scope an ordinary member holds, so this step needs no special privilege. A viewer cannot run it: minting a key is itself privileged, and the refusal arrives before the scope list is read.

2. Put the key where the agent will read it

Claude Code asks the CLI for the key each time it connects, so there is nothing to do. Codex, Cursor, Gemini CLI and Muse Code read it from the ANECTICO_API_KEY environment variable: the first bootstrap run ends with exit code 3 and the status needs_environment until the variable is set in the shell that starts the host. The configuration only refers to the variable, so the file stays safe to commit.

unset ANECTICO_API_KEY && \
anectico_agent_export=$(anectico agent key env --export) && \
eval "$anectico_agent_export" && \
unset anectico_agent_export && \
anectico agent doctor --host codex

doctor confirms, from this shell, that the host can use the setup. Start the host from the same shell: for Codex that is codex, and for Cursor cursor ..

3. Confirm the connection without invoking a tool

anectico mcp verify

It identifies the server over the current protocol and reports which discovery path answered. A key that authenticates but sees zero tools is a failure, not a quiet success: mcp:read on its own is served an empty tool list, because every tool also requires the scope of the domain it reads.

4. The agent's first two moves

Two tools are the way in:

  • search takes one query and looks across people, error issues, log lines, business accounts, and documentation in a single call.
  • fetch takes one reference from a search hit — or from any tool's evidence array — and returns the object it names.
{"name": "search", "arguments": {"query": "user_8842", "since": "24h"}}

The answer is a list of hits and a per-source report. Each hit carries ref (a canonical anectico://… reference), kind, fetchable, and tool — the specialised tool that produced it and the place to go for real filters. Each source reports searched, unauthorized (with the scope that was missing), out_of_profile, not_requested, or failed, so an empty answer is never ambiguous: the agent can tell "there is nothing there" from "this key may not look".

{"name": "fetch", "arguments": {"ref": "anectico://person/1f0c…"}}

fetch resolves references of kind person, error_group (an issue), trace, incident, agent_run, account, and doc, and returns exactly what that object's own read tool returns. The reference is its only argument — it already carries the project when the object needs one. Holding a reference grants nothing: every fetch is authorized against the key exactly as the original read was.

Only a hit marked fetchable: true can be passed to fetch — check the flag rather than assuming, because a cited reference is not automatically a fetchable one. A log line is the case an agent meets first: it is a search source and it is cited everywhere, but it has no single-object read. The refusal says what to do instead, per kind:

fetch cannot resolve a "log" reference. A log line has no single-object read:
find it with search_logs, or fetch the trace its citation carries.

Traces are deliberately not a search source. They are found by filter (search_traces) and by pivot — a log hit carries its trace reference, and fetch resolves it.

5. Go deep with the specialised tool the answer named

Read the instructions before choosing an action

The default investigate key includes docs:read. The agent can look up the supported procedure without leaving MCP or guessing a command:

{"name": "search", "arguments": {"query": "identify customers", "sources": ["docs"]}}

Pass a returned documentation hit's ref to fetch. For documentation-specific search, discover search_docs with list_read_actions and invoke it through the read gateway:

{"name": "execute_read_action", "arguments": {"action": "search_docs", "arguments": {"query": "identify customers", "limit": 5}}}

For a known page, use the same gateway:

{"name": "execute_read_action", "arguments": {"action": "get_doc", "arguments": {"slug": "instrument/identity"}}}

The Markdown body of a documentation response is capped at 48 KiB; its metadata and full outline are additional. If truncated is true, inspect outline, then call the same action with heading inside the inner arguments object, using an H2–H6 heading or anchor from that outline. The outer arguments is the MCP tool-call payload; the inner arguments holds the selected read action's parameters. Neither layer is named args. The omitted text is not summarized. See Machine-readable documentation for public Markdown, manifests, and retrieval examples.

Follow the evidence

search and fetch add no query power of their own. Once the agent knows what it is looking at, it uses the tool the hit named, with that tool's filters:

{"name": "get_person_timeline", "arguments": {"id_param": "buyer@acme.example", "since": "24h"}}
{"name": "search_logs", "arguments": {"level": "error", "trace_id": "4bf92f35…", "since": "1h"}}
{"name": "get_issue", "arguments": {"group_id": "grp_…"}}
{"name": "get_affected_users", "arguments": {"group_id": "grp_…"}}

Every result carries an evidence array of citations, each with a ref and RFC 6901 pointers into the data it supports, so the agent can quote a specific row rather than the whole answer — and you can fetch anything it quoted.

Open the proof

When a result is about one person, issue, trace, agent run, incident, dashboard, replay or analytics result, it also carries a link in its url field. Open it to see exactly what the answer claims, in a read-only page that names its project. A list result carries one link on each row. The agent should hand you the link with its conclusion. See Proof pages.

Administrative reads — on-call schedules, delivery receipts, ticket links, account lookup, product and export definitions, plan usage, LLM cost — are not first-class tools. Call list_read_actions with no arguments to browse them by domain, pass a domain or query to get each one's argument schema, then run it with execute_read_action. Both are read-only.

Connect the application you want to investigate

Connecting the agent gives it read access to Anectico; the application still needs instrumentation. Ask the agent to follow Quickstart, identify a test customer, and record one recognizable error. Give the app two separate keys: a native_ingest key with only ingest:write for telemetry (configured as ANECTICO_INGEST_KEY in local development) and a server_capture key with only analytics:write for product events and customer identity (configured as ANECTICO_CAPTURE_API_KEY; a browser uses browser_capture and a mobile app mobile_capture). Never put the agent key in the app.

An administrator can create these keys in the Console under Agents and keys, or in the setup guide at /get-started. An authorized human can also create them with anectico apikey create --help as the command guide. The read-only agent cannot mint them. An agent that you gave a management API key holding mcp:write, api_key:write and the scope of each key's purpose can prepare them when you ask, and creates a key only after you approve its complete preview; see Authentication and API keys. Verify the sample with the instrumentation_doctor read action or CLI service and mobile check, and require the actual customer and issue links. An export response or a working MCP connection is not completion.

6. Mint a second key, this one able to act

An investigate key cannot mutate anything — it holds no mcp:write, so no write tool is served to it at all. Resolving an issue needs four scopes: mcp:read and errors:read to see the issue and its current version, mcp:write and errors:write to change it.

You must be an owner or admin to do this. mcp:write is admin-granted, and a key can never carry a scope its creator lacks, so a member's mint is refused by name.

Name those four scopes and nothing else. --scope-profile "" is the part to get right: omit it and the bundle default applies, and you quietly mint a second read-only investigate key that cannot do the job either.

anectico agent bootstrap --project <project-id> --host claude \
  --scope-profile "" \
  --scope mcp:read --scope mcp:write \
  --scope errors:read --scope errors:write

That reports Scopes: 4 and the tools the new key can see. It stores the new key for the profile in place of the read-only one. For a host that reads the environment, replace the variable the same way as in step 2:

eval "$(anectico agent key env --export)"

This intentionally minimal write key cannot read documentation. Add --scope docs:read to the bootstrap command for a five-scope key that can look up procedures itself, or use the public Markdown documentation without credentials.

Then restart the agent, or reconnect the server in it. The tool list is decided by the credential that authenticated, and a host that connected with the read-only key holds a read-only tool list until it connects again. This is the step people skip, and its symptom is "the server does not support writes" from a key that supports writes perfectly well.

With the write-capable key connected, the agent discovers mutations through list_write_actions and runs one through the door its reach decides: execute_internal_action for a change that stops inside your organization, execute_external_action for one that also causes something Anectico cannot retract.

{"name": "list_write_actions", "arguments": {"domain": "errors", "destructive": true}}

A few daily-driver mutations are promoted to their own tools so a host can tell an acknowledgement from a delete. Resolving an issue is one of them, and it previews first:

{"name": "set_issue_status",
 "arguments": {"group_id": "grp_…", "action": "resolve",
               "expected_version": 7, "note": "fixed in 4.2.1"}}

The first call applies nothing. It returns a preview of what would change plus a confirm_token. Repeat the identical call with that token to apply it:

{"name": "set_issue_status",
 "arguments": {"group_id": "grp_…", "action": "resolve",
               "expected_version": 7, "note": "fixed in 4.2.1",
               "confirm_token": "…"}}

The token binds the organization, the caller, the tool and the exact arguments previewed, and lasts 10 minutes. Change one argument and it stops matching — preview again.

Read the preview before confirming. It is the last place some information exists: resolving an issue replaces the whole lifecycle overlay and a later call reverses the status only, so the resolution note, resolver, release baseline and regression state are named in the preview and nowhere afterwards. Resolving also reaches outside Anectico — it closes the linked ticket in your own tracker.

A committed write returns a receipt: the operation, the outcome, what changed, and the targets the platform confirmed — plus effect_scope and destructive, which describe the action's possible reach and restoration limits. External scope alone does not prove that a message or update was delivered. It carries a mutation id and a commit time when the platform reports them, and null when it does not; null there means "re-read to find out", not "nothing happened".

7. Verify the loop

anectico issues list --status resolved

The issue is now resolved, its version has advanced, and the note you passed is on it. Ask the agent for the issue's link and open the issue proof page to see the same status. The same change is in the audit trail, in the Console under Audit log (/audit-log) and through anectico audit list, naming the tool, the resource and the outcome — including the preview that preceded it.

If the loop stopped somewhere, anectico mcp verify identifies the server and confirms the current key reaches it; and remember that a key that authenticates but sees zero tools is a scope problem, never a server problem.

Where to go next

Resume a saved first-application setup

An MCP agent can read the project's saved setup draft with the get_onboarding_setup read action. It requires mcp:read and settings:read and is available in the investigate and admin profiles (incident inherits investigate). Newly minted investigate and incident CLI profiles include settings:read; existing keys keep their original scopes. If an existing key lacks it, an authorized administrator must mint a replacement with that scope. This scope also permits the other settings reads.

{"name":"execute_read_action","arguments":{"action":"get_onboarding_setup","arguments":{"project_id":"<project-id>"}}}

The response's data.setup contains host, stack, step, person, error_message, event_name, trace_id, started_at and updated_at. No draft returns not_found; a saved draft that is no longer valid returns an error. A saved step is not proof of completion: pass its test identifiers to instrumentation_doctor and check journey_verified.

The CLI equivalent is anectico onboarding-setup get --project '<project-id>'. To save a revised draft, use the update_onboarding_setup MCP action or the anectico onboarding-setup set command with the complete draft: host (claude, codex, cli or manual), stack (node, browser, python, go, otlp or mobile), step (0 to 3), the three test identifiers, trace_id and started_at. The draft replaces the saved one entirely and nothing else can be stored. These writes require settings:write; MCP also requires mcp:write and preview and confirmation.

Continue investigating