Score methodology

How the agent-readiness score is computed

The website checker reports a deterministic 0-100 agent-readiness score with a letter grade. This page is the formula. Every constant, every check and every threshold below is rendered from the same code that produces the score, so there is no unpublished formula and no hidden weighting.

Catalogv1.0.0
Formulav1.0.0
Checks scored now34
Required pool80
Recommended pool20
Bonus cap+5

What the score is

A deterministic 0-100 agent-readiness score for public content websites, computed from the 8 fetches the checker already makes (homepage, one sampled internal page, their markdown mirrors, llms.txt, robots.txt, the sitemap and a probe for a path that cannot exist). No LLM, no heuristics, no off-site search, and no extra request per check. The same engine runs in the browser on the checker page and in Node, and both compute identical numbers from the same evidence.

The score does not predict inclusion, ranking, traffic or citation by any AI system. It states what the fetched responses show, check by check, and how those checks add up under the rules below.

The lens

The structure is Essentials-shaped: required checks share a 80-point pool, recommended checks share 20 points, and bonus signals add 0.25 points each up to a cap of +5. That structure is modelled on the published Essentials layer of Ora (is-agentic.com, contract version 1.38.0, audit of agentmarkup.dev dated 2026-10-10). This is not Ora's score: Ora's headline grade is a different, layered lens, several of its checks need fetches this engine does not make, and the divergences are listed below. Agreement with Ora was checked on one site only; no calibration is claimed for any other site.

Status semantics

Each check ends in exactly one status. Only the first three sit in the denominator.

  • pass: fraction 1. Eligible.
  • partial: fraction strictly between 0 and 1, earning proportional credit. Eligible.
  • fail: fraction 0. Eligible.
  • not applicable: the applicability rule says the check does not apply to this site (no form fields, no served markdown, no API or MCP surface, a blocked homepage). Leaves the denominator; listed in the panel with the reason.
  • could not be verified: the evidence the check needs did not complete (status 0, a transport error, a 2xx without a body, a skipped fetch, a 429 or a 5xx without challenge markers). Leaves the denominator. One such check marks the whole run provisional: the panel shows the score with a pessimistic-to-optimistic range (every unverified check at fraction 0 and at fraction 1), the worker never caches the run, and it is never stored as a monthly reading. A timed-out fetch therefore never lowers the score.
  • not measured: listed in the catalog for parity but not implemented in this version. Leaves the denominator.

Two homepage rules sit above everything else. If the homepage itself could not be verified, every check is unverified, the run is blocked and there is no score. If the homepage answers a bot challenge or a 401/403, reach.bot-detection scores 0 with the status and marker quoted, every other homepage-derived check is not applicable, and the score is computed from what remains (robots.txt, llms.txt, the sitemap and the probe). A challenge page is never evaluated for headings, JSON-LD or landmarks.

The catalog

48 rows: 34 scored in catalog 1.0.0 (9 required, 10 recommended, 15 bonus), 3 that need one extra fetch each and wait for a catalog 2.0 decision, and 11 listed for parity with Ora's catalog and not measured (off-site search, API, MCP and payment surfaces). Each row names its bucket, what it reads, the exact rule with thresholds, the Ora counterpart, and the sentence a non-technical client sees on a pass and on a fail.

Required checks

80-point pool, even weight over eligible checks.

CheckBucketApplies whenReadsRuleStatus in this versionOra counterpart
Not blocked by bot detection
reach.bot-detectionPass: AI assistants can open your homepage.Fail: Your site's bot protection turns AI assistants away.
reachabilityAlways.Homepage status, the cf-mitigated header and the first 20,480 characters of the body.A 2xx HTML homepage with no challenge marker scores 1. A challenge page, or a 401/403 without markers, scores 0 and the evidence quotes the status and the marker. Status 0, 429 or 5xx without markers, or a null body, is unverified and the whole run is blocked.Scored (catalog 1.0.0)bot-detection
Content without JavaScript
content.no-jsPass: Your page text is in the page itself, so AI can read it without running scripts.Fail: Your page has little readable text in its HTML, so AI readers see little of what you offer.Partial: Part of your page text or its main heading is missing from the HTML, so AI readers see less than your visitors do.When client shell: Your page text only appears after scripts run, so most AI readers see an empty page.
contentAlways.Homepage body; sample page body when the sample completed.Sub-rules: homepage text of at least 500 characters and not a client shell; a non-empty h1; sample page text of at least 500 characters (only when the sample completed). Page text is the body text without script, style, noscript, template, svg, canvas, iframe and form blocks, so form labels and options never count. Fraction = passed / applicable sub-rules.Scored (catalog 1.0.0)content-no-js
Public content not behind a login
content.auth-gatePass: Your content pages are open, not hidden behind a login.Fail: Your public pages ask for a login before showing content.
contentAlways; judged on the homepage alone when the sample page is absent or unverified (the evidence says so).Homepage and sample page status and body.Any sampled page answering 401 or 403, or showing a password field with under 500 characters of text, scores 0; otherwise 1.Scored (catalog 1.0.0)docs-auth-gate
Document structure
ax.document-structurePass: Your page marks where the main content and the menu are and has an ordered outline.Fail: Your page does not mark where the main content and the menu are, or its headings skip levels, so an AI cannot outline it.Partial: Your page marks part of its structure, but the main content, the menu or the heading order is still missing or out of order.
controlsAlways.Homepage body outside script, style, template, noscript and svg.Three sub-rules: a main element or role=main; a nav element or role=navigation; a sane heading order (the first heading is an h1 and no level is skipped when descending, h2 to h4 is a skip). Fraction = passed / 3. A static-HTML proxy of the accessibility-tree check, published as such.Scored (catalog 1.0.0)ax-document-structure
Native interactive controls
ax.native-controlsPass: Your buttons are real buttons, not styled boxes an AI cannot press.Fail: Some of your buttons are styled boxes, not real buttons, so an AI cannot press them.
controlsAlways.Homepage body.Count of div, span, li, p, section, img and td elements carrying an onclick attribute or role=button: 0 scores 1; 1 to 2 score 0.5; 3 or more score 0. Count-based; handlers bound from scripts are not visible, published as such.Scored (catalog 1.0.0)ax-native-controls
Accessible names on controls
ax.accessible-namesPass: Every link and button has a name an AI can use.Fail: Some links and buttons have no name, so an AI cannot tell what they do.
controlsNot applicable when the homepage has zero controls.Homepage body.Controls are button, a[href], input[type=submit|button|image] and [role=button]. A control is named by non-empty text, aria-label, aria-labelledby, title, a child img[alt], a child svg title, value, or alt on an image input. Fraction = named / total, proportional to 3 decimals, never banded.Scored (catalog 1.0.0)ax-accessible-names
Form control labelling
ax.form-labelingPass: Your form fields are labeled so an AI knows what to type where.Fail: Some form fields have no label, so an AI does not know what to type where.Partial: Some of your form fields have labels and others do not, so an AI has to guess what to type in those.
controlsNot applicable when the homepage has no fields (input other than hidden, submit, button, reset or image; select; textarea).Homepage body.A field is labelled by a label[for] matching its id, a wrapping label, aria-label, aria-labelledby or a non-empty title (HTML-AAM names a control from its title when nothing else does). A placeholder never counts. Fraction = labelled / total, proportional.Scored (catalog 1.0.0)ax-form-labeling
Agent crawler reachability
reach.agent-uaPass: AI assistants that identify themselves can open your homepage.Fail: AI assistants that identify themselves are turned away from your homepage.
reachabilityAlways (catalog 2.0).One extra homepage GET with an agent User-Agent (ChatGPT-User), up to 2 redirects.Same status class as the checker fetch and no challenge scores 1; 401, 403 or a challenge scores 0 ("blocked for unverified bots"); 429, 5xx or status 0 is unverified. Not measured in catalog 1.x (needs one extra fetch).Not measured: needs one extra fetch, a catalog 2.0 decisionagent-crawler-reachability
Markdown content negotiation
content.markdown-negotiationPass: Your pages can be requested as plain markdown by an AI that asks for it.Fail: Your pages cannot be requested as plain markdown.
contentAlways (catalog 2.0).One extra homepage GET with Accept: text/markdown, capturing Content-Type and Vary.A text/markdown body of at least 20 characters with Vary containing Accept scores 1; markdown without Vary scores 0.5; HTML scores 0. Not measured in catalog 1.x (needs one extra fetch).Not measured: needs one extra fetch, a catalog 2.0 decisionmarkdown-negotiation-vary
API surface: OpenAPI spec, OAuth support, scoped permissions, JSON error responses, RFC 9728 metadata
api.required-groupPass: Your API is described and secured in the standard way.Fail: Your API is missing a standard description or security metadata.
reachabilityNot applicable unless an API surface is detected.None in this version.Not measured; listed so the denominator rule is explicit.Not measured: listed for parity; not applicable without a api surfaceopenapi-spec, oauth-support, scoped-permissions, json-error-responses, oauth-protected-resource
MCP surface: server identity, tools and views
mcp.required-groupPass: Your MCP server identifies itself and describes its tools.Fail: Your MCP server is missing identity or tool descriptions.
reachabilityNot applicable unless an MCP surface is detected.None in this version.Not measured; listed so the denominator rule is explicit.Not measured: listed for parity; not applicable without a mcp surfacemcp-server-identity ... mcp-view-csp

Recommended checks

20-point pool, even weight over eligible checks.

CheckBucketApplies whenReadsRuleStatus in this versionOra counterpart
Metadata completeness
meta.completenessPass: Your homepage carries its basic labels: official address, language, preview image and type.Fail: Your homepage is missing some basic labels (official address, language, preview image or type).Partial: Your homepage has some of its basic labels but not all of them (official address, language, preview image or type).
identityAlways.Homepage head and the final homepage URL.Four sub-rules: a canonical link that resolves to the homepage itself (same scheme and host, path equal after trailing-slash normalisation); a non-empty html lang attribute; an og:image; an og:type. Fraction = present / 4.Scored (catalog 1.0.0)metadata-completeness
Homepage indexable
meta.noindexPass: Your homepage is not marked "hide me" for search engines and AI.Fail: Your homepage is marked "hide me" for search engines and AI.
identityAlways.meta robots, googlebot and bingbot tags and the X-Robots-Tag header on the homepage.Any noindex or none directive scores 0; otherwise 1.Scored (catalog 1.0.0)noindex-directives
JSON-LD identity
jsonld.identityPass: Your site tells AI who you are (name, website, description) in a format it understands.Fail: Your site does not tell AI who you are in a format it understands.
identityAlways.Homepage JSON-LD blocks, @graph flattened, @id references resolved, parseable blocks only (an unparseable block is reported by jsonld.syntax).An identity node present scores 0.25, plus 0.25 each for name, url and description on it. No parseable identity node scores 0.Scored (catalog 1.0.0)json-ld
Organization schema completeness
jsonld.org-completenessPass: Your business listing includes an address and a way to contact you.Fail: Your business listing is missing an address or a way to contact you.When no address: Your business listing for AI has a way to contact you but no street address or city.When no contact: Your business listing for AI has your address but no phone number or email.When no contact point: Your business listing for AI has your address and a phone number or email, but not as a contact point, the entry AI assistants read for how to reach you.
identityNot applicable when the only identity node is a Person.The identity node with @id references resolved.An address resolving to a PostalAddress with streetAddress or addressLocality scores 0.5; a contactPoint with telephone or email scores 0.5, or a top-level telephone or email alone scores 0.25. No Organization or LocalBusiness node scores 0.Scored (catalog 1.0.0)org-schema-completeness
Sitemap exists
sitemap.validPass: AI and search engines can get a list of all your pages.Fail: AI and search engines cannot get a list of all your pages.
discoveryAlways.The robots-declared sitemap (same registrable domain as the final homepage origin) or /sitemap.xml.A body containing a urlset or sitemapindex element scores 1 (index children are not fetched, published as such). A 404 or a non-XML body scores 0. A fetch that did not complete is unverified: "declared in robots.txt at URL but could not be verified in time".Scored (catalog 1.0.0)sitemap
Trust anchor pages linked
trust.anchorsPass: Your site has About, Contact and Privacy pages linked from the homepage.Fail: Your homepage does not link About, Contact and Privacy pages.Partial: Your homepage links some, but not all, of your About, Contact and Privacy pages.
identityAlways.Homepage anchors resolved against the final homepage URL.Same-origin links whose first path segment matches about(-us|-me), who-we-are, our-story; contact(-us), get-in-touch; privacy(-policy|-notice), legal/privacy; or whose text equals About, About us, Contact, Contact us, Privacy or Privacy policy. Fraction = found / 3. Content depth is not measured, published as such.Scored (catalog 1.0.0)trust-anchors
Page token budget
content.token-budgetPass: Your pages are not so long that an AI runs out of room reading them.Fail: One of your pages is so long that an AI runs out of room reading it.
contentAlways.Homepage and sample page text.The largest sampled page text of at most 100,000 characters scores 1; otherwise 0. The evidence reports the length and an estimate at 4 characters per token.Scored (catalog 1.0.0)page-token-budget
Agent instruction in llms.txt
llms.agent-instructionPass: Your site has a short guide (llms.txt) that tells AI what you offer and when to use it.Fail: Your site has no short guide (llms.txt) telling AI what you offer and when to use it.Partial: Your short guide for AI (llms.txt) says what you offer but not when to use it.
discoveryAlways./llms.txt as a text resource.A heading or sentence with explicit guidance scores 1: 'when to use', 'best fit for/when' or 'instructions for (AI) agents' anywhere; 'use X when' (zero to three words for X) or 'do not use X for/when' (one to three words) as an instruction, at the start of a line, sentence or list item or after should, can, may, must or please, optionally opened by one of only, always, never or also; or a heading containing 'use cases' or 'for agents'. A summary blockquote of at least 100 characters after the H1 scores 0.5. Absent, HTML, or under 100 characters of text scores 0. A fetch that did not complete is unverified. A presence rule, not a semantic one.Scored (catalog 1.0.0)agent-instruction
Code fence validity
markdown.code-fencesPass: Code blocks in your text files are properly closed.Fail: A code block in one of your text files is not closed.
contentNot applicable when no served markdown (llms.txt, /index.md, the sample .md) contains a line starting with ``` or ~~~.Served markdown bodies.Every file with an even count of fence lines scores 1; otherwise 0.Scored (catalog 1.0.0)code-fence-validity
AI search and agent-user access
robots.ai-search-accessPass: Your robots.txt lets AI search assistants read your public pages. Blocking training bots is your choice and never lowers this score.Fail: Your robots.txt blocks AI search assistants from your public pages. Blocking training bots is your choice and never lowers this score.
reachabilityAlways./robots.txt as a text resource (an HTML body or a 404 means absent, which allows everything).The six AI search and user agents (OAI-SearchBot, Claude-SearchBot, PerplexityBot, ChatGPT-User, Claude-User, Perplexity-User) root-allowed under RFC 9309 group logic (own group, else *). Fraction = allowed / 6. Training-crawler blocks are reported as a policy note and never subtract. A fetch that did not complete is unverified.Scored (catalog 1.0.0)robots-ai-policy-quality, robots-agent-user-policy
Brand discoverability
search.brand-accuracyPass: Searching your brand name finds your site first.Fail: Searching your brand name does not find your site first.
discoveryAlways.Off-site search.Not measured (off-site search is out of scope).Not measured: listed for parity with the Ora catalogbrand-search-accuracy
Developer resource discoverability
search.developer-resourcesPass: Searching for your API finds your developer docs.Fail: Searching for your API does not find your developer docs.
discoveryNot applicable unless an API surface is detected.Off-site search.Not measured (off-site search is out of scope).Not measured: listed for parity; not applicable without a api surfaceagentic-search-specific
Pricing info accessible
commerce.pricing-infoPass: Your prices are published where an AI can read them.Fail: Your prices are not published where an AI can read them.
identityNot applicable unless a commerce surface is detected.A /pricing link or Offer JSON-LD.Not measured in catalog 1.0.Not measured: listed for parity; not applicable without a commerce surfacepricing-info
API surface: docs, portal, error model, versioning, SDKs, GraphQL
api.recommended-groupPass: Your API is documented the way agents expect.Fail: Your API documentation is missing pieces agents expect.
discoveryNot applicable unless an API surface is detected.None in this version.Not measured.Not measured: listed for parity; not applicable without a api surfacepublic-api-docs, developer-portal, public-api, rate-limit-headers, api-error-model, api-versioning-policy, response-schema-coverage, api-schema-analysis, function-calling-compat, onboarding-friction, cli-tool, agent-auth-www-authenticate, api-catalog-rfc9727, graphql-*
MCP surface: server, tools, parameter schemas, resources
mcp.recommended-groupPass: Your MCP server describes its tools the way agents expect.Fail: Your MCP server is missing tool descriptions agents expect.
discoveryNot applicable unless an MCP surface is detected (divergence: Ora scores mcp-server for every site).None in this version.Not measured.Not measured: listed for parity; not applicable without a mcp surfacemcp-server, mcp-tool-*, mcp-param-schemas, mcp-resource-quality

Bonus signals

0.25 points each times the fraction, capped at +5, never subtracts.

CheckBucketApplies whenReadsRuleStatus in this versionOra counterpart
llms.txt exists with real content
llms.existsPass: Your site publishes an llms.txt guide for AI.Fail: Your site does not publish an llms.txt guide for AI.
discoveryAlways./llms.txt.A text resource with at least 100 characters after whitespace collapse scores 1; otherwise 0.Scored (catalog 1.0.0)llms-txt-exists
llms.txt formatting
llms.formattingPass: Your llms.txt follows the expected layout.Fail: Your llms.txt does not follow the expected layout.
discoveryNot applicable without llms.txt./llms.txt.Four sub-rules: an H1 on the first non-blank line (BOM tolerated); at least one markdown link to http(s); under 30,000 characters; at least one ## section. Fraction = passed / 4.Scored (catalog 1.0.0)llms-txt-formatting
Modular llms.txt
llms.modularPass: Your llms.txt links to a fuller version for AI that wants more.Fail: Your llms.txt does not link to a fuller version.
discoveryNot applicable without llms.txt./llms.txt.A link to llms-full.txt or to another /llms.txt scores 1.Scored (catalog 1.0.0)modular-llms-txt
Markdown URL fallback
markdown.url-fallbackPass: Your pages have plain-text twins (.md) that AI can read directly.Fail: Your pages have no plain-text twins (.md) for AI to read directly.
contentAlways./index.md (or the alternate-link target) and the sample page .md.A mirror served as markdown (text/markdown, or a non-HTML body starting with # after optional frontmatter) scores its share: homepage mirror 0.5 and sample mirror 0.5 (the homepage mirror alone when no sample page exists). A mirror that did not complete makes the check unverified.Scored (catalog 1.0.0)markdown-url-fallback
Markdown frontmatter
markdown.frontmatterPass: Your plain-text twins carry a title header.Fail: Your plain-text twins do not carry a title header.
contentNot applicable when no markdown is served.Served .md bodies.A leading --- block with a title: line on each served file. Fraction = files with it / files served.Scored (catalog 1.0.0)markdown-frontmatter
Entity linking (sameAs)
jsonld.same-asPass: Your site links your official profiles so AI can confirm who you are.Fail: Your site does not link your official profiles for AI to confirm who you are.
identityNot applicable without an identity node.The identity node.At least two absolute http(s) sameAs URLs score 1; exactly one scores 0.5.Scored (catalog 1.0.0)json-ld-entity-linking
Schema type breadth
jsonld.type-breadthPass: Your structured data describes more than the basics (services, articles, FAQs).Fail: Your structured data only covers the basics.
identityNot applicable without JSON-LD.All JSON-LD @type values.Distinct types beyond the baseline set (Organization, WebSite, WebPage, BreadcrumbList, ImageObject, PostalAddress, ListItem, SiteNavigationElement, ReadAction, SearchAction, EntryPoint, PropertyValueSpecification, ContactPoint, Place, GeoCoordinates, OpeningHoursSpecification): two or more score 1, one scores 0.5.Scored (catalog 1.0.0)schema-type-breadth
JSON-LD blocks parse
jsonld.syntaxPass: Your structured data is valid.Fail: One of your structured data blocks is broken, so AI ignores it.
identityNot applicable when the homepage has no script type=application/ld+json.Every JSON-LD block.All blocks parse as JSON scores 1; any block that fails scores 0 and the evidence names the block index and the parse position. Shown as an error-level finding although it never subtracts from the score.Scored (catalog 1.0.0)json-ld
Sitemap freshness
sitemap.lastmodPass: Your sitemap tells AI when pages last changed.Fail: Your sitemap does not tell AI when pages last changed.
discoveryNot applicable when the sitemap is an index, absent or unverified.The urlset body and the fetch time.At least 50% of url entries carry a parseable lastmod and the newest is within 365 days of the fetch scores 1; coverage without freshness scores 0.5.Scored (catalog 1.0.0)sitemap-lastmod
HTTP Link discovery headers
link.headers-discoveryPass: Your server advertises your sitemap or markdown in its headers.Fail: Your server does not advertise your sitemap or markdown in its headers.
discoveryAlways (not applicable when response headers were not captured).The homepage Link header (captured, zero fetches).A Link header carrying rel=sitemap or type=text/markdown scores 1.Scored (catalog 1.0.0)link-headers-discovery
Accessibility-tree injection safety
ax.injection-safePass: Your page carries no hidden instructions aimed at AI readers.Fail: Your page carries hidden text that looks like instructions aimed at AI readers.
controlsAlways.alt, aria-label and title attribute text, and the text of aria-hidden or hidden elements.No pattern from the published list (ignore previous instructions, you are an ai, as an ai assistant, system prompt, disregard the above) scores 1; otherwise 0.Scored (catalog 1.0.0)ax-tree-injection-safe
Content-Signal declared
robots.content-signalPass: Your site states its content policy for AI in robots.txt.Fail: Your site does not state its content policy for AI in robots.txt.
reachabilityNot applicable when robots.txt is absent./robots.txt.A Content-Signal line that parses to at least one key=value directive (ai-train, search, ai-input, use) scores 1.Scored (catalog 1.0.0)none (agentmarkup only)
Markdown for agent user agents
markdown.agent-uaPass: AI user agents get your homepage as markdown.Fail: AI user agents get your homepage as HTML only.
contentAlways (catalog 2.0, shares the reach.agent-ua fetch).The agent-UA homepage response.An agent-UA homepage answered as text/markdown scores 1. Not measured in catalog 1.x.Not measured: needs one extra fetch, a catalog 2.0 decisionagent-ua-markdown
A2A agent card
a2a.agent-cardPass: Your site publishes an agent card.Fail: Your site does not publish an agent card.
discoveryAlways (needs one extra fetch).GET /.well-known/agent-card.json.A card that parses with name and url scores 1. Not measured in catalog 1.x.Not measured: listed for parity with the Ora cataloga2a-agent-card
Well-known agent skills file
agent.discovery-filePass: Your site publishes an agent skills file.Fail: Your site does not publish an agent skills file.
discoveryAlways (needs one extra fetch).None in this version.Not measured.Not measured: listed for parity with the Ora catalogagent-discovery-file
MCP discovery
mcp.well-knownPass: Your site advertises an MCP server.Fail: Your site does not advertise an MCP server.
discoveryAlways (needs one extra fetch).None in this version.Not measured.Not measured: listed for parity with the Ora catalogmcp-well-known-discovery

Formula v1.0.0 and grade bands

  1. The eligible set per tier is the checks in that tier with status pass, partial or fail. Not applicable, could-not-be-verified and not-measured checks leave the denominator.
  2. required.earned = 80 x sum(fraction over eligible required) / count(eligible required), and recommended.earned = 20 x sum(fraction over eligible recommended) / count(eligible recommended). Partial results earn proportional credit.
  3. bonus.points = min(5, 0.25 x sum(fraction over bonus checks with status pass or partial)). The absence of a bonus signal never subtracts. With 15 bonus signals scored now the maximum is 3.75 points before the cap binds.
  4. raw = required.earned + recommended.earned + bonus.points, reported to two decimals beside the integer; score = min(100, round-half-up(raw)).
  5. The grade comes from the bands below and the label from the grade. The bands are agentmarkup's own: they are not evidenced in any Ora file or page.
  6. A run is complete when no check and no fetched resource is unverified, and provisional when any is, with the pessimistic-to-optimistic range taken from the unverified checks (equal to the score when only a resource is unverified). It is blocked, with no score, when the homepage could not be fetched (a re-run may succeed) or when the site root gave a final non-2xx answer other than 401 or 403 (nothing to score until the root serves a page). A 401, a 403 or a challenge page is scored as described under status semantics.
  7. A tier with zero eligible checks contributes 0 and is reported as not applicable. This cannot happen for the required tier on a reachable HTML homepage because reach.bot-detection is always eligible.
  8. The catalog and formula versions are embedded in every report; a comparison between reports with different major versions is refused ("formula changed, re-baseline").
GradeScoreLabel
A+95 to 100Agent-ready
A86 to 94Strong fundamentals, small gaps
B70 to 85Readable, with fixable gaps
C48 to 69Partly readable
D28 to 47Hard for agents
F0 to 27Agents cannot use this site

Quantisation

Required steps are 80 / N for N eligible required checks: 8.9 points per full fail at N = 9 (every required check eligible), 10.0 at N = 8 (for example, a homepage without form fields). One required flip can cross a grade band. This is inherent to the pool structure; the mitigations are that an unverified check never counts, that multi-rule checks earn proportional credit, that the raw score is shown beside the integer, and that transient HTTP states (429, 5xx) never score.

Estimated gain and top fixes

Every non-passing eligible check carries the gain this score would get if the check reached fraction 1 with the current denominator:

  • required / recommended: round1((1 - fraction) x pool / count(eligible in tier))
  • bonus: round2(min((1 - fraction) x 0.25, 5 - bonus.points))
  • null when the check already passes; not applicable, unverified and not-measured checks never carry a gain.

Top fixes are ranked by estimated gain, then tier (required, recommended, bonus), then catalog order; the panel lists the first 5. Gains assume the current denominator: a fix that makes other checks eligible (serving markdown makes markdown.code-fences eligible) changes the count, so gains are estimates. When the score is already 100 the panel says "at the cap" and still lists the remaining gains so required gaps stay visible.

Divergences from Ora

  • A real 404 or 410 for a path that cannot exist earns full credit on nav.not-found; an agent-readable (markdown or JSON) 404 body is the separate bonus nav.not-found-markdown. Ora gives partial credit for the status alone.
  • The two robots.txt policy checks are scored as one recommended check, robots.ai-search-access, over the AI search and agent user agents only. Blocking training crawlers is reported as a policy note and never subtracts.
  • MCP and API checks are not applicable to a site without an MCP or API surface, so a public content website is not penalized for omitting an interface it does not provide. Ora scores mcp-server for every site.
  • The ax.* checks are static-HTML proxies of a browser accessibility tree: they count elements and attributes in the served HTML and cannot see handlers bound by JavaScript.
  • trust.anchors measures whether About, Contact and Privacy pages are linked from the homepage, not the depth of those pages.
  • llms.agent-instruction is a presence rule: it looks for explicit guidance wording or a summary blockquote, not for the quality of the advice.
  • jsonld.identity is evaluated over parseable JSON-LD blocks only; an unparseable block is reported by jsonld.syntax, an upside-only bonus shown as an error-level finding that never subtracts from the score.
  • A check whose evidence never completed (a timed-out or failed fetch, a 429 or a 5xx without challenge markers) is unverified: it leaves the denominator, marks the run provisional with a pessimistic-to-optimistic range, and is never cached or stored.

Sampling, caps and published lists

  • Sample page: the first same-origin link in document order on the homepage, resolved against the final homepage URL after redirects. Every report names it; a navigation reorder can change it.
  • Same origin is judged against the origin of the final homepage URL, never the requested one, so an apex-to-www redirect does not fail trust.anchors.
  • Evaluation cap: checks read at most the first 1,048,576 characters of any body; a truncated body is flagged in the evidence.
  • Missing-path probe: /agentmarkup-probe-404-does-not-exist-9f3a2c at the final-URL origin, following no redirects, with Accept: text/markdown, application/json;q=0.9, text/html;q=0.8, */*;q=0.1 so a compliant negotiator can answer markdown or JSON.
  • Challenge markers (a response header cf-mitigated containing challenge, or any of these strings in the first 20,480 characters of the body): __cf_chl, challenge-platform, cf-browser-verification, Just a moment..., Attention Required!, Enable JavaScript and cookies to continue, Pardon Our Interruption, _Incapsula_Resource, captcha-delivery, px-captcha. Additions bump the catalog minor version.
  • AI search and agent user agents scored by robots.ai-search-access: OAI-SearchBot, Claude-SearchBot, PerplexityBot, ChatGPT-User, Claude-User, Perplexity-User.
  • Training crawlers reported as a policy note, never scored: GPTBot, ClaudeBot, Google-Extended, CCBot.
  • Text resource: a 2xx response whose content type is not HTML and whose body is not an HTML document. A host answering 200 HTML for llms.txt, robots.txt or a markdown URL reads as absent for that resource; a 200 status is not proof.

Versioning

The catalog and the formula carry semantic versions. Any change to required or recommended membership (adding, removing or re-tiering a check) bumps the catalog MAJOR version because it changes denominators; a rule change inside a check bumps MINOR; a copy-only change bumps PATCH. Scores compare only within a major version, and every report embeds both versions so a stale comparison is refused instead of silently mixing formulas. The 3 checks that need an extra fetch are therefore a catalog 2.0 decision, not a point release.

Reproduce it yourself

The checker's "Technical details and resources" panel shows the fetched resources, and every finding carries the evidence string the rule read: counts, ids, URLs, attribute and header values, never raw HTML. The engine itself is open source in the agentmarkup repository under packages/core/src/score/ as the score entry of @agentmarkup/core (evaluateSiteChecks and scoreChecks). From Node, npx @agentmarkup/audit <url> --score prints the same report once the audit release that carries the flag is on npm.

Change log

  • Catalog 1.0.0 and formula 1.0.0 (November 2026): first public version. 34 checks scored with zero extra fetches, 3 awaiting a catalog 2.0 decision, 11 listed for parity and not measured.