> ## Documentation Index
> Fetch the complete documentation index at: https://velt.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Review Agents

> Build review agents for your product that review web pages, data, charts, and anything else you can surface via API or MCP, then create findings as comment annotations.

## What are review agents?

Build review agents for your product. Point an agent at a URL, and it reviews the content and posts findings as comment annotations.

Review agents can review anything you can surface:

* **Web pages and sites**: text, screenshots, HTML, CSS, links, accessibility tree, Lighthouse.
* **Your data**: pull any REST endpoint into the review with the `rest-api` strategy.
* **Charts, dashboards, and more**: anything you can expose via an API or MCP server.

You write a prompt and pick a few config options. The platform handles context gathering, LLM invocation, post-processing, deduplication, and annotation creation.

You can also put agent creation in your users' hands: ship the [built-in agents](#built-in-agents) as defaults, and let users create custom agents in plain English from your UI. The [prompt tools](https://velt.dev/docs/api-reference/rest-apis/v2/agents/prompt/enhance.md) turn a one-line instruction into a production agent config.

## What you get

* **Built-in and custom agents.** Ready-made agents (Proofreader, Link Checker, Image Inspector, Mobile Inspector, Consistency Checker, PII, Lighthouse, accessibility, [and more](#built-in-agents)), or your own from a prompt.

* **Plain-English agent builder.** Let your users describe a review in simple English; prompt tools ([enhance](https://velt.dev/docs/api-reference/rest-apis/v2/agents/prompt/enhance.md), [validate](https://velt.dev/docs/api-reference/rest-apis/v2/agents/prompt/validate.md), [refine](https://velt.dev/docs/api-reference/rest-apis/v2/agents/prompt/refine.md)) check it, expand it into a full agent config, and iterate on feedback. `userContextFields` render typed inputs in your setup UI.

* **Pluggable context gathering.** Stack strategies: page text, screenshots, HTML, CSS, links, accessibility tree, computed styles, robots.txt, sitemap, Lighthouse, live REST API data.

* **Live REST API context.** The `rest-api` strategy fetches your endpoints at execution time and injects the responses into the prompt. Secrets are encrypted at rest and redacted on read.

* **MCP tool use.** The `mcp-tools` strategy runs a multi-turn tool loop against your remote [MCP](https://modelcontextprotocol.io) servers. Works with Claude and Gemini.

* **Versioned configurations.** Every behavioral edit creates a new version; one-click restore rolls back.

* **Async execution.** `Run Execution` returns an `executionId` immediately; poll `Get Execution` until `status !== "running"`.

* **Cross-page execution.** Set `crossPageExecute: true` to crawl the seed URL and review up to `maxUrlsToProcess` pages.

* **Page lists.** Send `urls` to review exactly those pages, with no crawl. Use it for sites whose pages differ only by a query string.

* **Several agents, one request.** Send `agentIds` to run up to 10 agents together, on one page or on a list of pages. Each agent still gets its own execution, and each page is loaded once for all of them.

* **Focused rechecks.** Set `userContext.focusIssueTypes` to recheck only some [issue types](#issue-types), for example only blurry images.

* **Per-run options.** Switch individual checks of a built-in agent off, or tune its thresholds, for one run. See [Per-run options](#per-run-options).

* **Device emulation.** Run each execution as `"mobile"` or `"desktop"`.

* **Re-run deduplication.** Re-running an agent replaces the prior run's suggestions instead of piling up duplicates. A focused recheck replaces only the suggestions of the issue types it rechecks.

* **Token usage analytics.** Per-agent, per-model, per-month token usage via the Analytics endpoint.

* **Agent groups.** Bundle related agents (e.g. "Brand QA") and filter lists by group.

## Use cases

> [card] Brand consistency
>
> Verify brand colors, typography, and logo placement across your marketing pages. Re-run on every deploy.

> [card] Pre-launch QA
>
> Run the Proofreader, Link Checker, and accessibility agents before a release. Findings land on the staging document.

> [card] Content moderation
>
> Flag PII and profanity on user-generated pages. Pair with Review Workflow Builder for human review.

> [card] Cross-page audit
>
> Set `crossPageExecute: true` and the crawler discovers internal links, then reviews each page.

> [card] Data-enriched checks
>
> Pull live business data into the prompt with `rest-api`, e.g. validate on-page pricing against your billing API.

> [card] Workflow integration
>
> Trigger an agent from a Review Workflow Builder workflow node and park the workflow on its findings.

> [card] User-built agents
>
> Let your users create review agents in plain English from your UI. Ship built-in agents as defaults; prompt tools turn user instructions into custom ones.

> [card] Docs accuracy
>
> Use `mcp-tools` to verify on-page code snippets live against your documentation MCP server.

## How it works

1. **Define the agent.** Call [Create Agent](https://velt.dev/docs/api-reference/rest-apis/v2/agents/create.md) with a name, instructions, and config (context gathering, execution strategy, post-processing).
2. **Run an execution.** Call [Run Execution](https://velt.dev/docs/api-reference/rest-apis/v2/agents/execution/run.md) with `agentId` and `url`, or with `agentIds` to run several agents on the same pages. Returns an `executionId` per agent immediately.
3. **Poll for results.** Call [Get Execution](https://velt.dev/docs/api-reference/rest-apis/v2/agents/execution/get.md) until `status !== "running"`. Set `includeResults: true` for per-URL findings.
4. **Findings appear as annotations.** Each finding becomes a comment annotation on the document referenced by `organizationId` / `documentId` (on by default).

## Mental model

| Concept | Meaning |
| - | - |
| **Agent** | Reusable review configuration: identity (`name`, `description`, `enabled`) plus behavior (instructions, context gathering, execution, post-processing). Behavioral edits create a new version. |
| **Execution** | One run of an agent against a seed URL. Pins the agent `version` at dispatch, so in-flight runs ignore mid-run config changes. |
| **Finding** | One issue on one URL: severity, category, target text, suggestion, HTML selector, confidence. Guardrails deduplicate and sanitize findings before annotations are created. |

**Execution lifecycle:**

```
running → passed | failed | partial | error | skipped
```

## Pipeline phases

Each agent run executes sequential phases:

| Phase | What happens |
| - | - |
| `validate` | Zod check on payload + input requirements + variable keys |
| `extract` | All configured context gathering strategies run |
| `execute` | LLM call (or registered service); results normalized to a finding array |
| `postProcess` | Guardrails → delete previous suggestions → pin resolution → annotation creation → analytics |
| `structureResponse` | Final response assembly with optional response adapter |

## Execution statuses

| Status | Meaning |
| - | - |
| `running` | Execution is in progress |
| `passed` | Completed successfully: all URLs processed cleanly, **no findings** |
| `failed` | Completed with **findings**: all URLs processed cleanly |
| `partial` | Mixed outcome: at least one URL succeeded and at least one URL failed ("passed with some failures") |
| `error` | Every processed URL failed, or a fatal crawl/dispatch failure; nothing usable produced |
| `skipped` | Execution was skipped (e.g. a precondition was not met) |

**Terminal status precedence:** `error` > `partial` > `failed` > `passed`. A run that produced findings but had a single failing page surfaces as `partial` (not `error`). For `partial`/`error`, per-page failure detail is in `resultsSummary.urlsErrored` and `resultsSummary.erroredUrls`.

## Built-in agents

Built-in agents are pre-registered for every workspace. Run one by its ID.

| Agent ID | Name | Description |
| - | - | - |
| `spell-check` | Proofreader | Typos, doubled words ("the the"), punctuation slips (",," or a space before a full stop), brand names written with the wrong casing, a term cased two ways on one page, and leftover placeholder text such as lorem ipsum or "Insert headline here". Accepts British spellings and skips spelling on pages not written in English. It does not check grammar: use `grammar-check`. `aiConfig` does not apply to it. |
| `grammar-check` | Grammar Check | Grammar checking |
| `broken-links` | Link Checker | Every link, button, image, and form on the page: broken links and images, form submits that fail, buttons and links that do nothing when clicked, links to staging, preview, or local hosts, malformed links, a header logo not linked to the home page, phone numbers and emails that are not links, social icons that point at the wrong network, and links that open in the wrong kind of tab. |
| `image-inspector` | Image Inspector | Images that do not show, blurry (upscaled) or stretched images, CSS background images included, empty or placeholder image slots, and images without alt text. An optional check for badly cropped photos (a head cut off) sends screenshots of the photos to an AI model, and is off unless you turn it on: see [Image Inspector](#image-inspector). |
| `mobile-inspector` | Mobile Inspector | Opens the page at phone width (375 px by default) and tablet width (768 px), and flags a desktop layout shrunk to fit, sideways scrolling, content that runs off the screen, cut-off buttons and text, tap targets that are too small, button labels that wrap, content hidden under sticky bars, a menu button that opens nothing, and links or headings shown on desktop that a phone visitor cannot reach, with phone-width screenshots. To test the menu and sticky bars it taps the menu button and up to 2 same-page links: switch either off with [`skipChecks`](#mobile-inspector). Always runs as `"mobile"`. |
| `consistency-checker` | Consistency Checker | Compares phone numbers, addresses, opening hours, emails, prices, and service and business names on the page with other key pages of the same site (6 by default), and flags values that differ: this part uses an AI model. Also flags terms capitalized differently from the rest of the site, on English pages, and buttons and links that look or behave differently from the others on the site, without a model. |
| `ai-visibility` | AI Visibility | Scores whether AI answer engines can reach, read, understand, and correctly cite the page, with a fix for every failure. A visible date and author are asked for only on articles, such as blog posts and guides. A help page is asked for a list, table, or question heading. Home, pricing, product, collection, and landing pages, and news and press items, are not asked. See [AI Visibility](#ai-visibility) for its options. |
| `migration-parity` | Migration Parity | Compares each page with the same page on your live or old site, and flags what the new page lost: team bios, reviews, FAQ questions, phone numbers, emails, street addresses, list items such as services, a page title, and a main heading. Reworded copy is never reported. Needs `userContext.liveSiteUrl`: see [Migration Parity](#migration-parity). No AI model. |
| `content-request-list` | Content Request List | One checklist finding per page of what still waits on the client: empty sections, placeholder text and photos, "Coming soon" lines, short bios, and open comment threads that ask the client for content. See [Content Request List](#content-request-list). No AI model. |
| `pii-detection` | PII Detection | PII (personal info) detection |
| `profanity-filter` | Profanity Filter | Profanity detection |
| `sensitive-data` | Sensitive Data | Sensitive data detection |
| `lighthouse` | Lighthouse | Google Lighthouse performance/SEO/a11y audit |
| `accessibility-checker` | Accessibility Checker | Accessibility (WCAG) audit |
| `og-image-checker` | OG Image Checker | Open Graph image validation |
| `lorem-ipsum` | Lorem Ipsum | Placeholder / lorem-ipsum text detection |

When a finding comes with an exact correction, such as a corrected spelling or link, the agent puts it in `suggestedFix`. The comment annotation carries it as `agent.reason.suggestedFix`.

> [!NOTE]
>
> Display names can change between releases. Identify agents by their ID.

## Issue types

These built-in agents tag every finding with one of a fixed set of `issueType` values. Use them to filter findings, or pass some of them in `userContext.focusIssueTypes` on [Run Execution](https://velt.dev/docs/api-reference/rest-apis/v2/agents/execution/run.md) to recheck only those issues.

| Agent ID | Issue types |
| - | - |
| `spell-check` | `spelling`, `doubled-word`, `punctuation`, `placeholder`, `brand-casing`, `inconsistent-casing` |
| `broken-links` | `broken-link`, `broken-image`, `dead-button`, `dead-form`, `staging-link`, `malformed-link`, `unlinked-logo`, `unlinked-phone`, `unlinked-email`, `unlinked-contact`, `social-link-mismatch`, `same-tab-link`, `new-tab-internal-link` |
| `image-inspector` | `broken-image`, `empty-image`, `blurry-image`, `stretched-image`, `missing-alt`, `bad-crop` |
| `mobile-inspector` | `desktop-layout-on-phone`, `horizontal-scroll`, `overflowing-element`, `overflowing-text`, `cut-off-button`, `cut-off-text`, `small-tap-target`, `wrapped-button-label`, `hidden-under-sticky-bar`, `broken-mobile-menu`, `missing-on-mobile` |
| `consistency-checker` | `inconsistent-phone`, `inconsistent-address`, `inconsistent-hours`, `inconsistent-email`, `inconsistent-price`, `inconsistent-service-name`, `inconsistent-business-name`, `cross-page-casing`, `style-mismatch`, `missing-hover`, `hover-invisible` |
| `migration-parity` | `missing-bio`, `missing-review`, `missing-faq`, `missing-phone`, `missing-email`, `missing-address`, `missing-list-item`, `missing-page-title`, `missing-main-heading` |
| `content-request-list` | `content-requests` |

A focused run also skips work that cannot produce the listed issue types. A Mobile Inspector run focused on `small-tap-target` taps neither the menu nor same-page links, and a Consistency Checker run focused only on `cross-page-casing` or the visual issue types (`style-mismatch`, `missing-hover`, `hover-invisible`) makes no model call.

> [!TIP]
>
> To have the Link Checker report broken links only, run it with `userContext.focusIssueTypes` set to `["broken-link"]`. To stop it looking for a kind of problem at all, use its [per-run options](#link-checker).

## Per-run options

The built-in agents below read options from the `userContext` of [Run Execution](https://velt.dev/docs/api-reference/rest-apis/v2/agents/execution/run.md). Use them to switch a check off or tune a threshold for one run. Leave a key out to keep its default: the defaults are the agent's normal behavior. The agent ignores a value of the wrong type and applies the default. An empty string or `null` also keeps the default. `0` and `false` are values, not blanks.

Each agent reads only its own keys, so a run with `agentIds` can carry options for several agents in one `userContext`:

```JSON theme={null}
{
  "data": {
    "agentIds": ["broken-links", "spell-check"],
    "url": "https://example.com/pricing",
    "organizationId": "org_001",
    "documentId": "doc_001",
    "userContext": {
      "clickTest": false,
      "brandNames": ["AcmeCloud"],
      "skipChecks": ["placeholder"]
    }
  }
}
```

### Link Checker

Options for `broken-links`.

| Key | Type | Default | Effect |
| - | - | - | - |
| `clickTest` | boolean | `true` | Clicks links and buttons in a separate browser session to find controls that do nothing, and to tell a failing link from one the page handles itself. It blocks requests other than `GET`, `HEAD`, and `OPTIONS` and calls to analytics, advertising, and session-recording endpoints, and never clicks a control labeled as destructive or transactional. `false` skips the click test, so the run reports no `dead-button` findings. |
| `pageLinkChecks` | boolean | `true` | `false` turns off `checkLogo`, `checkContacts`, `checkSocialIcons`, and `checkTabTargets` together. |
| `checkLogo` | boolean | `true` | A header logo that does not link to the home page (`unlinked-logo`). |
| `checkContacts` | boolean | `true` | Phone numbers and emails written as plain text (`unlinked-phone`, `unlinked-email`, `unlinked-contact`). |
| `checkPhoneNumbers` | boolean | `true` | Phone numbers written as plain text (`unlinked-phone`). `false` keeps the check for plain-text emails only. Has no effect when `checkContacts` is `false`. |
| `checkSocialIcons` | boolean | `true` | Social icons that link to a different network (`social-link-mismatch`). |
| `checkTabTargets` | boolean | `true` | Links that open in the wrong kind of tab (`same-tab-link`, `new-tab-internal-link`). Any other domain is another site, even a sister brand or another domain you own, so a same-tab link to it is reported. A subdomain of the page's domain is the same site. A same-tab link whose label hands the visitor over to an app or a purchase, such as `Sign in`, `Book now`, or `Checkout`, is not reported. To count other domains as yours, use `ownDomains` or `sameNameIsOwnSite`. |
| `ownDomains` | string\[] | `[]` | Your other domains, such as a sister brand or a careers site. A same-tab link to one, or to one of its subdomains, is not reported. Host names or URLs, at most 50. Public suffixes, such as `co.uk` or `vercel.app`, and IP addresses are ignored. |
| `sameNameIsOwnSite` | boolean | `false` | `true` counts the same site name of 4 or more letters on another suffix (`brand.jobs` from `brand.com`) and the brand's status-page domain (`brandstatus.com`) as your own site. Never for government, school, or military domains. On by default before October 7, 2026. |
| `reportOwnFilesInSameTab` | boolean | `false` | `true` also reports a document on your own site, such as a PDF, a spreadsheet, or an archive, that opens in the same tab (`same-tab-link`). A text file is never reported. |
| `checkStagingLinks` | boolean | `true` | Links to staging, preview, or local hosts (`staging-link`). |
| `checkMalformedLinks` | boolean | `true` | Links written in a way that cannot work (`malformed-link`). |
| `checkImageUrls` | boolean | `true` | Image addresses (`broken-image`). |
| `checkFormActions` | boolean | `true` | Form submit endpoints (`dead-form`). |
| `checkInternalLinks` | boolean | `true` | Links to the same site. |
| `checkExternalLinks` | boolean | `true` | Links to other sites. |
| `maxLinksToCheck` | number | `500` | Most links checked per page. Whole number, clamped to 1 to 1000. |
| `stagingNoindexSignal` | boolean | `true` | A same-site `dev.`, `qa.`, or `test.` link whose page answers with a `2xx` status and an `X-Robots-Tag: noindex` header counts as a staging link. Never for a link labeled as a sign-in. `false` lets only the words in the host decide. |
| `stagingWords` | string\[] | `[]` | Words that mark a staging host wherever they appear in it, such as `beta` or `acc`, on top of the built-in ones (`staging`, `stage`, `stg`, `dev`, `preview`, `uat`, `qa`, `sandbox`, `test`, and a few more). |
| `ambiguousStagingWords` | string\[] | `[]` | Words that mark a staging host in a subdomain only next to `www` or another staging word, as `dev` does. |
| `notStagingWords` | string\[] | `[]` | Built-in staging words your site uses for something public, such as a public `preview.` subdomain. |
| `ignoreOverlaySelectors` | string\[] | `[]` | CSS selectors of overlays your page embeds, such as a review toolbar or a chat widget. A change inside them never counts as the effect of a click. |
| `skipClickLabels` | string\[] | `[]` | Labels the click test never clicks, on top of its built-in list of destructive and transactional words. Matched as whole words, in any case and any script. |

The three staging word lists take single host words of 2 to 30 letters or digits, at most 50 per list. `ignoreOverlaySelectors` and `skipClickLabels` take at most 20 entries, of at most 200 and 60 characters. Other entries are ignored.

During the click test, a click that opens a new tab, starts a download, or hands off to an app counts as working. A page that builds its content from data queries the test refuses, such as GraphQL, is not judged for dead controls.

### Proofreader

Options for `spell-check`. The Proofreader finds candidates with a dictionary and rules, then asks a verification model to confirm the ones the rules are not certain of. If the model cannot answer, the run still reports the findings the rules are certain of, and its summary says what could not be checked.

| Key | Type | Default | Effect |
| - | - | - | - |
| `rulesOnly` | boolean | `false` | Sends no page text to the verification model. Only findings the rules are certain of are reported. Spelling is not checked, and the run summary says so. |
| `acceptedWords` | string\[] | `[]` | Words to accept as correctly spelled, in any case, on top of the built-in list. |
| `brandNames` | string\[] | `[]` | Brand names and their exact casing, on top of the built-in list. Your casing wins over the built-in one. |
| `skipChecks` | string\[] | `[]` | Issue types not to look for: any of `spelling`, `doubled-word`, `punctuation`, `placeholder`, `brand-casing`, `inconsistent-casing`. |
| `keepAtOrAbove` | number | `0.75` | Lowest verification-model confidence at which a candidate the model checked is reported. Greater than 0 and at most 1. To get close to the behavior before October 7, 2026, send `0.6` with `nameChecks: false`. |
| `nameChecks` | boolean | `true` | Before the Proofreader reports a spelling candidate, it asks the verification model whether the word is a name (a person, place, product, or brand). It skips this step when the word has a clear typo pattern, such as two swapped letters. `false` turns these name rules off. |
| `nameAtOrAbove` | number | `0.75` | Lowest verification-model confidence that a word is a name at which a spelling candidate is dropped. A capitalized word that reads like a name is dropped at `0.5`, or at this value when it is lower. Greater than 0 and at most 1. Independent of `keepAtOrAbove`. |
| `useGuidelines` | boolean | `true` | Reads extra accepted words and brand-name casing from the brand guidelines in your workspace's knowledge base. `false` skips that read for this run. |
| `loremIpsumOnSamePages` | boolean | `false` | With `true`, lorem ipsum and pseudo-Latin filler are left to the `lorem-ipsum` agent, and the run summary says `Lorem ipsum is left to the Lorem Ipsum agent.` The Proofreader's other placeholder checks, such as "Insert headline here", still run. Ignored when you send `skipChecks`. |
| `checkHiddenText` | boolean | `false` | Also proofreads text a visitor cannot see, such as an icon link's off-screen label or screen-reader-only text: what screen-reader users hear. |

`acceptedWords` and `brandNames` take single words. The first 500 entries are read, and an entry longer than 64 characters is ignored.

The verification model answers at most 20,000 questions per API key per UTC day, and a candidate takes one to three. Change detection's check of changed page text counts toward the same limit (see the run-control keys of [Run Execution](https://velt.dev/docs/api-reference/rest-apis/v2/agents/execution/run.md)). Past that, the Proofreader reports only the findings its rules are certain of, and the run summary says `The daily spelling check limit was reached.`

> [!TIP]
>
> The Proofreader also reports lorem ipsum. A run with `agentIds` that starts both `spell-check` and `lorem-ipsum` sets `loremIpsumOnSamePages: true` for you, so each lorem ipsum line is reported once, by the Lorem Ipsum agent. It does not when you send `skipChecks` or `loremIpsumOnSamePages` yourself. If you run the two agents on the same pages in separate requests, send `loremIpsumOnSamePages: true` to the Proofreader. The Proofreader cannot see whether the Lorem Ipsum execution succeeds. If that execution fails, lorem ipsum on those pages goes unreported. Send `loremIpsumOnSamePages: false` when you want both.

A spelling finding names its correction in `suggestion` and `suggestedFix` when the verification model picks one of the dictionary's suggestions, or when there is only one. When there are several and none is picked, its `suggestion` is `Check the spelling.` and it has no `suggestedFix`.

### Consistency Checker

Options for `consistency-checker`. Its keys start with `consistency` because a run with `agentIds` shares one `userContext` across every agent.

| Key | Type | Default | Effect |
| - | - | - | - |
| `consistencyCasingCheck` | boolean | `true` | Runs the cross-page casing check (`cross-page-casing`). Brand names you give the Proofreader in `brandNames` are left to the Proofreader. |
| `consistencyVisualCheck` | boolean | `true` | Runs the visual check, which uses no model: buttons and links styled differently from the site's usual style for their kind (`style-mismatch`), with no hover effect while the others have one (`missing-hover`), or whose text matches its background on hover (`hover-invisible`). |
| `consistencyPeersOnly` | boolean | `true` | The visual check compares an element only with its peers. It reports no style difference for a component repeated on the page (unless the same component looks different on another page), for the colors of a promotion, for a button color that buttons on other pages also use (the site's accent color), or for a link colored like the text around it. The selected item of a tab or filter row is left out. `false` compares every element, as before October 7, 2026. |
| `consistencyExactValues` | boolean | `true` | When this page's phone number or email is a one-character slip of the value the other pages agree on, names that value in the suggestion and in `suggestedFix`. |
| `consistencyMaxPages` | number | `6` | Other pages of the site to compare with. Whole number, capped at 12. |
| `consistencyMaxCharsPerPage` | number | `6000` | Characters of each other page's text given to the AI model. Whole number, capped at 20,000. |
| `consistencyTextVisibility` | string | `"visible"` | `"visible"` compares only the text a visitor sees. `"all"` compares all rendered text, including text hidden with zero opacity. |
| `consistencyIncludeScreenReaderText` | boolean | `false` | Counts screen-reader-only text, such as an icon link's label, as page text in the comparison and the casing check. |
| `consistencyRawPagesAsEvidence` | boolean | not set | `true` reports a difference that rests only on pages read without a browser, such as a page that failed to render. A phone number is never reported this way. Not set, it is off when the run renders pages in a browser, which is the usual case. |

A visual finding names the elements it groups in `metadata.labels`. A `style-mismatch` finding also lists what differs in `metadata.differences`, one entry per property: `{ property, value, dominant, dominantCount, css }`, where `css` is the declaration the rest of the site uses, such as `border-radius: 8px`. Its suggestion names the first declaration and counts the others. Read `metadata` on the findings of [Get Execution](https://velt.dev/docs/api-reference/rest-apis/v2/agents/execution/get.md) with `includeResults: true`.

### Image Inspector

Options for `image-inspector`. A value outside its range is ignored, and the default applies.

| Key | Type | Default | Effect |
| - | - | - | - |
| `blurMinNaturalRatio` | number, 0.05 to 1 | `0.6` | An image is blurry when its file is narrower than this share of the CSS pixels it fills. |
| `blurHighScale` | number, 1 to 20 | `2.5` | Enlargement from which a blurry image is `high` severity instead of `medium`. |
| `blurMinRenderedWidthPx` | number, 0 to 4000 | `120` | Narrowest image, in CSS pixels, checked for blur. |
| `stretchTolerance` | number, 0 to 1 | `0.08` | Aspect-ratio difference allowed before an image counts as stretched. |
| `stretchMinWidthPx` | number, 0 to 4000 | `64` | Narrowest box, in CSS pixels, checked for stretching. |
| `stretchMinHeightPx` | number, 0 to 4000 | `32` | Shortest box, in CSS pixels, checked for stretching. |
| `emptyMinSidePx` | number, 0 to 4000 | `24` | Smallest image slot, in CSS pixels, reported as empty. |
| `altMinSidePx` | number, 0 to 4000 | `48` | Smallest image, in CSS pixels, that needs alt text. |
| `maxPerCategory` | whole number, 1 to 50 | `6` | Most findings pinned per issue type on a page. |
| `linkCheckerOnSamePages` | boolean | `false` | With `true`, broken images the Link Checker also reports are left to it, so they are not reported twice. A one-page run with `agentIds` that starts `broken-links` sets it for you whenever the Link Checker checks images in that run. Set it yourself when you run the two agents on the same pages in separate requests, or in one `agentIds` run over several pages. A value you send always wins. |
| `cropCheck` | boolean | not set | `true` turns on the bad-crop check (`bad-crop`): screenshots of up to 6 photos per page are sent to an AI model, which flags a head or main subject cut off at an edge. `false` keeps the check off whatever `aiConfig.modelChecks` says. Not set, the check runs only when the run's [`aiConfig.modelChecks`](https://velt.dev/docs/api-reference/rest-apis/v2/agents/execution/run) lists `image-crop`. |

Images without alt text are reported as one finding: pinned on the image when there is one, and page-level when there are several. The bad-crop check is the Image Inspector's only model call, and it is off unless turned on. A run focused on other issue types never runs it. When the model gives no usable answer, the run summary says `Photo crops could not be checked.`

### Mobile Inspector

Options for `mobile-inspector`. A value outside its range is ignored, and the default applies.

| Key | Type | Default | Effect |
| - | - | - | - |
| `phoneWidthPx` | whole number, 320 to 480 | `375` | Phone screen width, in CSS pixels, the page opens at. |
| `minTapTargetPx` | number, 8 to 96 | `24` | Smallest tap target, in CSS pixels, that passes. The suggestion names this size. |
| `maxScreenshots` | whole number, 0 to 10 | `7` | Screenshots per page, including the first screen. `0` turns screenshots off. |
| `tabletWidthPx` | whole number, 600 to 1024, or `0` | `768` | Width, in CSS pixels, of the tablet layout pass. `0` turns the tablet pass off. |
| `skipChecks` | string\[] | `[]` | Checks not to run, any of: `tablet` (the tablet layout pass), `sticky-bar` (content under fixed or sticky bars; it scrolls and taps same-page links), `wrapped-label` (button labels that wrap), `menu` (taps the menu button to see whether it opens anything), and `missing-on-mobile` (content shown on desktop that a phone visitor cannot reach). Unknown entries are ignored. |
| `closeNotices` | boolean | `true` | Closes cookie and consent notices and small popups the way a visitor would before each width is measured, and leaves out the ones that stay. `false` leaves every notice alone and judges it as page content, so a button a cookie banner covers is reported as hidden under it. |

The phone checks for sideways scrolling, overflow, cut-off content, and small tap targets always run. With `menu` skipped, the menu is not judged, and links that sit in a hidden phone menu are never reported as missing on phones.

### Migration Parity

Options for `migration-parity`. `liveSiteUrl` is required.

| Key | Type | Default | Effect |
| - | - | - | - |
| `liveSiteUrl` | string | none | Required. The live or old site to compare against: a full address or a bare domain, such as `old.example.com`. Only its origin is used. `liveUrl` is read as the same key when `liveSiteUrl` is absent. |
| `maxFindings` | whole number, 1 to 20 | `6` | Most findings per page. A focused recheck (`focusIssueTypes`) caps only the issue types it asks for. |
| `useSitemap` | boolean | `true` | When the same path does not exist on the live site, looks for the best match by address in the live site's sitemap. |

A run without a usable `liveSiteUrl`, or whose live site is the site of the run's `url`, returns `INVALID_ARGUMENT` before any execution is created, with `Migration Parity needs the live site to compare against: send userContext.liveSiteUrl (a full address or a bare domain)` or `Migration Parity needs a live site other than the project site: userContext.liveSiteUrl names the same site as the run's url`. In a run with `agentIds`, Migration Parity is listed in `data.failed` and the other agents still start.

For each page, the agent finds the same page on the live site and reports what the live page has that the new one lost. Names, numbers, and addresses are compared exactly; a phone number counts as kept in any written form. Contact details the live site shows only in its header or footer are compared once per run, on the run's first page.

Live pages are read without your site access credentials, and only on public addresses. A page that was not compared gets no findings, keeps its earlier suggestions, and says why in the run summary: no matching live page, a live site that could not be read, a live page that timed out or refused the visit, too little text on either page, or a sign-in wall in front of either page. A page skipped for a sign-in wall is not billed.

Each finding carries `livePageUrl` and `missing` (the missing items, at most 20) in `agent.reason`. Each page's result on [Get Execution](https://velt.dev/docs/api-reference/rest-apis/v2/agents/execution/get.md) with `includeResults: true` carries `agentResult.report`: `livePageUrl`, `match` (`"same-path"`, `"sitemap"`, or `"none"`), `compared` (how many bios, reviews, FAQs, phone numbers, emails, addresses, and list items were compared), and `skipped` (`"gated"` or `"live-gated"` when a sign-in wall stood in front of the page or its live page).

### Content Request List

Options for `content-request-list`. All are optional.

| Key | Type | Default | Effect |
| - | - | - | - |
| `includeThreads` | boolean | `true` | Lists the document's open comment threads that ask for content or a confirmation. |
| `maxItems` | whole number, 1 to 50 | `25` | Most checklist items per page. |
| `minBioWords` | whole number, 1 to 100 | `10` | A team member's bio shorter than this is listed as short, when another member of the same team has a full bio. |
| `clientUserIds` | string\[] | none | Up to 1,000 user IDs of the client. A thread the client opened is the client asking your team, so it is left out. Without this key or `clientEmailDomains`, every human ask counts. |
| `clientEmailDomains` | string\[] | none | Up to 100 email domains of the client, subdomains included. Works as `clientUserIds` does, on the email of the thread's author. |
| `audienceLabel` | string, 1 to 40 characters | `"the client"` | Who the checklist is for, as the finding names them, for example `3 things still need content from the owner`. Angle brackets are not allowed. |

The agent posts one page-level finding per page, with issue type `content-requests`. The whole checklist is on the finding's `agent.reason.contentRequests` and on each page's `agentResult.report.contentRequests` in [Get Execution](https://velt.dev/docs/api-reference/rest-apis/v2/agents/execution/get.md) results: items `{ kind, label, section?, text?, annotationId?, count? }`, where `kind` is `empty-section`, `placeholder-text`, `coming-soon`, `placeholder-image`, `thin-bio`, or `open-question`.

It reads the run document's open comment threads and quotes one only when the run's audience can already see it: a public thread always, an organization-private thread only on a `"private"` run of that same organization, and a thread restricted to named users never. Threads an agent opened, and threads whose last human reply looks like the answer, are left out. It reads up to 2,000 annotations past the agents' own suggestions, and the summary says when older threads were not read.

A page title alone in a banner, a "Coming soon" badge among real content, and stand-in lines in the header, navigation, or footer are not listed. A page behind a sign-in wall is skipped (`report.skipped: "gated"`), is not billed, and keeps its earlier checklist.

### AI Visibility

Options for `ai-visibility`.

| Key | Type | Default | Effect |
| - | - | - | - |
| `minVisibleWithoutJs` | number, 0 to 100 | `90` | The JavaScript check passes when at least this percent of the page's text is visible without running JavaScript. |
| `failVisibleWithoutJs` | number, 0 to 100 | `60` | The JavaScript check fails below this percent. Between the two thresholds, it warns. |
| `scoreAnswerShapeOnAllPages` | boolean | `false` | `true` scores the answer-shape check on every kind of page, as it was scored before October 2026: question headings, a list or table, a date, and an author on an article, and question headings and a list or table on other pages. A page with fewer than half of them fails. With `false`, the check asks only what the [`ai-visibility` row](#built-in-agents) describes, and a gap is a warning. |

`0` is accepted as a threshold. Leave the key out, or send `null` or an empty string, to keep the default. A threshold outside 0 to 100 is ignored. Unlike the other options on this page, the two thresholds are declared fields of the agent, so a threshold that is not a number returns `INVALID_ARGUMENT`.

## Context gathering strategies

Stack one or more strategies in the order you want them to run.

| Strategy | What it returns |
| - | - |
| `web-page-text` | Visible text extracted via Puppeteer |
| `web-page-screenshot` | Full-page screenshot as image (multimodal input) |
| `web-page-html` | Cleaned HTML content |
| `web-page-css` | Cleaned CSS content from stylesheets |
| `web-page-links` | All hyperlinks on the page, classified internal/external |
| `web-page-accessibility` | Accessibility issues (Pa11y / HTML\_CodeSniffer) |
| `computed-styles` | Browser-resolved computed CSS for specific selectors |
| `robots-txt` | Fetched `robots.txt` |
| `sitemap-data` | Discovered and parsed XML sitemaps |
| `lighthouse` | Google Lighthouse audit (performance / a11y / best-practices / SEO) |
| `rest-api` | Customer-configured REST endpoints fetched at runtime (SSRF-guarded, encrypted auth); injected via `{{restApiData}}` |
| `none` | No context gathering (for service-only or text-only agents) |

Per-strategy overrides are supplied under `contextGathering.strategyOptions["<strategy>"]`. See [Create Agent](https://velt.dev/docs/api-reference/rest-apis/v2/agents/create.md) for the `rest-api` endpoint configuration schema.

## Execution strategies

| Strategy | Purpose |
| - | - |
| `ai` | LLM-driven analysis (default) |
| `service` | Delegate to a registered built-in service (`serviceId` required) |
| `service+ai` | Registered service, then AI analysis; `{{serviceResult}}` in the instructions resolves to the service output (`serviceId` required) |
| `stagehand-agent` | Browser agent: the agent's model drives a live page with browser tools (`instructions` required) |
| `mcp-tools` | Model-driven tool loop against remote MCP server(s) (`instructions` + `execution.mcpServers` required) |

## Knowledge (Memory-RAG)

Agents can pull workspace knowledge from Velt Memory into the prompt via `execution.knowledge`:

| Field | Type | Range | Description |
| - | - | - | - |
| `useMemory` | boolean | | When `true`, retrieves knowledge/patterns/activities from Memory and injects them as `{{memoryContext}}` |
| `maxChunks` | number | 1–20 | Max knowledge chunks to retrieve |
| `maxPatterns` | number | 1–20 | Max learned patterns to retrieve |
| `maxActivities` | number | 1–20 | Max recent activities to retrieve |

> [!NOTE]
>
> The `knowledge` block is strictly validated: only the four fields above are accepted. The legacy `sourceIds` field has been removed, and `maxChunks` is now capped at 20 (previously 50). Knowledge retrieval never fails an execution: if Memory is unavailable, the run continues in a degraded mode without knowledge context.

## Scope

| Field | Bound to |
| - | - |
| `apiKey` | Workspace-wide (default; agents are per-workspace) |
| `organizationId` | Annotations created on the named organization |
| `documentId` | Annotations created on the named document |

`organizationId` and `documentId` are required on Run Execution and control where annotations land. The document must already exist before you run an agent against it.

## Get started

> [card] [Setup](https://velt.dev/docs/ai/agents/setup.md)
>
> Create an agent, run it against a URL, and read the findings end-to-end.

> [card] [API Reference](https://velt.dev/docs/api-reference/rest-apis/v2/agents/create.md)
>
> All endpoints organized into Agents, Execution, Versioning, Prompt Tools, Analytics, and Groups.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.