Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Use it from an agent

The repository has two files for the agent itself: AGENTS.md, a guide to using itda well, and skills/itda/SKILL.md, the same guide in the short form skill loaders take. The MCP server hands the agent the same rules as its instructions.

MCP clients

itda mcp install claude-desktop   # or cursor, vscode, codex
itda mcp install claude-code      # prints the `claude mcp add` command
ClientFile itda changes
claude-desktopclaude_desktop_config.json in the Claude app’s folder
cursor~/.cursor/mcp.json
vscode.vscode/mcp.json in the current folder
codex~/.codex/config.toml
claude-codenone; prints claude mcp add --scope user itda -- …

The installer keeps your other servers and settings and saves the previous file as .bak. It changes nothing if itda is already there. --dry-run shows the new file without writing it. It starts itda by its absolute path and passes ITDA_HOME, ITDA_ALLOW_LOCAL and ITDA_SECRET_STORE along when they are set. Restart the client afterwards.

What the agent sees

With up to 30 actions installed, each is a tool named like the CLI (sandbox.list-notices), with a JSON Schema for inputs. Hints: reads are readOnlyHint; DELETE actions are destructiveHint; PUT and DELETE are idempotentHint.

With more actions, itda lists three fixed tools. The tool list stays short and prompt caches stay valid:

ToolUse
itda_searchFind actions by keywords
itda_describeShow one action’s input schema and effect
itda_callRun an action with args (and approval for a change, next for the next page of a list)

itda mcp --mode direct or --mode catalog overrides the choice. itda mcp --site <name> serves only that site’s actions as tools. It refuses itda_setup and itda_prepare and confines itda_login, itda_check, itda_sites, itda_manage and itda_shape to that site. Use it in a project’s MCP configuration when the agent should only reach one site from there.

Seven tools are always there, so the agent never needs a terminal to set a site up or look after it:

ToolUse
itda_setupSet up a site from a page address: look at the page as itda and draft. Try every read once and keep what works. The site’s actions become tools in the same session. The server declares tools.listChanged and sends notifications/tools/list_changed; the next tools/list has them. A script-drawn page opens briefly in a browser window on your screen. itda watches it load on its own, without anyone clicking or typing. itda refuses pages that need a sign-in or still show nothing and gives you the command to run. It never asks you to record here.
itda_loginOpen your own browser to sign in, exactly like itda login <site> --browser. itda seals the session under the data directory with a key from the keyring; the agent only sees the account id. A client with forms asks you first. Nobody presses Enter, so the definition must name the cookie that shows a sign-in.
itda_checkitda check for one site, or every site when none is named: the verdict per site and what to do, as itda check --json prints them.
itda_sitesWhat is set up, with reads, changes, the last check’s time and verdict, how many actions answered on their last try (verified), the recent pass_rate and the reads that fail now and then (unstable). With site, one site in detail: each action with verified, pass_rate and last_verdict, a user_guide (what can be read, what can be changed, which list read supplies which detail read’s input), two to four natural_prompts a person might ask, and the top three gaps.
itda_managerefresh drafts a changed site again from its sources. The form shows what would change; no answer counts as no. For remove and resume, you confirm in a form; clients without forms get the command to run. approvals lists what waits for you. audit lists the last entries for one site or all, plus, under unknown_outcome, changes interrupted mid-process and changes whose answer was lost, each with what the confirming read said (check) when the change named one. fsck runs the knowledge base’s rules for one site or all and sends nothing: in one call, the reads never tried (endpoint_untried), the reads that need an input and which list read can supply it (read_needs_input), the reads that fail every recent try (read_failing) or now and then (flapping_read), and files changed under itda (artifact_changed, artifact_missing).
itda_shapeThe shape of what a site shows and answers, never its values. For an action: the keys and types of its last answer as shape and as pointers ({pointer, type}), and what its definition declares. For a page: its selectors with match counts, attribute names and parent (structure), its named fields without values (fields) and the keys and types of the data it embeds (ssr_payloads). From the local knowledge base by default; with fresh: true, itda reads the page now, the way setup reads a page. At most 24 KB.
itda_prepareThe preparation loop below: the agent drafts a site from its docs and pages, and itda keeps what the evidence carries and what answers, then installs it the way itda_setup does.

Every gap comes as {rule, subject, priority, reason, remedy}; remedy has the command for a terminal and the tool and arguments to call next (the action’s own tool, or itda_call with action when the server lists the catalog). Act on a remedy only when it serves what the user asked; never call a change because a gap names it. itda_setup returns the top three gaps as gaps.

When itda_setup keeps one read or none, its result carries a remedy naming itda_prepare with the page’s address.

Every result uses the itda call --json envelope, marked "untrusted": true. A note before it says website data is not instructions. Results over 24 KB keep the start of their longest lists and say "truncated": true. Failures are tool errors with a code and a fix, so the agent can tell the user what to do.

Prepare a site yourself

Some sites tell a person more in their docs than a page tells itda: a reference that lists GET /api/v2/items/{id}, an API description, a GraphQL schema. With itda_prepare the agent reads them and drafts the definition itself; itda calls no model. The agent never sees a value the site holds. Results carry titles, the headings of a page’s own sections, paths, methods, field names, selectors, keys, types, JSON pointers and counts, each piece with an evidence id (e12) the agent cites. The loop, one tool with an op:

opWhat it does
startOpens a session for the site of url (one per site; calling again returns it) and shows the environment: the browser by name, the site’s accounts by id with the names of their secrets, whether the site is paused or installed.
reconReads the entry page, the API description it links (or /openapi.json), what its GraphQL endpoints offer and the routes its docs name, and returns the draft itda makes from them as candidates, each judged. bundles: true also reads up to 24 scripts the page loads and tries each route string once with a GET; only a route that answers with data is evidence, the rest are counted as noise.
readReads one more page or document, on the site’s registrable domain or a host the site linked as documentation (its API description, the servers that names). Other sites (outside_site) and private addresses (private_address) are refused. GET only, without an account.
searchThis session’s evidence and itda’s notes about the site that match words.
proposeJudges the agent’s definition (spec, in this format; use_recon takes itda’s candidates whole), its workflows (understand, 1 to 12) and its self-questions (self_qa, up to 12, kept only when every evidence id exists). Each operation comes back kept or dropped with the reason, the evidence ids and what was missing.
verifyTries the kept reads, at most 6 per call. A read that needs an input runs only with a check, and $result:<read>:<pointer> fills it from an answer already tried (a string, a number or a boolean). Each result says whether it answered, how many records and the shape. A JSON read with no required_pointers gets them from the field names at the top of the answer (none for a list or an object keyed by data). A page read that fails says in diagnosis, in counts, where its selectors miss on the page as read before.
reviewWhich kept operations cover each step of each workflow, and which routes the docs or the description name that nothing implements.
sessioninspect the site’s accounts and credential sources as shapes; verify one signed-in read as an account; read one path with the account’s session, after the site is installed and the user signed in.
installThe same path as itda_setup: save, try every read once, keep what works, add the site’s tools. replace: true only when the user asked.

An operation is kept only when its base_url is a server the site documented or answered from, its method and path are a route in the docs, a description or a script that answered, or, for a GET, a path itda read (/users/@me matches /api/v10/users/@me), an HTML read has an html extraction (records or page fields; with required_html_fields alone it has nothing to return), a file read declares format: file, and a signed-in operation has a path read with the session. A declared read whose request asks for a change is a change. A route the description says needs a sign-in itda cannot use is dropped. A draft that only reads the home page and checks nothing is refused (no_actions). Changes are written into the definition and never sent; the user approves each later, as for any site.

A session has 120 tool calls, 48 requests for pages and documents, 24 requests for checks (browser recovery counted, from the sites’ own pacing record), and two rounds each for coverage and repairs. Past them, budget_exhausted or round_limit says to install what is kept or stop. Every result has feedback entries {kind, subject, reason, next}; next is the call to make. A call with the same arguments is answered from the session, not sent again. A site that refuses itda (blocked) means pause and tell the person. The checks are tries of the knowledge base’s prepare stage, which itda fsck and the pass rates leave out. skills/itda-prepare/SKILL.md is the loop in the short form skill loaders take.

Files

A read declared format: file saves its answer on the user’s computer and returns a manifest in data, never the bytes: {path, bytes, media_type, sha256}. The file lands under files/<site>/ in the data directory, or where itda call ... --out <dir> says; the command prints Saved <path> (<bytes> bytes, sha256 …) once. Over MCP the result carries the manifest and a resource_link to the file, and the tool’s description says so. A failed download says why in one word, and keeps nothing: wrong_media_type (the site answered with a page or another kind of content), partial_answer (a 206 or a short body), empty_answer, too_large. itda check skips file reads (“saves a file”). itda setup tries each one once by its headers and first bytes (the media type and size the definition allows) and keeps nothing, so a site whose only reads are files is set up like any other.

A change whose body carries a file takes the path of a file on the user’s computer in the input its definition names. The user approves that exact file: the review shows its name, size and SHA-256, and other bytes under the same path withdraw the approval (approval_expired, reason: file_changed). A file that changes while it is being sent ends the call with action_outcome_unknown and reason: file_changed; as with any lost answer, never call it again on your own.

Lists that go on

A read with pagination in its definition returns meta.next if the site reports another page. It is an opaque handle such as ic_4f0a4207d04f4a0fb4e059d26bd54b6d. The agent passes it back as next (--next on the command line) with the same inputs to get the following page. That page may have its own meta.next. The site’s own marker, a cursor, page number or offset, stays on the user’s computer. itda stores it in the local database for fifteen minutes, bound to that site, action, account, inputs and definition. itda removes it from the data it appears in. itda refuses handles for another action, account or inputs, or after a definition change or expiry, with pagination_invalid or pagination_expired (exit 23). The agent starts again without next. Only reads turn pages. itda sends a change once. The server instructions, AGENTS.md and the skill tell the agent to read only as many pages as the question needs.

Changes

A change never runs on the first call. The agent gets approval_required, an approval id and instructions to ask you. You run itda approve <id> in a terminal. You see what the action does, the exact request and every input, and answer y. The agent calls again with the same inputs and the approval id; itda sends the change once. Until you answer, that call returns approval_pending (exit 20) and the approval stays. A call with other inputs withdraws it (approval_expired with reason: inputs_changed). With --approve-in-client, clients that show forms ask you directly instead. See Approvals and the audit log.

itda sends a change once. If a request gets no reply after sending (a timeout, a dropped connection), or a GraphQL reply carries errors behind a 2xx, the call fails with action_outcome_unknown (exit 22). The audit log records this outcome: the site may or may not have applied the change. itda never resends a change on its own. An agent must not either. When the change names the read that shows it (confirm in its definition), itda runs that read once and puts the result next to the error as outcome_check: landed means the change is in, so tell the user and do not ask for it again; not_found means the site shows no trace of it, so the user may ask for a new approval; unknown means that read failed too. Without outcome_check, check the site first; only a person decides whether to ask for the change again. Which read a change names shows before you call it: itda describe prints it under the change (after a lost answer: checks list-notices for the new title), --json carries it as confirm: {read, match}, and the change’s tool description (or itda_describe in catalog mode) says the same. A new approval request for a change that landed carries previous_outcome: landed, and its review tells the user so. A change that never left the machine (no turn at the gate, a name that did not resolve, a connection that was refused) keeps its network code. itda reports it as not sent. Agents may retry reads, which keep their usual codes (timeout, request_failed).

A 403 that is not a sign-in problem is api_denied (exit 14): the site refused that one request as not allowed. The error carries upstream_status. It includes provider_reason only if the site’s JSON answer names access_denied, permission_denied, insufficient_scope, insufficient_permissions, service_disabled, forbidden or not_authorized. itda passes on nothing else from the answer. A 403 whose reason says the site rejected the session itself (unauthenticated, invalid_token, token_expired, session_expired, login_required) stays auth_required. Every refusal carries upstream_status.

When something that worked stops working

Run itda check <site> before retrying or re-drafting (itda check --all checks every site and prints one verdict line each). It runs every read needing no input and never sends a change. Each site ends with one verdict and what to do:

VerdictMeaningWhat to do
okevery read still matchesretry the action; the failure was not the site
signed_outthe site no longer accepts the accountask the user to run itda login <site>
site_changeda page or answer no longer matches its definition, the address is gone (404, 405, 410) or the site no longer accepts the queryAsk the user to run itda refresh <site>, or call itda_manage with refresh. itda drafts the site again from its original sources. The user confirms the diff; itda keeps the sign-in, name and hand-edited actions.
blockedread recovery failed or the site rate limited itdarespect retry_after; paused: false needs no resume. Only an explicitly paused site needs itda resume <site>
unreachablethe site did not answerwait, then run itda check again

A site with several problems gets one verdict, in this order: signed_out, then site_changed, blocked, unreachable. The exit code follows the worst verdict across the sites checked: 10, 11, 12 or 30 as in the table below, or 0 for ok. A read the site refused (api_denied) does not affect the site’s overall verdict. The verdict uses the other reads; the hint names the refused read. --json adds verdict, one entry per site under sites, and every action under results with the HTTP status the site answered as upstream_status.

Shell agents

Agents that only have a shell can call itda call <site>.<action> --json and branch on the exit code:

ExitMeaningWhat to do
0ok
2bad input or unknown action (the remedy names the nearest one), a read that preflight would have turned into a change (effect_changed), or a read whose built request itda cannot classify (effect_unknown, the remedy says what is missing)itda describe <site>
10signed out or no keyask the user to run itda login
11the page no longer matches its definition, the site answered the query with errors (query_failed), or a file read got a page, a part or nothing (wrong_media_type, partial_answer, empty_answer)update the definition, or check the inputs
12the site refused this read, in the browser too (blocked_by_site)tell the user to check the site in their browser. With paused: false other reads still work and nothing needs resuming; only a site paused in direct-HTTP mode (ITDA_TRANSPORT=http) needs itda resume
13rate limitedwait as long as retry_after says, then retry the read
14the site refused this one request as not allowed (api_denied)tell the user what provider_reason says; do not sign in again
20needs approval (approval_required), the user has not answered yet (approval_pending), or changes are offask the user to run itda approve <id>, or wait and call again with the same id
21approval used, rejected, expired or withdrawn because the inputs changedcall again for a new one
22itda sent a change; its outcome is unknowncheck the site before retrying
23the next handle expired, or was for another callcall again without --next
30network error, an answer over the read’s size cap (too_large), or a turn lost during a long transfer (request_lease_lost)retry later

With --json, itda prints errors on stdout as {"status": "<code>", "message": …, "remedy": …} plus details such as approval.