agentspeed.
Specification · Public · Versioned

The AgentSpeed Rubric

r2026.11.0activebands v1published 2026-08-19

The AgentSpeed Rubric is the specification for computing scores published at /score/<domain>. It enumerates every check, its weight, and the grade bands that map a composite into a letter. Versions are immutable (§10); historical scans render against the rubric they were computed on. Class weight policy in §11.1 caps how much of a score can come from heuristic or model-assisted checks.

Based on 36 checks · 25 deterministic · 10 heuristic · 1 model-assisted.

Summary

AgentSpeed scores whether AI agents can discover, read, understand, and act on your website.

Five sub-scores combined into a 0–100 composite, mapped to a letter grade A–F. The full mathematical specification is below. This overview is for everyone else.

How often is this score wrong?

Measured against a frozen corpus of hand-labelled cases, with the disagreements, the case ids behind them, and the checks we have too little evidence to rate: score accuracy →

And every change to the instrument itself, derived from the rubric files: rubric changelog →

Rubric version
Current version
r2026.11.0
Published
2026-08-19
Checks
37 (36 scored, 1 reported only)
Deterministic
25
Heuristic
10
Model-assisted
1
Grade bands
bands v1
Versions are immutable. Historical scans render against the rubric they were computed on.View changelog →
Categories
Discoverability22% weight

what it measures

How easily an agent finds canonical content and capability manifests: robots.txt, llms.txt, sitemap, OAuth metadata, MCP server card.

why it matters

If agents can't find your canonical pages, every other score is academic. The page won't show up in agent answers.

example checks

Readability22% weight

what it measures

How much primary content is available without executing JavaScript, and whether structural signals (headings, title, meta description, markdown negotiation) are correct.

why it matters

Agents read raw HTML before they render. A site that hides its hero behind a JS bundle is a site agents quote a footer about.

example checks

Structured data13% weight

what it measures

Whether JSON-LD is present, validates against schema.org, and covers the apparent purpose of the page.

why it matters

Typed data lets agents quote prices, authors, and FAQ answers verbatim. Without it, agents guess from prose and hallucinate.

example checks

Actionability28% weight

what it measures

Whether an agent can identify the primary offering and its call-to-action, and whether the site exposes in-page agent surfaces (Agent Skills, WebMCP).

why it matters

Reading is half the work. If an agent can't tell what the site offers or how to act on it, it stops at the homepage.

example checks

Performance15% weight

what it measures

Time-to-first-byte, full render, and total page weight, measured against thresholds chosen for typical agent timeouts.

why it matters

Most agents abort at 6s. A page that renders for humans in 8s is invisible to agents and to the answers they generate.

example checks

How to read your score

Why skipped checks do not inflate the score. Skipped checks are excluded from both the numerator and denominator of their sub-score. We do not count skip as a pass (which would inflate) or as a fail (which would unfairly punish sites for not adopting an opt-in capability). A site that legitimately does not run an API will have api.* checks skip and a sub-score computed only over the checks that ran.

What counts as agent-ready?
  1. 01
    Agents can find your important pages

    robots.txt allows known agent UAs, sitemap.xml lists canonical URLs, and /llms.txt points at docs and pricing.

  2. 02
    Agents are not blocked accidentally

    No inherited User-agent: * disallow blocks GPTBot / ClaudeBot, and no Cloudflare challenge fires on agent traffic.

  3. 03
    Agents can read content without broken JS

    Primary content renders server-side. JavaScript is enhancement, not requirement.

  4. 04
    Agents can parse structured data

    JSON-LD blocks are present, validate against schema.org, and cover the page kind (Product, Article, FAQPage, BreadcrumbList).

  5. 05
    Agents can identify pricing or CTA

    Pricing is reachable as text or Offer schema. The primary CTA is a real link with text, not a JS-only button.

  6. 06
    Agents can load the page quickly

    TTFB and full render fit within typical agent timeouts (around 6 seconds).

↓ full specification below ↓

§1 Status of this document

This is version r2026.11.0, published 2026-08-19. It does not retroactively rescore scans run against earlier versions (see §10). The file that produced this document is under version control; its content hash is part of every permalinked scan's citation (see §13). Older deprecated versions are listed in §12.

§2 Terminology
checka single rule evaluated against a target site. Returns one of pass, warn, fail, skip, blocked.
probea check whose evaluation involves a language model. Probes are enumerated in §9. Every other check is deterministic or heuristic.
deterministica check whose rule references an external specification (RFC, W3C, IETF draft, schema.org). No AgentSpeed-chosen thresholds. Re-running on identical bytes produces an identical output as long as the rubric version is unchanged.
heuristica check whose rule is fixed code but whose threshold or match pattern was chosen by AgentSpeed rather than by a published standard. Bitwise reproducible against the same rubric; a different rubric can legitimately disagree. The chosen parameter is shown inline in §6 and catalogued in §8.
sub-scorea weighted average, in the range 0 to 100, of the checks belonging to one of five categories. See §5.
compositethe weighted average of the five sub-scores. Range 0 to 100. Rendered with one decimal place.
gradea letter derived from the composite via the current grade bands (§7).
findinga check result that produced a warn or fail, surfaced on the public score page with a severity and a remediation page.
remediationa markdown document attached to a finding; permalinked at /score/<domain>/fix/<checkKey>.
§3 Principles
  1. Public. Every check, weight, and band is documented on this page.
  2. Reproducible. Identical input produces an identical score, within the measurement error introduced by the target site changing between runs.
  3. Versioned. Rubric changes produce a new version identifier. Historical scans retain the version they were computed on.
  4. Conservative. When a check cannot be evaluated (timeout, block, robots disallow), it returns skip and is excluded from its sub-score denominator. Skips never inflate the composite.
  5. Agent-first. Checks measure properties that matter to automated clients (ChatGPT, Perplexity, Claude, Operator, and named crawlers such as GPTBot and ClaudeBot), not human visitors.
§4 Scoring pipeline

A scan executes the following steps in order:

  1. Accept a URL. Normalise to origin, enforce https, apply the host policy (private IPs, reserved TLDs, and AgentSpeed-owned hosts are rejected).
  2. Fetch the canonical document over HTTP with the AgentSpeedBot/1.0 user-agent, alongside robots.txt, sitemap.xml and llms.txt. Redirects are followed to a maximum of five hops, each one re-checked against the host policy.
  3. Conditionally render with a headless browser at a fixed viewport 1280×800 and re-extract the text from the rendered DOM. This step does not run on every scan — see below.
  4. Evaluate every check in §6 against the captured artefacts.
  5. For each sub-score s, compute sub_score(s) = 100 × Σ(value(c) × weight(c)) / Σ(weight(c)) over checks c in category s whose status is not skip or blocked. Check values are pass = 1, warn = 0.5, fail = 0.
  6. Compute the composite: composite = Σ(sub_score(s) × sub_weight(s)) / Σ(sub_weight(s)).
  7. Resolve the grade by walking the grade bands (§7) from highest to lowest min and selecting the first band where composite ≥ min.
  8. Generate findings for every fail and warn and persist them alongside the scan.

§4.1 When step 3 runs

Step 3 is the one step that is not universal, and this specification does not present it as though it were. The free scan behind /score/<domain> is HTTP-only: it opens no browser at all, and records that it did not. The Deep Scan runs the full engine, which opens a headless browser only when the fetched HTML looks JavaScript-dependent — little extractable text, or an empty mount node — and only when enough of the scan budget remains for a render to finish. That browser is either launched locally or connected to over CDP, depending on deployment; the rubric treats both identically.

Where the two modes differ is in what gets measured, never in how a measurement is scored. Checks that need a rendered DOM — performance.full_render_ms above all — return skip when no render happened, and a skip is excluded from its sub-score denominator under §3. A scan therefore reports fewer measured checks in HTTP-only mode; it never reports a rendered measurement it did not take.

§5 Sub-scores
discoverability
22%
readability
22%
structured_data
13%
actionability
28%
performance
15%
discoverabilityHow easily an agent finds canonical content and capability manifests: robots.txt, llms.txt, sitemap, OAuth metadata, MCP server card, Web Bot Auth.
readabilityHow much of the primary content is available without executing JavaScript, and whether structural signals (headings, title, meta description, markdown negotiation) are correct.
structured_dataWhether JSON-LD is present, validates, and covers the apparent purpose of the page.
actionabilityWhether an agent can identify the primary offering and its call-to-action, and whether the site exposes in-page agent surfaces (Agent Skills, WebMCP).
performanceTime-to-first-byte, full render, and total page weight, measured against thresholds chosen for typical agent timeouts.
§6 Check catalogue

Every check that contributes to the composite on r2026.11.0, grouped by sub-score. determinism marks whether a check is evaluated by fixed rules or involves a language model (§8, §9); weight is the check's contribution to its sub-score before normalisation.

discoverability12 checks · click to expand
keydescriptiondeterminismweight
robots_txt.presentA reachable robots.txt exists at the site root. spec ↗
deterministic
1
robots_txt.allows_known_agentsrobots.txt does not disallow answer-time AI access agents (ChatGPT-User, OAI-SearchBot, Claude-User, Claude-SearchBot, PerplexityBot, Perplexity-User, YouBot, Amazonbot). Training-data crawler blocks (GPTBot, CCBot, Google-Extended, …) are reported as informational and never fail the check. spec ↗
deterministic
2
robots_txt.content_signalsrobots.txt advertises Content-Signal directives (e.g. `Content-Signal: ai-train=no, ai-summarize=yes`) that let agents respect granular usage preferences. spec ↗
deterministicemerging
1
llms_txt.presentAn llms.txt file at the site root. Reported for completeness and NOT scored: no measurement has connected it to AI citations. Google states Search does not use it; a ~300k-domain study found no correlation with citations; a 137k-domain crawl found 97% of these files received zero requests. Most traffic they do get is from SEO audit tools checking whether the file exists. spec ↗
deterministic
2
sitemap.presentA sitemap.xml is reachable and referenced from robots.txt. spec ↗
deterministic
2
discoverability.link_headersHTTP `Link:` response headers carry useful relations (canonical, alternate, describedby) that agents consume without parsing HTML. spec ↗
deterministic
1
markup.canonicalA canonical URL is declared and resolves to the same page. spec ↗
deterministic
2
discoverability.mcp_server_cardAn MCP Server Card is reachable at `/.well-known/mcp/server-card.json` (or referenced from a Link header) and validates against the Model Context Protocol spec. spec ↗
deterministicemerging
1
discoverability.oauth_authorization_server`/.well-known/oauth-authorization-server` is reachable and conforms to RFC 8414, letting agents discover authorization endpoints without out-of-band setup. spec ↗
deterministicemerging
1
discoverability.oauth_protected_resource`/.well-known/oauth-protected-resource` is published per RFC 9728 so agents can discover required scopes and authorization servers programmatically. spec ↗
deterministicemerging
1
discoverability.api_catalogAn API catalog is published at `/.well-known/api-catalog` (RFC 9727) or an OpenAPI document is reachable at `/openapi.json` or `/openapi.yaml`. spec ↗
deterministicemerging
1
discoverability.web_bot_authThe site signals support for the Web Bot Auth IETF draft (HTTP Message Signatures over a known JWKS) so well-behaved agents can prove identity. spec ↗
deterministicemerging
1
readability9 checks · click to expand
keydescriptiondeterminismweight
readability.markdown_negotiationRequests with `Accept: text/markdown` return a markdown representation of the page (Markdown content negotiation). spec ↗
deterministicemerging
1
content.text_ratioVisible text makes up at least 15% of the rendered DOM weight.
heuristicmin text ratio = 15%
1
content.js_required_for_primary_contentPrimary content is visible without JavaScript.
heuristicdetector = no-JS visibility heuristic
2
content.headings_hierarchyHeading hierarchy is well-formed (one H1, no skipped levels). spec ↗
heuristicrule = single H1, no skipped levels
1
auth.cookie_consent_blocks_contentA cookie-consent modal does not cover or block the primary content on first load.
heuristicdetector = consent overlay heuristic
2
markup.languageThe document declares its language: <html lang> is present and a well-formed BCP 47 tag, and any hreflang alternates carry well-formed values. Self-referencing and reciprocity are not checked — both require fetching the alternates, and a wrong warning there would be the scanner's limit charged to the site.
deterministic
1
markup.titleA non-empty <title> is present and under 70 characters. spec ↗
deterministic
2
markup.meta_descriptionA meta description is present and between 50 and 200 characters. spec ↗
deterministic
2
coherence.language_declared_matches_content<html lang> matches the language the visible content is actually written in, per a conservative deterministic language profile. The classic failure is a template default nobody edited: a German shop declaring lang="en". A mismatch WARNs, never fails - the detector is probabilistic and stays silent when unsure.
heuristicemergingdetector = stopword/script profile, >=40 words, WARN-only
1
structured_data5 checks · click to expand
keydescriptiondeterminismweight
structured_data.jsonld_presentAt least one valid JSON-LD block is present. spec ↗
deterministic
2
structured_data.validatesJSON-LD validates against the declared schema.org type. spec ↗
deterministic
2
structured_data.type_coverageDeclared JSON-LD types cover the apparent page purpose (e.g. a product page has Product, a blog post has Article).
heuristicmatch = type-to-purpose inference
1
coherence.jsonld_price_matches_visibleA price declared in JSON-LD appears among the prices visible on the served page, compared by numeric value ("79.00" matches "$79"). Fails only when NO declared price is visible - a page whose machine channel and human channel disagree makes agents quote a number customers never see. Both price lists are recorded as evidence. spec ↗
deterministicemerging
2
coherence.jsonld_name_matches_visibleA Product/Organization/Store name declared in JSON-LD appears in the page title or visible text (case-insensitive). A declared name that appears nowhere is stale structured data or machine-only content - either way agents identify an entity visitors never see. spec ↗
deterministicemerging
1
actionability8 checks · click to expand
keydescriptiondeterminismweight
auth.paywall_or_login_wall_on_landingLanding URL is not gated by a login or paywall.
heuristicdetector = paywall/login-wall heuristic
2
journey.primary_probeA read-only LLM-driven probe can identify the primary offering and either its price or its primary call-to-action.
model-assisted
2
reachability.statusLanding URL returns a 2xx after at most one redirect. spec ↗
deterministic
2
operability.primary_action_in_domThe page expresses its primary action as a real clickable element - a link with an href, a button, or a submit input - rather than as text painted into an image or onto a plain element. Passes as soon as one clickable element carries action language. Skips when the page asks the reader to do nothing. Fails only when the page clearly asks for an action and nothing clickable carries it.
deterministicemerging
2
operability.filters_addressableWhen the page offers to filter or sort a list, at least one filtered view is reachable by URL - a link carrying a filter query parameter, or a GET form around the controls. Warns when controls are served but no filtered view has its own URL. Fails when the page offers filtering and serves no operable control at all. Skips on pages that offer no filtering.
deterministicemerging
2
actionability.agent_skillsAn Agent Skills manifest is reachable (e.g. `/.well-known/agent-skills.json`) describing discrete tasks an agent can perform on the site.
deterministicemerging
1
actionability.web_mcpThe page exposes WebMCP (in-browser Model Context Protocol) so on-page agents can invoke tools without leaving the tab.
deterministicemerging
1
actionability.commerce_protocolsThe site declares an agentic-commerce discovery manifest (x402, UCP, or ACP), so a buying agent can learn how to transact from the domain alone.
deterministicemerging
1
performance3 checks · click to expand
keydescriptiondeterminismweight
performance.ttfb_msTime-to-first-byte is under 800ms from a US-East origin. Measured as a single sample of total fetch time from one location, so treat it as directional. spec ↗
heuristicthreshold = 800ms
1
performance.full_render_msFull render (network idle) completes under 4 seconds.
heuristicthreshold = 4s
1
performance.payload_kbTotal page weight is under 3 MB, and the document can be fetched at all.
heuristicthreshold = 3MB
1
§7 Grade bands
A
90
B
80
C
70
D
60
F
0

Grade bands are versioned independently (bands v1). A change in the band cutoffs bumps the band version and is treated equivalently to a rubric change for historical preservation (§10).

§8 Heuristic checks

10 checks in r2026.11.0 are heuristic: the scanner evaluates a fixed rule, but the threshold or match pattern was chosen by AgentSpeed rather than by an external specification. Heuristic checks are bitwise reproducible (two scans on identical bytes against the same rubric produce identical results), but a different rubric can legitimately disagree. The chosen parameter is rendered inline in §6 and enumerated below. Thresholds are versioned with the rubric (§11); a change in a threshold requires a rubric version bump.

keyparametervalue
content.text_ratiomin text ratio15%
content.js_required_for_primary_contentdetectorno-JS visibility heuristic
content.headings_hierarchyrulesingle H1, no skipped levels
auth.cookie_consent_blocks_contentdetectorconsent overlay heuristic
coherence.language_declared_matches_contentdetectorstopword/script profile, >=40 words, WARN-only
structured_data.type_coveragematchtype-to-purpose inference
auth.paywall_or_login_wall_on_landingdetectorpaywall/login-wall heuristic
performance.ttfb_msthreshold800ms
performance.full_render_msthreshold4s
performance.payload_kbthreshold3MB
§9 Model-assisted checks

One check in r2026.11.0 is model-assisted: journey.primary_probe. The probe is a single, read-only request to an Anthropic model (claude-haiku-4-5-20251001 at the time of publication) that returns a structured JSON classification of the page's primary offering and price-or-CTA. The probe performs no tool calls and visits no other URL. Its prompt, model, and decoding temperature are fixed for the lifetime of the rubric version; changes to any of the three produce a new rubric version.

The following constraints bind every model-assisted check and MUST hold in any future probe added to the rubric:

§10 Historical preservation

Each scan is persisted with the rubric version and grade-band version in force at the time it ran (Scan.rubricVersion, Scan.gradeBandVersion). Rendering a scan, including via its permalink at /score/<domain>/scan/<scanId>, uses those stored versions, not the current rubric. Changes to the rubric MUST NOT rescore or mutate historical scans. A deprecated check (deprecatedIn set) continues to display on historical scans that included it.

§11 Versioning policy

Rubric versions follow the form rYYYY.SERIES.PATCH. The middle field is a series counter, not a month. The active rubric r2026.11.0 was published 2026-08-19; the changelog in §12 lists consecutive series numbers published days apart. Read as a month, a version id dates a rubric to a time it was never frozen at — publishedAt, shown against every version in §12, is the only date an id carries.

Existing ids are never renumbered to look tidier: they are already embedded in issued certificates, stored scans and public permalinks, and rewriting them would invalidate citations that are correct as published.

Grade bands carry a separate integer version (v1, v2, …). A band-cutoff change bumps the grade-band version but not the rubric version.

Every rubric version is immutable after publication. Each version's file has a content hash; that hash is part of the citation format in §13.

§11.1 Class weight policy

The rubric targets a minimum share of deterministic weight and maximum shares of heuristic and model-assisted weight, so a score cannot be dominated by AgentSpeed-chosen thresholds or by a language model:

measurecurrenttargetstatus
deterministic share70.6%≥ 60%
within
heuristic share25.5%≤ 30%
within
model-assisted share3.9%≤ 10%
within
max single model-assisted weight2≤ 2
within
§12 Changelog
versionstatuspublishedchangesfile sha
r2026.11.0active2026-08-19Adds actionability.commerce_protocols (weight 1, emerging): does the site declare an agentic-commerce discovery manifest — x402 (/.well-known/x402.json), UCP (/.well-known/ucp), or ACP (/.well-known/acp.json)? One check that passes on any of the three, because a site adopts one standard and the capability, not the spelling, is the subject. Nothing else changes: no thresholds move, no check is removed or reweighted. The text-density finding now reports where a document's bytes actually went. It gave a percentage and then blamed "heavy ad or navigation markup", which is wrong for most framework-rendered pages, where the weight is serialized hydration state inside script tags. Measured across 20 live sites, script and style are a median 34% of a homepage. Thresholds are unchanged: on the same 20 sites the existing bands separate document-first sites from application shells, with 30% passing. One page now yields one text reading. Three implementations of "the text an agent sees" had drifted apart over what to do with template elements, the document title and inline SVG labels, so the same page scored differently depending on which path scanned it. Verdicts move slightly downward on template-heavy pages scanned through the public path. performance.payload_kb can fail again. It fails above 3 MB, but the public scan refuses to download more than 3 MB, so the heaviest documents on the web were recorded as "not measured" and scored 100. A document too large to fetch is now graded as too large rather than as a missing measurement. A scan no longer describes a document the origin never served. When the landing page returns a non-2xx status, every check whose subject is that document reports no measurement; robots.txt, sitemap.xml and the /.well-known surface still report, because they are separate fetches, and reachability.status still fails, because the status code is its subject. Found in the corpus: the three highest text-ratio scores across 43 scans were a 404 and two 403s, at 90.0%, 77.6% and 40.2%, all PASS, while every site that served us a real page failed the same check. content.text_ratio requires a document of at least 2,048 bytes. Below that there is no markup weight to crowd out text, so the ratio measures rounding. Threshold set from the corpus, where every document under 16 KB passed and the smallest to return anything else was 33,794 bytes. A refused probe is no longer read as an absent resource. The /.well-known checks scored any unsuccessful probe as "not published", so a site blocking our user-agent was told to publish six files it may already serve. HTTP 401, 403, 407, 408, 429 and 5xx now report no measurement; 404, 410, a 200 with an invalid body, and 406 for Accept: text/markdown still fail, because each of those answers the question asked. New check family: operability (2 checks). Every check before this one graded what a page SAYS. None graded whether its controls can be worked by an agent driving the DOM, which is where agents actually fail. Published measurement, not assumption: on 300 tasks across 136 live sites the strongest agent succeeded 61.3% of the time, and filter and sorting errors caused 57.7% of its failures (arXiv:2504.01382); in a controlled experiment a call to action baked into an image was clicked 0/10 by every model tested versus 7/10 for the same action as a real element (arXiv:2507.12844). operability.primary_action_in_dom (actionability, weight 2, deterministic): a page that asks for an action must express it as a real clickable element. PASSes on the first link, button, or input carrying action language; SKIPs when the page asks for nothing; FAILs only when the words appear in image alt text or on a plain element and nothing clickable carries them. operability.filters_addressable (actionability, weight 2, deterministic): when a page offers to filter or sort a list, at least one filtered view must be reachable by URL, through a link with a query parameter or a GET form. WARNs when controls exist but produce no URL, FAILs when no operable control is served at all, SKIPs on pages with no facets. The check set grows from 34 to 36 (35 scored). No claim is made that operability changes citation or conversion rates. The cited research measures agent task success on other sites, not revenue on yours. These checks state something per-site and factual: the control is operable, or it is not. New check family: coherence (3 checks). The rubric so far verified each machine channel EXISTS - JSON-LD present, lang declared - but nothing verified the channels AGREE with each other or with what humans see. Disagreement is worse than absence: an absent price makes an agent hedge, a divergent one makes it quote the wrong number with confidence. Cross-channel agreement is also structurally un-gameable - the only way to game a consistency check is to become consistent. coherence.jsonld_price_matches_visible (structured_data, weight 2, deterministic): a price declared in JSON-LD must appear among the visible prices, compared by numeric value. FAILs only when ZERO declared prices are visible. Both price lists are recorded as evidence. coherence.jsonld_name_matches_visible (structured_data, weight 1, deterministic): a declared Product/Organization/Store name must appear in the title or visible text. coherence.language_declared_matches_content (readability, weight 1, heuristic): <html lang> compared against a conservative stopword/script language profile of the content; WARNs, never FAILs, and stays silent when unsure. The check set grows from 31 to 34 (33 scored). No claim is made that coherence affects AI citation rates - that measurement has not been done. What these checks demonstrate is per-site and factual: when the machine and human channels disagree, an agent trusting the machine channel quotes numbers and names the visible page does not show.sha fd2d068
r2026.10.4deprecated2026-07-30The text-density finding now reports where a document's bytes actually went. It gave a percentage and then blamed "heavy ad or navigation markup", which is wrong for most framework-rendered pages, where the weight is serialized hydration state inside script tags. Measured across 20 live sites, script and style are a median 34% of a homepage. Thresholds are unchanged: on the same 20 sites the existing bands separate document-first sites from application shells, with 30% passing. One page now yields one text reading. Three implementations of "the text an agent sees" had drifted apart over what to do with template elements, the document title and inline SVG labels, so the same page scored differently depending on which path scanned it. Verdicts move slightly downward on template-heavy pages scanned through the public path. performance.payload_kb can fail again. It fails above 3 MB, but the public scan refuses to download more than 3 MB, so the heaviest documents on the web were recorded as "not measured" and scored 100. A document too large to fetch is now graded as too large rather than as a missing measurement. A scan no longer describes a document the origin never served. When the landing page returns a non-2xx status, every check whose subject is that document reports no measurement; robots.txt, sitemap.xml and the /.well-known surface still report, because they are separate fetches, and reachability.status still fails, because the status code is its subject. Found in the corpus: the three highest text-ratio scores across 43 scans were a 404 and two 403s, at 90.0%, 77.6% and 40.2%, all PASS, while every site that served us a real page failed the same check. content.text_ratio requires a document of at least 2,048 bytes. Below that there is no markup weight to crowd out text, so the ratio measures rounding. Threshold set from the corpus, where every document under 16 KB passed and the smallest to return anything else was 33,794 bytes. A refused probe is no longer read as an absent resource. The /.well-known checks scored any unsuccessful probe as "not published", so a site blocking our user-agent was told to publish six files it may already serve. HTTP 401, 403, 407, 408, 429 and 5xx now report no measurement; 404, 410, a 200 with an invalid body, and 406 for Accept: text/markdown still fail, because each of those answers the question asked. New check family: operability (2 checks). Every check before this one graded what a page SAYS. None graded whether its controls can be worked by an agent driving the DOM, which is where agents actually fail. Published measurement, not assumption: on 300 tasks across 136 live sites the strongest agent succeeded 61.3% of the time, and filter and sorting errors caused 57.7% of its failures (arXiv:2504.01382); in a controlled experiment a call to action baked into an image was clicked 0/10 by every model tested versus 7/10 for the same action as a real element (arXiv:2507.12844). operability.primary_action_in_dom (actionability, weight 2, deterministic): a page that asks for an action must express it as a real clickable element. PASSes on the first link, button, or input carrying action language; SKIPs when the page asks for nothing; FAILs only when the words appear in image alt text or on a plain element and nothing clickable carries them. operability.filters_addressable (actionability, weight 2, deterministic): when a page offers to filter or sort a list, at least one filtered view must be reachable by URL, through a link with a query parameter or a GET form. WARNs when controls exist but produce no URL, FAILs when no operable control is served at all, SKIPs on pages with no facets. The check set grows from 34 to 36 (35 scored). No claim is made that operability changes citation or conversion rates. The cited research measures agent task success on other sites, not revenue on yours. These checks state something per-site and factual: the control is operable, or it is not. New check family: coherence (3 checks). The rubric so far verified each machine channel EXISTS - JSON-LD present, lang declared - but nothing verified the channels AGREE with each other or with what humans see. Disagreement is worse than absence: an absent price makes an agent hedge, a divergent one makes it quote the wrong number with confidence. Cross-channel agreement is also structurally un-gameable - the only way to game a consistency check is to become consistent. coherence.jsonld_price_matches_visible (structured_data, weight 2, deterministic): a price declared in JSON-LD must appear among the visible prices, compared by numeric value. FAILs only when ZERO declared prices are visible. Both price lists are recorded as evidence. coherence.jsonld_name_matches_visible (structured_data, weight 1, deterministic): a declared Product/Organization/Store name must appear in the title or visible text. coherence.language_declared_matches_content (readability, weight 1, heuristic): <html lang> compared against a conservative stopword/script language profile of the content; WARNs, never FAILs, and stays silent when unsure. The check set grows from 31 to 34 (33 scored). No claim is made that coherence affects AI citation rates - that measurement has not been done. What these checks demonstrate is per-site and factual: when the machine and human channels disagree, an agent trusting the machine channel quotes numbers and names the visible page does not show.sha 78f75e9
r2026.10.3deprecated2026-07-30A scan no longer describes a document the origin never served. When the landing page returns a non-2xx status, every check whose subject is that document reports no measurement; robots.txt, sitemap.xml and the /.well-known surface still report, because they are separate fetches, and reachability.status still fails, because the status code is its subject. Found in the corpus: the three highest text-ratio scores across 43 scans were a 404 and two 403s, at 90.0%, 77.6% and 40.2%, all PASS, while every site that served us a real page failed the same check. content.text_ratio requires a document of at least 2,048 bytes. Below that there is no markup weight to crowd out text, so the ratio measures rounding. Threshold set from the corpus, where every document under 16 KB passed and the smallest to return anything else was 33,794 bytes. A refused probe is no longer read as an absent resource. The /.well-known checks scored any unsuccessful probe as "not published", so a site blocking our user-agent was told to publish six files it may already serve. HTTP 401, 403, 407, 408, 429 and 5xx now report no measurement; 404, 410, a 200 with an invalid body, and 406 for Accept: text/markdown still fail, because each of those answers the question asked. New check family: operability (2 checks). Every check before this one graded what a page SAYS. None graded whether its controls can be worked by an agent driving the DOM, which is where agents actually fail. Published measurement, not assumption: on 300 tasks across 136 live sites the strongest agent succeeded 61.3% of the time, and filter and sorting errors caused 57.7% of its failures (arXiv:2504.01382); in a controlled experiment a call to action baked into an image was clicked 0/10 by every model tested versus 7/10 for the same action as a real element (arXiv:2507.12844). operability.primary_action_in_dom (actionability, weight 2, deterministic): a page that asks for an action must express it as a real clickable element. PASSes on the first link, button, or input carrying action language; SKIPs when the page asks for nothing; FAILs only when the words appear in image alt text or on a plain element and nothing clickable carries them. operability.filters_addressable (actionability, weight 2, deterministic): when a page offers to filter or sort a list, at least one filtered view must be reachable by URL, through a link with a query parameter or a GET form. WARNs when controls exist but produce no URL, FAILs when no operable control is served at all, SKIPs on pages with no facets. The check set grows from 34 to 36 (35 scored). No claim is made that operability changes citation or conversion rates. The cited research measures agent task success on other sites, not revenue on yours. These checks state something per-site and factual: the control is operable, or it is not. New check family: coherence (3 checks). The rubric so far verified each machine channel EXISTS - JSON-LD present, lang declared - but nothing verified the channels AGREE with each other or with what humans see. Disagreement is worse than absence: an absent price makes an agent hedge, a divergent one makes it quote the wrong number with confidence. Cross-channel agreement is also structurally un-gameable - the only way to game a consistency check is to become consistent. coherence.jsonld_price_matches_visible (structured_data, weight 2, deterministic): a price declared in JSON-LD must appear among the visible prices, compared by numeric value. FAILs only when ZERO declared prices are visible. Both price lists are recorded as evidence. coherence.jsonld_name_matches_visible (structured_data, weight 1, deterministic): a declared Product/Organization/Store name must appear in the title or visible text. coherence.language_declared_matches_content (readability, weight 1, heuristic): <html lang> compared against a conservative stopword/script language profile of the content; WARNs, never FAILs, and stays silent when unsure. The check set grows from 31 to 34 (33 scored). No claim is made that coherence affects AI citation rates - that measurement has not been done. What these checks demonstrate is per-site and factual: when the machine and human channels disagree, an agent trusting the machine channel quotes numbers and names the visible page does not show.sha 946257b
r2026.10.2deprecated2026-07-30New check family: operability (2 checks). Every check before this one graded what a page SAYS. None graded whether its controls can be worked by an agent driving the DOM, which is where agents actually fail. Published measurement, not assumption: on 300 tasks across 136 live sites the strongest agent succeeded 61.3% of the time, and filter and sorting errors caused 57.7% of its failures (arXiv:2504.01382); in a controlled experiment a call to action baked into an image was clicked 0/10 by every model tested versus 7/10 for the same action as a real element (arXiv:2507.12844). operability.primary_action_in_dom (actionability, weight 2, deterministic): a page that asks for an action must express it as a real clickable element. PASSes on the first link, button, or input carrying action language; SKIPs when the page asks for nothing; FAILs only when the words appear in image alt text or on a plain element and nothing clickable carries them. operability.filters_addressable (actionability, weight 2, deterministic): when a page offers to filter or sort a list, at least one filtered view must be reachable by URL, through a link with a query parameter or a GET form. WARNs when controls exist but produce no URL, FAILs when no operable control is served at all, SKIPs on pages with no facets. The check set grows from 34 to 36 (35 scored). No claim is made that operability changes citation or conversion rates. The cited research measures agent task success on other sites, not revenue on yours. These checks state something per-site and factual: the control is operable, or it is not. New check family: coherence (3 checks). The rubric so far verified each machine channel EXISTS - JSON-LD present, lang declared - but nothing verified the channels AGREE with each other or with what humans see. Disagreement is worse than absence: an absent price makes an agent hedge, a divergent one makes it quote the wrong number with confidence. Cross-channel agreement is also structurally un-gameable - the only way to game a consistency check is to become consistent. coherence.jsonld_price_matches_visible (structured_data, weight 2, deterministic): a price declared in JSON-LD must appear among the visible prices, compared by numeric value. FAILs only when ZERO declared prices are visible. Both price lists are recorded as evidence. coherence.jsonld_name_matches_visible (structured_data, weight 1, deterministic): a declared Product/Organization/Store name must appear in the title or visible text. coherence.language_declared_matches_content (readability, weight 1, heuristic): <html lang> compared against a conservative stopword/script language profile of the content; WARNs, never FAILs, and stays silent when unsure. The check set grows from 31 to 34 (33 scored). No claim is made that coherence affects AI citation rates - that measurement has not been done. What these checks demonstrate is per-site and factual: when the machine and human channels disagree, an agent trusting the machine channel quotes numbers and names the visible page does not show.sha a27e32e
r2026.10.1deprecated2026-07-30New check family: operability (2 checks). Every check before this one graded what a page SAYS. None graded whether its controls can be worked by an agent driving the DOM, which is where agents actually fail. Published measurement, not assumption: on 300 tasks across 136 live sites the strongest agent succeeded 61.3% of the time, and filter and sorting errors caused 57.7% of its failures (arXiv:2504.01382); in a controlled experiment a call to action baked into an image was clicked 0/10 by every model tested versus 7/10 for the same action as a real element (arXiv:2507.12844). operability.primary_action_in_dom (actionability, weight 2, deterministic): a page that asks for an action must express it as a real clickable element. PASSes on the first link, button, or input carrying action language; SKIPs when the page asks for nothing; FAILs only when the words appear in image alt text or on a plain element and nothing clickable carries them. operability.filters_addressable (actionability, weight 2, deterministic): when a page offers to filter or sort a list, at least one filtered view must be reachable by URL, through a link with a query parameter or a GET form. WARNs when controls exist but produce no URL, FAILs when no operable control is served at all, SKIPs on pages with no facets. The check set grows from 34 to 36 (35 scored). No claim is made that operability changes citation or conversion rates. The cited research measures agent task success on other sites, not revenue on yours. These checks state something per-site and factual: the control is operable, or it is not. New check family: coherence (3 checks). The rubric so far verified each machine channel EXISTS - JSON-LD present, lang declared - but nothing verified the channels AGREE with each other or with what humans see. Disagreement is worse than absence: an absent price makes an agent hedge, a divergent one makes it quote the wrong number with confidence. Cross-channel agreement is also structurally un-gameable - the only way to game a consistency check is to become consistent. coherence.jsonld_price_matches_visible (structured_data, weight 2, deterministic): a price declared in JSON-LD must appear among the visible prices, compared by numeric value. FAILs only when ZERO declared prices are visible. Both price lists are recorded as evidence. coherence.jsonld_name_matches_visible (structured_data, weight 1, deterministic): a declared Product/Organization/Store name must appear in the title or visible text. coherence.language_declared_matches_content (readability, weight 1, heuristic): <html lang> compared against a conservative stopword/script language profile of the content; WARNs, never FAILs, and stays silent when unsure. The check set grows from 31 to 34 (33 scored). No claim is made that coherence affects AI citation rates - that measurement has not been done. What these checks demonstrate is per-site and factual: when the machine and human channels disagree, an agent trusting the machine channel quotes numbers and names the visible page does not show.sha 0771b93
r2026.10.0deprecated2026-07-28New check family: operability (2 checks). Every check before this one graded what a page SAYS. None graded whether its controls can be worked by an agent driving the DOM, which is where agents actually fail. Published measurement, not assumption: on 300 tasks across 136 live sites the strongest agent succeeded 61.3% of the time, and filter and sorting errors caused 57.7% of its failures (arXiv:2504.01382); in a controlled experiment a call to action baked into an image was clicked 0/10 by every model tested versus 7/10 for the same action as a real element (arXiv:2507.12844). operability.primary_action_in_dom (actionability, weight 2, deterministic): a page that asks for an action must express it as a real clickable element. PASSes on the first link, button, or input carrying action language; SKIPs when the page asks for nothing; FAILs only when the words appear in image alt text or on a plain element and nothing clickable carries them. operability.filters_addressable (actionability, weight 2, deterministic): when a page offers to filter or sort a list, at least one filtered view must be reachable by URL, through a link with a query parameter or a GET form. WARNs when controls exist but produce no URL, FAILs when no operable control is served at all, SKIPs on pages with no facets. The check set grows from 34 to 36 (35 scored). No claim is made that operability changes citation or conversion rates. The cited research measures agent task success on other sites, not revenue on yours. These checks state something per-site and factual: the control is operable, or it is not. New check family: coherence (3 checks). The rubric so far verified each machine channel EXISTS - JSON-LD present, lang declared - but nothing verified the channels AGREE with each other or with what humans see. Disagreement is worse than absence: an absent price makes an agent hedge, a divergent one makes it quote the wrong number with confidence. Cross-channel agreement is also structurally un-gameable - the only way to game a consistency check is to become consistent. coherence.jsonld_price_matches_visible (structured_data, weight 2, deterministic): a price declared in JSON-LD must appear among the visible prices, compared by numeric value. FAILs only when ZERO declared prices are visible. Both price lists are recorded as evidence. coherence.jsonld_name_matches_visible (structured_data, weight 1, deterministic): a declared Product/Organization/Store name must appear in the title or visible text. coherence.language_declared_matches_content (readability, weight 1, heuristic): <html lang> compared against a conservative stopword/script language profile of the content; WARNs, never FAILs, and stays silent when unsure. The check set grows from 31 to 34 (33 scored). No claim is made that coherence affects AI citation rates - that measurement has not been done. What these checks demonstrate is per-site and factual: when the machine and human channels disagree, an agent trusting the machine channel quotes numbers and names the visible page does not show.sha 64ab233
r2026.09.0deprecated2026-07-27New check family: coherence (3 checks). The rubric so far verified each machine channel EXISTS - JSON-LD present, lang declared - but nothing verified the channels AGREE with each other or with what humans see. Disagreement is worse than absence: an absent price makes an agent hedge, a divergent one makes it quote the wrong number with confidence. Cross-channel agreement is also structurally un-gameable - the only way to game a consistency check is to become consistent. coherence.jsonld_price_matches_visible (structured_data, weight 2, deterministic): a price declared in JSON-LD must appear among the visible prices, compared by numeric value. FAILs only when ZERO declared prices are visible. Both price lists are recorded as evidence. coherence.jsonld_name_matches_visible (structured_data, weight 1, deterministic): a declared Product/Organization/Store name must appear in the title or visible text. coherence.language_declared_matches_content (readability, weight 1, heuristic): <html lang> compared against a conservative stopword/script language profile of the content; WARNs, never FAILs, and stays silent when unsure. The check set grows from 31 to 34 (33 scored). No claim is made that coherence affects AI citation rates - that measurement has not been done. What these checks demonstrate is per-site and factual: when the machine and human channels disagree, an agent trusting the machine channel quotes numbers and names the visible page does not show.sha caf8fc1
r2026.08.1deprecated2026-07-26New check markup.language (readability, weight 1, page-scoped): <html lang> must be present and a well-formed BCP 47 tag, and hreflang alternates must carry well-formed values when declared. The first language check in the rubric — an agent should not have to guess what language a document is in. The check set grows from 30 to 31. structured_data.type_coverage now recognises storefronts pricing in ¥ ₩ ₹ ₽ R$ and the major non-Western currency codes, with cart vocabulary in Japanese, Korean, Chinese, German, French, Spanish and Russian. Previously only $ € £ storefronts were evaluated; everyone else was "intent unclear" and passed by default. Sites affected lose a free pass, not points they had earned.sha 1710b08
r2026.08.0deprecated2026-07-26llms_txt.present is retired: still reported, no longer scored, and labelled unproven. Google states Search does not use llms.txt; a ~300,000-domain study found no correlation with AI citations and improved accuracy when the variable was removed; a 137,210-domain crawl found 97% of these files received zero requests in May 2026. Most requests they do receive come from SEO audit tools checking the file exists. It remains reported so a site can see its status, but ~4.5% of every score should not have rested on it. Sites without llms.txt score HIGHER under this version. performance.ttfb_ms drops from weight 2 to 1. The deployed scan path records total fetch time and labels it TTFB, and takes one sample from one location — a self-declared proxy should not carry the same weight as paywall or JS-dependency detection. This also keeps the rubric inside the §11.1 heuristic ceiling after llms_txt.present went to zero. robots_txt.allows_known_agents now scores Applebot, the crawler behind Siri and Spotlight answers. Only Applebot-Extended (the AI-training opt-out) was tracked before, so blocking the agent that decides whether Siri can recommend you cost nothing. The scored set goes from 8 access agents to 9, and sites blocking Applebot score lower under this version. Baiduspider, Sogou, PetalBot, YandexBot and Naver Yeti are recognised for the first time and reported when blocked, together with the markets a site declares via <html lang> and hreflang. They are NOT scored: blocking Baidu is a defect for a site selling into China and a reasonable choice for one that is not, and the two must not be charged the same. Every previously scored access agent was US-operated, so the score could not express "invisible to Chinese, Russian or Korean AI" at all. Weights, grade bands and the check set are unchanged.sha 8c8f95b
r2026.07.4deprecated2026-07-25structured_data.validates no longer penalises a JSON-LD block whose @type is outside the twenty types this validator implements. Such blocks were reported as warnings worth −5 each, so a page using SoftwareApplication, Course, JobPosting, or Book was docked for our coverage gap rather than for a defect in its markup. They are now informational and excluded from scoring. Weights, grade bands, and the check set are unchanged. structured_data.validates no longer reports a missing @context for nodes inside a @graph. @context is a document-level JSON-LD keyword that scopes the entire document, so graph nodes correctly omit it; the validator was flagging every node of the canonical multi-entity pattern. Sites using @graph score higher under this version. Weights, grade bands, and the check set are unchanged. robots_txt.allows_known_agents now scores only answer-time access agents (assistant fetchers and AI search indexers). Training-data crawler blocks (GPTBot, CCBot, Google-Extended, Bytespider, …) are reported as informational instead of failing the check — blocking AI training is a content-licensing choice, not an agent-readiness defect. Deprecated Claude-Web replaced with the documented Claude-User and Claude-SearchBot agents. Weights unchanged.sha ed23d54
r2026.07.3deprecated2026-07-25structured_data.validates no longer reports a missing @context for nodes inside a @graph. @context is a document-level JSON-LD keyword that scopes the entire document, so graph nodes correctly omit it; the validator was flagging every node of the canonical multi-entity pattern. Sites using @graph score higher under this version. Weights, grade bands, and the check set are unchanged. robots_txt.allows_known_agents now scores only answer-time access agents (assistant fetchers and AI search indexers). Training-data crawler blocks (GPTBot, CCBot, Google-Extended, Bytespider, …) are reported as informational instead of failing the check — blocking AI training is a content-licensing choice, not an agent-readiness defect. Deprecated Claude-Web replaced with the documented Claude-User and Claude-SearchBot agents. Weights unchanged.sha 3c6337b
r2026.07.2deprecated2026-07-23robots_txt.allows_known_agents now scores only answer-time access agents (assistant fetchers and AI search indexers). Training-data crawler blocks (GPTBot, CCBot, Google-Extended, Bytespider, …) are reported as informational instead of failing the check — blocking AI training is a content-licensing choice, not an agent-readiness defect. Deprecated Claude-Web replaced with the documented Claude-User and Claude-SearchBot agents. Weights unchanged.sha 07da708
r2026.07.1deprecated2026-07-20Rebalance weights after the first months of production scans: the five weight-2 emerging-standard checks (Content-Signal, MCP server card, markdown negotiation, Agent Skills, WebMCP) drop to weight 1; five established fundamentals (llms.txt, sitemap, canonical URL, title, meta description) rise to weight 2. Class shares are unchanged. Tag the nine agent-protocol checks introduced in r2026.04.2 as maturity: emerging so score surfaces label them as early-adoption opportunities rather than defects.sha adca6e8
r2026.04.2deprecated2026-04-27Rebalance per-check weights so the rubric satisfies the §11.1 class policy (deterministic ≥60%, heuristic ≤30%, ≤2 per LLM-assisted check). Add 10 checks aligned with 2026 agent-protocol standards: MCP server card, OAuth authorization-server + protected-resource discovery, API catalog, Web Bot Auth, Content-Signal directives, markdown content negotiation, Agent Skills manifest, WebMCP, HTTP Link headers.sha 7045eb0
r2026.04.1deprecated2026-04-01Initial rubric: 20 checks across 5 sub-scores.sha 2794c2b
§13 How to cite a score

A citation names the domain, the rubric version, the scan ID, and the scan timestamp:

stripe.com · r2026.11.0 · scan 1a2b3c4d · 2026-04-27T14:30Z

This is what appears at the top of every /score/<domain>/scan/<scanId> permalink. The scan ID is the canonical identifier; the other three fields are redundant context that travels with it.

The AgentSpeed Rubric · AgentSpeed