# AgenticWebScore — documentation > AgenticWebScore measures how well a website serves AI agents. Its 61 checks in 5 dimensions give a score you can recompute and a fix for every failure. Rubric v0.7 · 61 checks · 5 dimensions · 60 skill packs. Generated from a single content store. Every section below is also a page on https://agenticwebscore.com. 78 of the 81 routes in the sitemap are below: every page in the page registry and every learn article. The 3 routes without a markdown twin are not: `/scan`, `/directory`, `/learn`. They serve HTML only. --- # Agent readiness, measured from the outside > Find out whether AI agents can read your site. AgenticWebScore runs 61 checks from the outside and gives a fix for every failure. - Source: / - Site: AgenticWebScore - Language: English --- AgenticWebScore measures agent readiness: how well a website serves an agent that has no browser. It fetches a public domain from the outside, the way an agent would. It scores what it observed against a versioned rubric of 61 checks in 5 dimensions. Every failed check comes with a fix. Lighthouse runs in a browser. This scanner uses a plain HTTP client, and it gives no score to a site it cannot measure. ## The problem The web was built for people with screens. An agent fails on it in ways a browser never shows: | Failure | The agent's experience | | --- | --- | | No /llms.txt, no /AGENTS.md | Must crawl everything to learn anything | | Client-side rendering only | 200 OK and almost no readable text | | SPA wildcard fallback | 200 OK plus HTML for /llms.txt: silent, confident, wrong | | Parked domain | Every path returns 200 with a parking page | | No API contract | The agent guesses endpoints and produces broken calls | | No bot identity | The site cannot tell a signed agent from a scraper | | No agent payment declaration | The agent finds no declared way to pay | | IP-level blocking | Nobody can measure the site at all | ## The dimensions | Dimension | Weight | Question | | --- | --- | --- | | Protocol Discovery | 25% | Do you expose your service as a callable tool and an authorisable API? | | Content Accessibility | 22% | Is your content genuinely readable as markdown, semantic structure and structured data? | | Discoverability | 20% | Can an agent find you, reach the right page and understand what you offer? | | Bot Access Control | 18% | Can you tell agent traffic apart by identity? | | Commerce Protocols | 15% (conditional) | Which standard do you accept agent-initiated transactions over? | > Commerce is conditional: its checks leave the denominator unless the site shows a commercial signal. A site with no commercial signal is not penalised for having no payment standard. ## How it works 1. Fetch public paths only: a fixed list of 103, plus a capped set of URLs the site's own documents name. Each response is read to at most 3 MB, and no JavaScript is executed. 2. Run the 61 checks against what was fetched. No check makes a request of its own. 3. Weight and combine. Tier pools of 80 / 20 / up to 5 points produce a score, a grade, and a readiness level. 4. Fingerprint the result with SHA-256. The fingerprint binds the host, the rubric version, and each check's id, status, rounded points, and counted flag. /verify recomputes the score, grade, and level from those and reports a mismatch as tamper evidence. The detail and evidence text and the site profile are not bound. The commercial signal and the out-of-scope or not-measured label are not bound either, so only an edit that the bound outcomes contradict is caught. ## This site's own surfaces This site publishes the surfaces below. Each is served now and generated from one content source. It does not pass every check in its own rubric. - `/llms.txt` — llms.txt: Structured summary for language models - `/llms-full.txt` — llms-full.txt: Every page in the page registry and every learn article, in one markdown document - `/AGENTS.md` — AGENTS.md: Build, test and contribution contract for coding agents - `/sitemap.md` — sitemap.md: Every page as a markdown link list - `/sitemap.xml` — sitemap.xml: Machine sitemap with lastmod - `/index.json` — index.json: Typed index of every page and surface - `/rubric.json` — rubric.json: The complete rubric, machine-readable - `/robots.txt` — robots.txt: Named AI crawler rules plus Content-Signal - `/ai.txt` — ai.txt: Plain-language access declaration - `/auth.md` — auth.md: How an agent authenticates (and what is public) - `/ai-policy` — AI policy: Crawling, training, commercial use, contact - `/bot` — Agent policy: Bot identity, rates and contact - `/privacy` — Privacy: What is stored, how long it stays, and what is not collected - `/terms` — Terms of use: What a measurement is, what the API allows, and what the badge licence grants - `/abuse` — Abuse and removal: What the scanner requests, how to block it, and how to request removal - `/.well-known/agent-permissions.json` — agent-permissions.json: Allow, deny and human-approval rules - `/.well-known/mcp/server-card.json` — MCP server card: A declaration only: the planned transport and tools are recorded in x-planned fields, no /mcp endpoint is running, and the scanner reads the card as partial rather than as a server an agent can call - `/.well-known/api-catalog` — api-catalog: RFC 9727 catalog of callable APIs. Its targets are absolute URLs on the canonical origin, so a scan of any other host reports them as declared rather than observed, and the scanner scores it partial - `/openapi.json` — openapi.json: OpenAPI description of the API endpoints that answer today - `/.well-known/agent-skills/index.json` — agent-skills index: 60 publishable skill packs covering all 61 checks - `/.well-known/security.txt` — security.txt: RFC 9116 vulnerability disclosure - `/.well-known/dns-aid.json` — dns-aid.json: The DNS-AID records this domain declares, documented in this file and not yet in the zone ## Questions ### What is agent readiness? It is whether an autonomous agent can find your site, read it, trust it, and act on it without a human in the loop. That is narrower than SEO and different from AI visibility: it measures the machine-facing contract, not your ranking or your brand mentions. ### How is this different from Lighthouse? Lighthouse runs in a browser and audits one page at a time, its agentic browsing audits included. This scanner uses a plain HTTP client and no browser. The scanner requests a fixed list of 103 paths, plus a capped set of URLs the site's documents name. It scores what it observed against a published rubric and publishes a record with a fingerprint. A site can use both. ### Why does a blocked site get no score instead of a low one? A site that returns 403 or 429 to every automated client has told us nothing about itself. It has told us something about our vantage point. So the result is no score, with an explanation, rather than a number. ### Will it tell me to fix things that do not apply to my site? No. The scanner decides what kind of site it is looking at before it scores anything. Checks that apply only to other kinds of site are reported as out of scope, not as failures. If the site profile cannot be confirmed, those checks leave the denominator, and the report says so. ### Can I verify a score someone shows me? Yes, within limits: every record carries a fingerprint. The fingerprint binds the host, the rubric version, and each check's id, status, rounded points, and counted flag. /verify recomputes the score, grade, and level from those and reports a mismatch as tamper evidence. The detail and evidence text and the site profile are not bound. The commercial signal and the out-of-scope or not-measured label are not bound either, so only an edit that the bound outcomes contradict is caught. A record from an earlier rubric is reported as superseded, not recomputed. ## Current state The rubric is published as `/rubric.json`, the surfaces above are served, and the scanner runs. This site's own score is read from its scan record, as any other site's is. When a record of this site is stored, it is at `/aws/` for this site's host, with a markdown copy at `/aws//status.md`. No score is published for this site without one. ## Scan, fix, re-scan Every failed check comes with what the scanner observed and a fix to ship. Ship the fixes, then press Re-scan now on your report. Entering your domain again within 6 hours opens the stored report instead. --- # Methodology and rubric > The complete scoring contract for AgenticWebScore rubric v0.7: 5 dimensions, tier pools, the scoring formula, grades, and levels. - Source: /methodology - Site: AgenticWebScore - Language: English --- This page is the scoring contract. It is versioned, public, and reproduced in full, so anyone with a terminal can recompute a score AgenticWebScore publishes. ## What this rubric measures, and what it does not It measures what a site publishes and what a plain HTTP client can retrieve. That is which documents are served, which headers are set, which links resolve, and what text a page holds without a browser. Every check reports the request it made and the response it saw. A check passes only on something the scan observed. For `security-txt`, `openapi`, and `api-catalog`, the thing observed is a **document**, and the document describes a service the scan does not call. These checks confirm that each document is present and well-formed. They do not confirm that the service it describes answers. The detail of `security-txt`, `openapi`, `oauth-discovery`, and `api-catalog` can end with sentences that start “Not scored:”. Each one reports what an endpoint the document declares answered, or that the scan did not request it. Such a sentence carries no points and never changes the status. A site can therefore score well on those checks while running none of what it describes. Read a score as **what an agent can find**. The level is not a statement about function either. It adds required checks on top of the score, and some of them are document checks. [The level table](#readiness-levels) marks them. Under rubric v0.6, a red-team site whose every declared endpoint answered 404 reached the same level as a site that ran everything. A result can also change with no change to the site. The list below names the sources of variance the scan knows about. - `security-txt` passes only while its `Expires` field is in the future. - `status-page` reports a partial pass once the newest entry in a linked feed is more than 180 days old. - A request that gets no response within 12 s counts as no response. The check that needed it is then not measured, or earns less. So the same bytes served slowly can move the score and the fingerprint, and the check detail says timeout. - A scan that reaches its 60 s deadline is not measured at all, and gets no score. - `dns-aid` reads DNS records through a DNS-over-HTTPS resolver. When the DNS-over-HTTPS resolver answers no question, the check is not measured. A question that fails while others answer reads as no records, so the check can still fail with no change to the site. A difference that comes from one of these is not a finding. Rubric v0.7 defines 61 checks across 5 dimensions. Each check declares an id, a dimension, a tier, a weight, and an impact. It also declares a rationale, the paths it requests or the documents it reads, what it observes, and a command to reproduce it. A check that is not measured scores 0 and lowers confidence. [What changed in v0.7](#changes-v0-7) lists what moved from the version before it. ## The 5 dimensions Every check belongs to a single dimension. The weights below combine the dimension scores into the final 0–100 score. | Dimension | Weight | The question it asks | | --- | --- | --- | | Protocol Discovery | 25% | Do you expose your service as a callable tool and an authorisable API? | | Content Accessibility | 22% | Is your content genuinely readable as markdown, semantic structure and structured data? | | Discoverability | 20% | Can an agent find you, reach the right page and understand what you offer? | | Bot Access Control | 18% | Can you tell agent traffic apart by identity? | | Commerce Protocols | 15% (conditional) | Which standard do you accept agent-initiated transactions over? | > Commerce Protocols is conditional. 6 of its 10 checks are out of scope unless the site shows a commercial signal, and an out-of-scope check leaves the denominator. A signal is a `Product` type, an `Offer` with a price, purchase-intent copy, a cart or checkout path, or product schema on a product page. A site with no commercial signal is not penalised for having no payment standard. `inventory-freshness`, `shipping-costs`, `booking-action`, and `seller-identity` are scoped to site profiles instead. Each is scored when the site's identified or declared profile is one it names, with or without a commercial signal. A bare `Offer` is not enough. A free product publishes `offers: { price: "0" }` as ordinary pricing metadata. Treating that as a commercial signal once pulled the retail checks into the score of a site with no checkout. Those were the return policy, shipping costs, and UCP manifests. Demanding a returns policy from a free tool wastes a site owner's time, so a zero-price offer carries no weight. ## Tier pools Checks are also grouped into 3 tiers. The tier decides the pool of points available. That keeps a missing emerging standard from dominating the result. | Tier | Pool | Checks | Role | | --- | --- | --- | --- | | Essential | 80 raw → 76.2 of 100 | 16 | The core. An essential check that is not measured scores 0, as a failure does, and lowers confidence. | | Recommended | 20 raw → 19 of 100 | 28 | Markedly improves the agent experience. | | Emerging | 5 raw → 4.8 of 100 | 17 | New standards. Never mandatory; worth at most 4.8 of the published 100. | The tier sets how many points a check can earn. It is separate from maturity, which describes how settled the standard behind a check is: adopted, draft, and experimental. ## The formula Within a tier, a check earns points from 0 to 1, and partial credit is allowed. A tier score is the weighted mean of those points inside each dimension. The dimension means are combined by dimension weight, then scaled to the tier's pool. The 3 pools are raw and sum to 105. The total is rescaled onto the published 0–100 scale, so a perfect site scores exactly 100. _Scoring, exactly as implemented_ ```text mean_points(c, t) = Σ(check_weight × check_points) / Σ(check_weight) # per category, per tier tier_score(t) = Σ_c [ w(c) × mean_points(c, t) ] / Σ_c [ w(c) ] × pool(t) # w(c) = category weight total_score = (essential + recommended + emerging) × 100 / 105 pools = { essential: 80, recommended: 20, emerging: 5 } # raw, sums to 105 ceiling = 100 # the raw sum is rescaled onto the published 0–100 scale, so a perfect site scores exactly 100 ``` > A check that is not measured stays in the denominator at 0 points. It is not a finding: the scan could not observe it, so it is not the site's failure. It earns no credit either, because credit requires observation. Both the score and the confidence fall. The score says what was demonstrated, and the confidence says how much of the rubric could be observed. Only a check that is out of scope leaves the denominator. > This replaces an earlier policy that let a check that was not observed leave the mean entirely. That rewarded a site for being hard to measure: refusing to answer a probe scored higher than answering it and failing. A check that is not measured now scores exactly what a failure scores. ## Grades The score is a share of the rubric: 40 means about two fifths of the asked-for surfaces are in place. Each band carries a plain-language label for that share, so a letter is not read as a school mark. | Grade | Minimum score | Label | | --- | --- | --- | | AAA | 90 | near-complete | | AA | 75 | strong | | A | 60 | solid | | BBB | 45 | partial | | BB | 30 | thin | | B | 15 | minimal | | C | 5 | barely started | | D | 0 | nothing measurable | ## Readiness levels A level is a minimum score plus a set of required checks. Levels are cumulative: to hold a level, a site must pass the required checks of that level and of every level below it. A required check that is out of scope does not hold a level back, and one that is not measured does. An identified site profile can add required checks to a level. | Level | Name | Minimum score | Required checks | What it means | | --- | --- | --- | --- | --- | | L0 | Not Ready | 0 | None | Agents cannot read, verify or use this site. | | L1 | Basic Web Presence | 14 | `reachable` | The site is reachable, but there are no agent-specific signals. | | L2 | Bot-Aware | 30 | `robots-txt`, `ai-rules`, `content-signal`, `sitemap-xml` | Agent traffic is recognised and routed deliberately. | | L3 | Agent-Readable | 48 | `llms-txt`, `markdown-negotiation`, `headings`, `meta`, `jsonld`, `no-js-fallback` | Content is genuinely machine-readable. | | L4 | Agent-Integrated | 66 | `mcp-card`, `oauth-discovery`, `api-catalog` (document), `agent-permissions`, `openapi` (document) | The service is exposed as a callable, authorisable tool. | | L5 | Agent-Native | 82 | `webbotauth`, `agent-permissions`, `a2a-card`, `payment-protocols`, `product-schema` | Agents are first-class users: cryptographic identity and commerce protocols. | > A check marked (document) confirms that a document is present and well-formed, not that the service it describes answers. So a level is not a statement about function either. ## When a site cannot be measured This is the rule the whole product is built around. If a site refuses the scanner, that is a fact about our vantage point, not about the site. Reporting it as a low score would misstate the site, so the scan reports it as not measured. _Output for a site that is not measured_ ```text score = null grade = "NA" level = null confidence = reported blockedNote = why the site could not be measured # triggers homepage answers 401/402/403/406/429/503 homepage gives no response (timeout, connection error, or a redirect the scan refuses or cannot finish) homepage answers 2xx with fewer than 60 readable words and more than 4096 characters of markup (JavaScript-only) the probe phase reaches the 60 s whole-scan deadline ``` ## Verification Every scan record carries a fingerprint. The fingerprint binds the host, the rubric version, and each check's id, status, rounded points, and counted flag. It never reads the detail or evidence text, so rewording a detail does not change it. _Fingerprint (serialisation v2)_ ```text fingerprint = SHA-256( JSON( { v: 2, host: "", rubric: "", checks: [ [check_id, status, round(points, 3), counted ? 1 : 0], ... ] // sorted by check id in code-point order } ) ) # The exact bytes hashed for an example record with 3 checks. # The record stores "counted" as true or false; the row carries 1 or 0. {"v":2,"host":"example.com","rubric":"0.7","checks":[["llms-txt","warn",0.667,1],["product-schema","na",0,0],["reachable","pass",1,1]]} # Its fingerprint 1bc585b130c31d45172d5d6d39580f52ee56b73deaf00365e09863c599ac8f19 ``` Hash those bytes, without a trailing newline, using any SHA-256 tool. The lowercase hex digest is the fingerprint. > The host and rubric version are inside the hash on purpose. An earlier serialisation hashed only the check outcomes. Different sites with the same results then shared a fingerprint, and records in this corpus did. A fingerprint that cannot tell 2 hosts apart is not evidence about a host. A match proves that the check outcomes are as they were written, for that host and that rubric. For a record under the current rubric, `/verify` also recomputes the score, grade, and level from those outcomes. It reports a stored value that disagrees as tamper evidence. For a record under an older rubric, `/verify` recomputes no score, grade, or level, because the engine scores only under the rubric it loads. It reports such a record as superseded, not as tamper evidence, whether or not its fingerprint matches. The fingerprint does not bind the detail and evidence text, or whether a check is labelled out of scope or not measured. An edit to those is not detected. It does not bind the site profile or the commercial signal either. An edit to those is detected only when the stored score, grade, or level no longer matches, and only under the current rubric. A match does not prove the measurements are correct. For that, re-run the scan and compare. A difference that comes from one of the sources of variance above is not a finding. ## Keeping a measurement current There is no scheduler and no monitoring. A scan runs when somebody requests one, and the requester need not be the site owner. Every scan endpoint here is unauthenticated. A stored record younger than 6 hours is reused rather than measured again. That happens only when the request and the record declare the same site profile, or neither declares one. A request that asks for a fresh scan skips the stored record. Every report states how long ago it was measured and carries a Re-scan now button. Before you treat a changed number as a change on the site, rule out the sources of variance above. > If a report is more than a day old, re-scan before you quote it. ## What this rubric refuses to do - It never gives a score to a site it cannot read. A blocked site gets the grade NA and the reason, not a low score. - It never reports an adjective without the measured value behind it. - It names its sources of variance. They are the clock checks `security-txt` and `status-page`, the 12 s request timeout, the 60 s scan deadline, and DNS for `dns-aid`. - It never hides a gap. What the product cannot yet do is published alongside what it can. - It publishes every signal it scores. This site is its own first customer. - It never asks a site owner to do work that does not apply to them. [Site profiles](#site-profiles) explains how. ## Site profiles The same rubric measures an online shop, a news publisher, and a developer platform. It must not ask them for the same things. A product feed is essential for a retailer and irrelevant to a newspaper. A booking action matters to a clinic and means nothing on an API platform. A scanner that does not know what kind of site it is looking at gives confident, specific instructions that are wrong. The site owner pays for that mistake with their time. > No profile-specific demand without a positively identified profile. Failing to understand a site must never turn into work for its owner. So every check declares a scope. The scope decides whether the check is scored. It also decides whether the check may produce an instruction at all. | Scope | Checks | Scored when | | --- | --- | --- | | Universal | 46 | Always. These are signals any site can act on, whatever it is. | | Commercial | 6 | Only when a commercial signal was detected: product or offer schema, purchase-intent copy, or a cart or checkout path. | | Profile | 9 | Only when a site profile was positively identified. Otherwise it is out of scope, and never counted as a failure. | ### The profiles A profile changes 4 things: the dimension weights, which checks are in scope, which checks are out of scope, and what each level requires. The rubric defines 8 profiles, including a general fallback. A site whose profile cannot be identified is still measured rather than skipped. | Site profile | The question it asks | Dominant dimensions | | --- | --- | --- | | E-commerce / retail | Can an agent find, price and buy your products without a human? | Commerce Protocols 28% · Protocol Discovery 20% | | Marketplace / aggregator | Can an agent tell who is selling what, at what price, and buy it? | Commerce Protocols 24% · Protocol Discovery 24% | | SaaS / software product | Can an agent understand what the product does, what it costs, and how to call it? | Protocol Discovery 30% · Content Accessibility 22% | | API / developer platform | Can an agent discover, authorise against and call the API without reading a tutorial? | Protocol Discovery 34% · Content Accessibility 20% | | Content / media / publisher | Can an agent read, quote and correctly attribute your content? | Content Accessibility 30% · Discoverability 24% | | Services / local business | Can an agent understand what you offer, where, when and for how much? | Discoverability 24% · Content Accessibility 24% | | Institution / public sector / education | Can an agent find the authoritative document, in an accessible form, and cite it? | Content Accessibility 26% · Discoverability 22% | | General website | Can an agent find you, read you and trust you? | Protocol Discovery 25% · Content Accessibility 22% | ### How the profile is detected Detection is deterministic and produces evidence. Signals are evaluated against documents already fetched: structured-data types, responding paths, page copy, and the domain suffix. Every signal that fires is reported with the profile it supports. _Selection rule_ ```text profile_score = Σ(weight of each matched signal) identified : top >= 3 AND (top - runner_up) >= 2 ambiguous : top >= 3 AND (top - runner_up) < 2 unknown : no profile reaches 3 ``` | Detection outcome | What happens | | --- | --- | | Identified | The profile's weights, not-applicable list and level requirements apply. Profile-scoped checks are in scope. | | Ambiguous | Baseline weights apply. Profile-scoped checks are NOT scored and leave the denominator. Both candidate types are reported and the owner is invited to declare one. | | Unknown | Baseline weights apply. Profile-scoped checks are NOT scored and leave the denominator. The report states plainly that the site type could not be determined. | | Declared by the owner | A site owner may declare the type. A declared profile is treated as identified and the record states that it was declared rather than detected. | ### Why an unknown profile is not a penalty - Demanding a product feed from a news publisher, or a booking action from a developer platform, is a false positive that costs the site owner real work. - The cost of a missed optimisation is smaller than the cost of an incorrect instruction, because an incorrect instruction spends the site owner's trust as well as their time. - So a check that only applies to some site types stays out of scope unless the type was positively identified — and the report says which checks were left out and why. In practice, a site whose profile could not be identified is not scored on profile checks. The report states which checks were left out and why. Nothing is silently dropped, and nothing is invented to fill the gap. ## What changed in rubric v0.7 Rubric v0.7 is dated 12 October 2026. The lists below are what it changed from the version before it, as [`/rubric.json`](/rubric.json) records them under `changes`. A score measured under an earlier version is not comparable with a v0.7 score. Every scan record names the rubric version that produced it. ### Changes that can move a status or points A score on one side of these changes is not comparable with a score on the other. - [`llms-txt`](/checks/llms-txt): The link sample counts requests, not positions. A link on another origin, or one the scan already requested, no longer uses up the sample. A requested link that gets no answer is not measured, so it no longer makes the check partial. - [`mcp-card`](/checks/mcp-card): A streamable-http remote that answers 405 or 406 to a plain GET counts as a running server. So does any remote that answers 401 with a challenge naming resource_metadata. A bare 401 still does not count. - [`mcp-card`](/checks/mcp-card): The remotes sampled are those of the first card that offers a transport, which is the card the check reads. - [`mcp-card`](/checks/mcp-card), [`api-catalog`](/checks/api-catalog), [`agent-skills`](/checks/agent-skills), [`oauth-discovery`](/checks/oauth-discovery), [`status-page`](/checks/status-page), [`docs`](/checks/docs), and [`sandbox-environment`](/checks/sandbox-environment): A URL is on the scanned origin only when its scheme, host and port all match. A URL on another port or scheme is no longer judged by the scanned origin’s response. - [`oauth-discovery`](/checks/oauth-discovery): The scan requests the metadata of a same-origin authorization server named by protected resource metadata. When that metadata was requested and is missing, the check is partial. - [`docs`](/checks/docs): The scan requests documentation pointers on the homepage, service-doc first, up to a published cap. It does not request API catalog targets. An anchor counts only when a whole path segment names a documentation section, and its text no longer counts. A requested pointer that gives no response earns no partial credit. - [`breadcrumb`](/checks/breadcrumb): The last entry of a trail may omit item, as Google’s breadcrumb guidance allows. A value that is not a URL is still a defect. - [`dns-aid`](/checks/dns-aid): A record of another type in the answer, such as the CNAME of an alias, no longer counts as a DNS-AID record. When the DNS-over-HTTPS resolver answers no question, the check is not measured. It used to fail, or be judged on the TXT records the system resolver returned. - Every check: The probe phase stops at a whole-scan deadline. A scan that reaches it is reported as not measured, with no score, because part of the site was never requested. ### Changes to what a record says These change the words a record carries. They never change a status or points. - [`security-txt`](/checks/security-txt), [`openapi`](/checks/openapi), and [`api-catalog`](/checks/api-catalog): The detail adds sentences prefixed “Not scored:” about the endpoints the document declares. They never change the status or the points. - [`llms-txt`](/checks/llms-txt): The detail counts the links the scan requested and names each link that did not answer 2xx with the status it answered. - [`mcp-card`](/checks/mcp-card): The detail names the remotes the scan did not request, instead of saying it requested them. - [`openapi`](/checks/openapi): A partial names the missing info.title or info.version, instead of saying the document has no callable operation. - [`dns-aid`](/checks/dns-aid): One TXT record that both resolvers return counts once in the detail. - [`dns-aid`](/checks/dns-aid): The evidence names the DNS names and record types the scan queried, instead of agent names it never queried. A fail names the same names in its detail. - Every check: A check that raises an internal error is reported as not measured, in one sentence the health endpoint recognises. Every detail and evidence line is cut to one published length. - Every check: A record counts the markdown negotiation request in its request total and request log. ### Corrections to published text These change a published sentence about a check, not what the engine does. - [`reachable`](/checks/reachable): The measures text names the homepage statuses that make the whole scan not measured, which the engine already did. - [`llms-txt`](/checks/llms-txt): The measures text names every partial the check returns, including a missing blockquote and an H1 after other lines. - [`agent-skills`](/checks/agent-skills): The measures text states the fail clauses the check already returned: no index, or an artifact that does not match its digest. - [`mcp-card`](/checks/mcp-card), [`docs`](/checks/docs), and [`oauth-discovery`](/checks/oauth-discovery): The measures text describes the requests the scan now makes for these checks. - [`dns-aid`](/checks/dns-aid): The measures text names _agent., which the scan already queried, instead of agent names it never queried. It also says when the check is not measured. ## The 61 checks The full inventory, generated from the rubric file itself. Every check has its own page with the measurement, a command to reproduce it, and the fix to ship. ### Protocol Discovery — 25% | Check | Tier | Weight | Impact | Maturity | | --- | --- | --- | --- | --- | | `mcp-card` — MCP server card | Essential | 2 | high | Draft | | `oauth-discovery` — OAuth discovery documents | Essential | 2 | high | Adopted | | `openapi` — OpenAPI definition | Essential | 2 | high | Adopted | | `pricing-structured` — Structured pricing information | Recommended | 2 | high | Adopted | | `service-schema` — Service/product scope machine-readable | Recommended | 2 | high | Draft | | `a2a-card` — A2A agent card | Recommended | 2 | medium | Draft | | `agent-skills` — Agent Skills declaration | Recommended | 1 | medium | Draft | | `api-catalog` — API catalog | Recommended | 2 | medium | Experimental | | `docs` — Documentation reachable | Recommended | 1 | medium | Adopted | | `rate-limits-declared` — Rate limits and quotas documented | Recommended | 1 | medium | Experimental | | `sandbox-environment` — Sandbox or test environment documented | Recommended | 2 | medium | Experimental | | `a2a-signed` — Cryptographically signed agent card | Emerging | 1 | medium | Draft | | `auth-md` — /auth.md agent authentication guide | Emerging | 2 | medium | Draft | | `contact` — Structured contact information | Emerging | 1 | medium | Adopted | | `webmcp` — WebMCP browser tool declaration | Emerging | 2 | medium | Experimental | | `ard-manifest` — ARD resource discovery manifest | Emerging | 1 | low | Experimental | | `status-page` — Service status and changelog feed | Emerging | 1 | low | Adopted | ### Content Accessibility — 22% | Check | Tier | Weight | Impact | Maturity | | --- | --- | --- | --- | --- | | `jsonld` — JSON-LD structured data | Essential | 3 | critical | Adopted | | `headings` — Semantic heading structure | Essential | 2 | high | Adopted | | `meta` — Title and summary metadata | Essential | 2 | high | Adopted | | `no-js-fallback` — Content that needs no JavaScript | Essential | 2 | high | Adopted | | `markdown-negotiation` — Markdown content negotiation | Recommended | 3 | critical | Adopted | | `faq-schema` — FAQ / question-answer schema | Recommended | 2 | high | Draft | | `licensing-terms` — Reuse and licensing terms declared | Recommended | 2 | high | Draft | | `document-formats` — Documents in machine-readable formats | Recommended | 2 | medium | Draft | | `lang` — Language declaration and multilingual access | Recommended | 1 | medium | Adopted | | `summary` — Prominent summary block | Recommended | 1 | medium | Draft | | `token-efficiency` — Token efficiency (content-to-markup ratio) | Recommended | 2 | medium | Draft | | `provenance-declared` — Content provenance declared | Emerging | 1 | medium | Draft | | `spa-fallback` — Per-page content separation (no SPA fallback) | Emerging | 2 | medium | Experimental | | `breadcrumb` — Breadcrumb / navigation schema | Emerging | 1 | low | Draft | | `viewport` — Responsive markup | Emerging | 1 | low | Adopted | ### Discoverability — 20% | Check | Tier | Weight | Impact | Maturity | | --- | --- | --- | --- | --- | | `llms-txt` — /llms.txt published and well-structured | Essential | 3 | critical | Draft | | `reachable` — Homepage open to agent access | Essential | 3 | critical | Adopted | | `robots-txt` — robots.txt with agent directives | Essential | 2 | high | Adopted | | `sitemap-xml` — sitemap.xml valid and current | Essential | 2 | high | Adopted | | `agents-md` — AGENTS.md with the required sections | Recommended | 2 | high | Draft | | `content-signal` — Content-Signal usage signals | Recommended | 2 | high | Draft | | `canonical` — Canonical and hreflang discipline | Recommended | 2 | medium | Adopted | | `llms-full` — /llms-full.txt expanded context | Recommended | 1 | low | Draft | | `dns-aid` — DNS-AID discovery record | Emerging | 2 | medium | Experimental | | `link-headers` — Discovery via Link response headers | Emerging | 2 | medium | Adopted | | `sitemap-md` — /sitemap.md markdown site map | Emerging | 1 | low | Draft | ### Bot Access Control — 18% | Check | Tier | Weight | Impact | Maturity | | --- | --- | --- | --- | --- | | `agent-permissions` — Agent permission model (agent-permissions.json) | Essential | 3 | critical | Experimental | | `webbotauth` — Web Bot Auth key directory | Essential | 3 | critical | Draft | | `ai-policy` — AI usage policy page | Essential | 2 | high | Adopted | | `ai-rules` — Named AI bot rules in robots.txt | Essential | 2 | high | Draft | | `bot-page` — Crawler and agent policy page | Recommended | 1 | medium | Adopted | | `security-txt` — security.txt (RFC 9116) | Recommended | 1 | low | Adopted | | `ai-txt` — /ai.txt access declaration | Emerging | 1 | low | Draft | | `crawl-delay` — Crawl rate declaration | Emerging | 1 | low | Adopted | ### Commerce Protocols — 15% | Check | Tier | Weight | Impact | Maturity | | --- | --- | --- | --- | --- | | `product-schema` — Product/catalog schema | Essential | 3 | critical | Adopted | | `agent-purchase` — Agent purchase policy | Recommended | 2 | high | Draft | | `inventory-freshness` — Inventory and price freshness | Recommended | 2 | high | Adopted | | `payment-protocols` — Agent payment standard support (AP2/ACP/x402/UCP) | Recommended | 3 | high | Draft | | `shipping-costs` — Shipping cost and delivery declared | Recommended | 2 | high | Adopted | | `booking-action` — Machine-readable booking action | Recommended | 2 | medium | Draft | | `returns` — Return and shipping terms machine-readable | Recommended | 1 | medium | Adopted | | `seller-identity` — Seller identity declared | Recommended | 2 | medium | Adopted | | `ucp-manifest` — UCP manifest (/.well-known/ucp) | Emerging | 2 | medium | Draft | | `agent-analytics` — Agent traffic measurement | Emerging | 1 | low | Draft | --- # All 61 agent readiness checks by dimension > Every check in rubric v0.7, with the measurement, the reproduction command, and the fix to ship. They are grouped by dimension, with tier and impact. - Source: /checks - Site: AgenticWebScore - Language: English --- All 61 checks in rubric v0.7, grouped by dimension. Every check has its own page with what is measured, the exact requests the scanner makes, a command you can run yourself, and the artifact to ship. | Dimension | Weight | Checks | Question | | --- | --- | --- | --- | | Protocol Discovery | 25% | 17 | Do you expose your service as a callable tool and an authorisable API? | | Content Accessibility | 22% | 15 | Is your content genuinely readable as markdown, semantic structure and structured data? | | Discoverability | 20% | 11 | Can an agent find you, reach the right page and understand what you offer? | | Bot Access Control | 18% | 8 | Can you tell agent traffic apart by identity? | | Commerce Protocols | 15% (conditional) | 10 | Which standard do you accept agent-initiated transactions over? | ## Protocol Discovery — 17 checks MCP server card, A2A agent card, OAuth discovery, OpenAPI, Agent Skills, WebMCP. The layer that lets an agent use you instead of guessing at you. | Check | Tier | Impact | Maturity | Rationale | | --- | --- | --- | --- | --- | | [`mcp-card`](/checks/mcp-card) — MCP server card | Essential | high | Draft | Since MCP 2026-07-28, agents discover tool servers through a published declaration. | | [`oauth-discovery`](/checks/oauth-discovery) — OAuth discovery documents | Essential | high | Adopted | Required for agents to connect to your authenticated API on their own (RFC 8414 / RFC 9728). | | [`openapi`](/checks/openapi) — OpenAPI definition | Essential | high | Adopted | A machine-readable contract so an agent can discover your API and generate correct calls. | | [`pricing-structured`](/checks/pricing-structured) — Structured pricing information | Recommended | high | Adopted | An offer without a price cannot be compared by an agent — you drop out of consideration. | | [`service-schema`](/checks/service-schema) — Service/product scope machine-readable | Recommended | high | Draft | An agent must be able to answer "what does this site offer, and to whom". | | [`a2a-card`](/checks/a2a-card) — A2A agent card | Recommended | medium | Draft | A2A v1.0 (Linux Foundation) is the emerging standard for agent-to-agent discovery. Almost no site publishes a card yet, which makes this one of the cheapest places to be early. | | [`agent-skills`](/checks/agent-skills) — Agent Skills declaration | Recommended | medium | Draft | Offers ready-made capability packages to agent runtimes. | | [`api-catalog`](/checks/api-catalog) — API catalog | Recommended | medium | Experimental | Lets an agent see which capabilities are callable in a single document (RFC 9727). | | [`docs`](/checks/docs) — Documentation reachable | Recommended | medium | Adopted | An agent needs documentation to complete an integration on its own. | | [`rate-limits-declared`](/checks/rate-limits-declared) — Rate limits and quotas documented | Recommended | medium | Experimental | An agent that does not know the quota discovers it by being throttled, halfway through a task it cannot resume. | | [`sandbox-environment`](/checks/sandbox-environment) — Sandbox or test environment documented | Recommended | medium | Experimental | An agent cannot safely integrate against a production endpoint; a documented sandbox is the difference between a working trial and a support ticket. | | [`a2a-signed`](/checks/a2a-signed) — Cryptographically signed agent card | Emerging | medium | Draft | A2A v1.0 makes identity verifiable through JWS (RFC 7515). | | [`auth-md`](/checks/auth-md) — /auth.md agent authentication guide | Emerging | medium | Draft | A guide telling an agent which authentication flow to use. | | [`contact`](/checks/contact) — Structured contact information | Emerging | medium | Adopted | An agent must know where to reach you before starting a transaction, or when something fails. | | [`webmcp`](/checks/webmcp) — WebMCP browser tool declaration | Emerging | medium | Experimental | WebMCP lets sites expose tools to in-browser agents. It is the only normative deliverable of the W3C Agentic Web WG. | | [`ard-manifest`](/checks/ard-manifest) — ARD resource discovery manifest | Emerging | low | Experimental | Cisco/Outshift's Agentic Resource Discovery specification; Lighthouse audits it too. | | [`status-page`](/checks/status-page) — Service status and changelog feed | Emerging | low | Adopted | An agent should be able to learn about outages and API changes in a machine-readable way. | ## Content Accessibility — 15 checks Server-side rendering, markdown negotiation, semantic headings, JSON-LD. Adobe measured that 39% of retail product pages cannot be read by a machine. | Check | Tier | Impact | Maturity | Rationale | | --- | --- | --- | --- | --- | | [`jsonld`](/checks/jsonld) — JSON-LD structured data | Essential | critical | Adopted | The entity type becomes unambiguous to a machine. Without authoritative data, an agent answers from whatever it can scrape. | | [`headings`](/checks/headings) — Semantic heading structure | Essential | high | Adopted | A single H1 and a consistent H2 structure let the content be split correctly. | | [`meta`](/checks/meta) — Title and summary metadata | Essential | high | Adopted | This is how an agent learns what a page is about without opening it. | | [`no-js-fallback`](/checks/no-js-fallback) — Content that needs no JavaScript | Essential | high | Adopted | If content is only produced client-side, the page is empty for agents that do not run JavaScript. | | [`markdown-negotiation`](/checks/markdown-negotiation) — Markdown content negotiation | Recommended | critical | Adopted | Agents can request a markup-free version with "Accept: text/markdown", which cuts token cost. | | [`faq-schema`](/checks/faq-schema) — FAQ / question-answer schema | Recommended | high | Draft | Question-and-answer content is the type agents quote most. | | [`licensing-terms`](/checks/licensing-terms) — Reuse and licensing terms declared | Recommended | high | Draft | Declaring ai-train=no without stating a licensing path leaves both the publisher and the agent without an answer they can act on. | | [`document-formats`](/checks/document-formats) — Documents in machine-readable formats | Recommended | medium | Draft | A PDF that carries no document structure is unreadable to an agent and to a screen reader alike — the same defect, found twice. | | [`lang`](/checks/lang) — Language declaration and multilingual access | Recommended | medium | Adopted | A wrong language tag makes an agent misread the content. | | [`summary`](/checks/summary) — Prominent summary block | Recommended | medium | Draft | The llms.txt contract recommends a short summary at the top of every page; agents quote it directly. | | [`token-efficiency`](/checks/token-efficiency) — Token efficiency (content-to-markup ratio) | Recommended | medium | Draft | A bloated DOM wastes an agent's context window. | | [`provenance-declared`](/checks/provenance-declared) — Content provenance declared | Emerging | medium | Draft | Author, publication date and update date are what let an agent judge whether a source is current and attributable before it quotes it. | | [`spa-fallback`](/checks/spa-fallback) — Per-page content separation (no SPA fallback) | Emerging | medium | Experimental | A catch-all route returning the same skeleton for every URL makes pages indistinguishable to an agent. | | [`breadcrumb`](/checks/breadcrumb) — Breadcrumb / navigation schema | Emerging | low | Draft | Helps an agent make sense of where a page sits in your site. | | [`viewport`](/checks/viewport) — Responsive markup | Emerging | low | Adopted | Agent browsers mostly run at mobile scale. | ## Discoverability — 11 checks Machine discovery through robots.txt, sitemaps, DNS and link headers. The cheapest, highest-return layer of agent readiness. | Check | Tier | Impact | Maturity | Rationale | | --- | --- | --- | --- | --- | | [`llms-txt`](/checks/llms-txt) — /llms.txt published and well-structured | Essential | critical | Draft | The most widely adopted contract for making a site legible to agents. In the curated corpus we measured, 46% of sites published one and the average quality score was 37 out of 100 — adoption is not the same as usefulness. | | [`reachable`](/checks/reachable) — Homepage open to agent access | Essential | critical | Adopted | If an agent cannot read your site, every other check is moot. Cloudflare began blocking AI crawlers by default in 2025, with signed agents routed separately. | | [`robots-txt`](/checks/robots-txt) — robots.txt with agent directives | Essential | high | Adopted | The front door for agent traffic (RFC 9309). | | [`sitemap-xml`](/checks/sitemap-xml) — sitemap.xml valid and current | Essential | high | Adopted | The primary URL discovery source for agent crawlers. | | [`agents-md`](/checks/agents-md) — AGENTS.md with the required sections | Recommended | high | Draft | The instruction file for coding and operations agents. It fails more often than any other check in the curated corpus we measured, and the usual reason is not a missing file but a file without the sections an agent needs. | | [`content-signal`](/checks/content-signal) — Content-Signal usage signals | Recommended | high | Draft | Declares how your content may be used, inside robots.txt. Cloudflare included this in its readiness checks. | | [`canonical`](/checks/canonical) — Canonical and hreflang discipline | Recommended | medium | Adopted | An agent needs one consistent URL per important page. | | [`llms-full`](/checks/llms-full) — /llms-full.txt expanded context | Recommended | low | Draft | Lets an agent take in the full context in a single request instead of walking the site step by step. | | [`dns-aid`](/checks/dns-aid) — DNS-AID discovery record | Emerging | medium | Experimental | Lets agents read discovery information over DNS without an HTTP round trip. Cloudflare added it to its readiness checklist. | | [`link-headers`](/checks/link-headers) — Discovery via Link response headers | Emerging | medium | Adopted | RFC 8288 Link headers let an agent find your discovery resources without parsing HTML. | | [`sitemap-md`](/checks/sitemap-md) — /sitemap.md markdown site map | Emerging | low | Draft | Lets an agent read your site structure as markdown in a single file. Adoption is still very low, so this is an early-mover advantage. | ## Bot Access Control — 8 checks Cryptographic agent verification, content usage signals and an explicit permission model. Being blocked by IP is not a policy. | Check | Tier | Impact | Maturity | Rationale | | --- | --- | --- | --- | --- | | [`agent-permissions`](/checks/agent-permissions) — Agent permission model (agent-permissions.json) | Essential | critical | Experimental | Declares which actions an agent may take, which are refused, and which need a person. It is the difference between a policy and a wish: in the curated corpus we measured, roughly one site in a hundred publishes one. | | [`webbotauth`](/checks/webbotauth) — Web Bot Auth key directory | Essential | critical | Draft | RFC 9421 with Ed25519: the mechanism that lets a site verify which agent is calling rather than guessing from a user-agent string. Adoption in the curated corpus we measured is around one site in a hundred. | | [`ai-policy`](/checks/ai-policy) — AI usage policy page | Essential | high | Adopted | States the rules agents must follow and reduces licensing ambiguity. | | [`ai-rules`](/checks/ai-rules) — Named AI bot rules in robots.txt | Essential | high | Draft | Naming agent crawlers explicitly is the first step to being visible in agent traffic. | | [`bot-page`](/checks/bot-page) — Crawler and agent policy page | Recommended | medium | Adopted | Explains which agents are permitted and how they are verified. | | [`security-txt`](/checks/security-txt) — security.txt (RFC 9116) | Recommended | low | Adopted | Provides a responsible disclosure channel for agent-related security incidents. | | [`ai-txt`](/checks/ai-txt) — /ai.txt access declaration | Emerging | low | Draft | Some agent ecosystems read an /ai.txt contract alongside robots.txt. | | [`crawl-delay`](/checks/crawl-delay) — Crawl rate declaration | Emerging | low | Adopted | Cloudflare's Verified Bots policy drops AI crawlers that ignore crawl-delay. | ## Commerce Protocols — 10 checks ACP, AP2, x402, UCP/MPP, product schema and machine-readable returns. Excluded from the denominator unless the site shows a commercial signal. | Check | Tier | Impact | Maturity | Rationale | | --- | --- | --- | --- | --- | | [`product-schema`](/checks/product-schema) — Product/catalog schema | Essential | critical | Adopted | Product data is the most valuable and the least machine-readable: price, availability and returns are usually rendered for a person to read and never declared for a machine to parse. | | [`agent-purchase`](/checks/agent-purchase) — Agent purchase policy | Recommended | high | Draft | Liability is the open question in agent commerce, and it is a policy decision rather than a technical one: a site that accepts an agent purchase has to decide who carries the cost when the agent is wrong, and publish that decision where an agent can read it. | | [`inventory-freshness`](/checks/inventory-freshness) — Inventory and price freshness | Recommended | high | Adopted | An agent that cannot tell whether an item is in stock — or when a price was last valid — will quote a stale offer to a buyer, or refuse to quote at all. | | [`payment-protocols`](/checks/payment-protocols) — Agent payment standard support (AP2/ACP/x402/UCP) | Recommended | high | Draft | The least-implemented surface in the rubric. Accepting an agent payment means choosing a standard and changing a checkout, which is a business decision most sites have not made yet. | | [`shipping-costs`](/checks/shipping-costs) — Shipping cost and delivery declared | Recommended | high | Adopted | A purchase agent that cannot compute the delivered total cannot complete a checkout, and returns to the merchant without it. | | [`booking-action`](/checks/booking-action) — Machine-readable booking action | Recommended | medium | Draft | For a service business the agent's task is to book, not to browse — a declared action is what turns a contact page into a completed job. | | [`returns`](/checks/returns) — Return and shipping terms machine-readable | Recommended | medium | Adopted | An agent must verify return terms before making a purchase decision. | | [`seller-identity`](/checks/seller-identity) — Seller identity declared | Recommended | medium | Adopted | On a marketplace an offer is meaningless without knowing who is selling and who is the merchant of record, because that is who the agent has a contract with. | | [`ucp-manifest`](/checks/ucp-manifest) — UCP manifest (/.well-known/ucp) | Emerging | medium | Draft | Google and Shopify's Universal Commerce Protocol; lets a merchant declare checkout capabilities at transaction time. | | [`agent-analytics`](/checks/agent-analytics) — Agent traffic measurement | Emerging | low | Draft | If agent traffic is not measured separately, the channel's return is invisible and never funded. | --- # AI crawler access: is your homepage open to agents? > Homepage open to agent access: If an agent cannot read your site, every other check is moot. The fix: open agent access (clear the 403/429 block). - Source: /checks/reachable - Site: AgenticWebScore - Language: English --- If an agent cannot read your site, every other check is moot. Cloudflare began blocking AI crawlers by default in 2025, with signed agents routed separately. | Property | Value | | --- | --- | | Check id | `reachable` | | Dimension | Discoverability (20%) | | Tier | Essential — pool 80 pts | | Weight inside tier | 3 | | Impact | Critical | | Maturity | Adopted — A ratified standard with real deployment. | | Conditional | No | | Publishing skill | `agent-access` | | Standards | — | ## What is measured The scanner sends one GET to https:/// - the homepage is the only source for this check - using a non-browser agent user agent, and records the status code, Content-Type and body size. Pass = a 2xx HTML response with a real body. Partial = a 2xx response that is not HTML, a body smaller than roughly 1 KB or with almost no visible text, or a redirect chain that leaves the host before reaching content. Not measured = 401, 402, 403, 406, 429 or 503, no response, a JavaScript-only shell, or a scan cut at the whole-scan deadline: the whole scan is then reported as not measured, with no score. A refusal is a fact about the scanner's vantage point, not about the site. Fail = any other non-2xx status, such as 404, 451 or another 5xx. ## Reproduce it yourself You do not have to take our word for any of this. Run the same measurement against your own domain: ```bash DOMAIN=example.com curl -sS -o /dev/null -w 'status=%{http_code} type=%{content_type} bytes=%{size_download} redirect=%{redirect_url}\n' -A 'AgenticWebScore/0.3 (+https://agenticwebscore.com/bot)' "https://$DOMAIN/" ``` ## The fix This is the artifact to ship. It is the complete change, not a description of one. ```text # nginx: clear the 403/429 that agent user agents hit on the homepage. # $bot_block and the rate limit come from your existing config; the allow-list # below is evaluated first so agents are never sent down the block path. map $http_user_agent $agent_allow { default 0; "~*(GPTBot|OAI-SearchBot|ChatGPT-User|ClaudeBot|PerplexityBot)" 1; "~*(Google-Extended|Applebot-Extended|CCBot|Amazonbot)" 1; } server { listen 443 ssl; server_name example.com; location = / { if ($agent_allow) { set $bot_block 0; } if ($bot_block) { return 403; } try_files /index.html =404; } } ``` > If a CDN or WAF sits in front of nginx - for example Cloudflare's default AI-crawler block - the allow decision must be made there too, because nginx never sees a request the edge rejects. ## Related checks | Check | Tier | Impact | Same skill | | --- | --- | --- | --- | | `robots-txt` — robots.txt with agent directives | Essential | High | — | | `sitemap-xml` — sitemap.xml valid and current | Essential | High | — | | `llms-txt` — /llms.txt published and well-structured | Essential | Critical | — | | `link-headers` — Discovery via Link response headers | Emerging | Medium | — | | `dns-aid` — DNS-AID discovery record | Emerging | Medium | — | | `canonical` — Canonical and hreflang discipline | Recommended | Medium | — | | `llms-full` — /llms-full.txt expanded context | Recommended | Low | — | | `agents-md` — AGENTS.md with the required sections | Recommended | High | — | --- # robots.txt for AI agents: rules, crawl-delay and AI crawlers > robots.txt with agent directives: The front door for agent traffic (RFC 9309). It is an essential-tier check in the Discoverability dimension. - Source: /checks/robots-txt - Site: AgenticWebScore - Language: English --- The front door for agent traffic (RFC 9309). | Property | Value | | --- | --- | | Check id | `robots-txt` | | Dimension | Discoverability (20%) | | Tier | Essential — pool 80 pts | | Weight inside tier | 2 | | Impact | High | | Maturity | Adopted — A ratified standard with real deployment. | | Conditional | No | | Publishing skill | `robots-txt` | | Standards | RFC 9309 | ## What is measured The scanner fetches https:///robots.txt ($robots in the probe map) and parses it per RFC 9309, where a group is a User-agent line followed by its Allow/Disallow rules. Pass = HTTP 200 with a parseable file that names at least one agent crawler as its own group and declares a Sitemap. Partial = the file parses but contains only a blanket User-agent: * group, or places rules before any User-agent line. Fail = 404 or 5xx, a non-text response, or HTML returned for the path by a catch-all route. ## Reproduce it yourself You do not have to take our word for any of this. Run the same measurement against your own domain: ```bash DOMAIN=example.com curl -sSi "https://$DOMAIN/robots.txt" | sed -n '1,40p' ``` ## The fix This is the artifact to ship. It is the complete change, not a description of one. ```text # https://example.com/robots.txt # RFC 9309: a group is a User-agent line followed by its rules. User-agent: * Allow: / Disallow: /admin/ Disallow: /cart/ Disallow: /search? # Name the agent crawlers you welcome, so agent traffic is routed deliberately. User-agent: GPTBot Allow: / User-agent: OAI-SearchBot Allow: / User-agent: ClaudeBot Allow: / User-agent: PerplexityBot Allow: / Sitemap: https://example.com/sitemap.xml ``` > Rules must follow their own User-agent line - a Disallow placed before any User-agent is ignored - and robots.txt is only read at the root of the host, never at a subpath. ## Standards referenced - `RFC 9309` ## Related checks | Check | Tier | Impact | Same skill | | --- | --- | --- | --- | | `reachable` — Homepage open to agent access | Essential | Critical | — | | `sitemap-xml` — sitemap.xml valid and current | Essential | High | — | | `llms-txt` — /llms.txt published and well-structured | Essential | Critical | — | | `link-headers` — Discovery via Link response headers | Emerging | Medium | — | | `dns-aid` — DNS-AID discovery record | Emerging | Medium | — | | `canonical` — Canonical and hreflang discipline | Recommended | Medium | — | | `llms-full` — /llms-full.txt expanded context | Recommended | Low | — | | `agents-md` — AGENTS.md with the required sections | Recommended | High | — | --- # sitemap.xml valid and current > sitemap.xml valid and current: The primary URL discovery source for agent crawlers. The fix: publish a sitemap with lastmod. - Source: /checks/sitemap-xml - Site: AgenticWebScore - Language: English --- The primary URL discovery source for agent crawlers. | Property | Value | | --- | --- | | Check id | `sitemap-xml` | | Dimension | Discoverability (20%) | | Tier | Essential — pool 80 pts | | Weight inside tier | 2 | | Impact | High | | Maturity | Adopted — A ratified standard with real deployment. | | Conditional | No | | Publishing skill | `sitemap` | | Standards | — | ## What is measured The scanner fetches https:///sitemap.xml ($sitemap in the probe map) and parses it as XML. Pass = a urlset (or a sitemapindex) whose entries carry absolute loc URLs and a lastmod timestamp. Partial = valid XML with loc entries but no lastmod anywhere, or a sitemapindex that only points at child sitemaps. Fail = 404, an HTML page returned with a 200 by a catch-all route, or XML that does not parse. ## Reproduce it yourself You do not have to take our word for any of this. Run the same measurement against your own domain: ```bash DOMAIN=example.com curl -sS "https://$DOMAIN/sitemap.xml" | grep -E '|' | head -20 ``` ## The fix This is the artifact to ship. It is the complete change, not a description of one. ```xml https://example.com/ 2026-10-08 weekly 1.0 https://example.com/docs/quickstart 2026-10-08 monthly 0.8 https://example.com/pricing 2026-09-30 monthly 0.6 ``` > lastmod must be a real modification date in W3C datetime form and must actually change when the page changes, otherwise the whole file reads as stale. ## Related checks | Check | Tier | Impact | Same skill | | --- | --- | --- | --- | | `reachable` — Homepage open to agent access | Essential | Critical | — | | `robots-txt` — robots.txt with agent directives | Essential | High | — | | `llms-txt` — /llms.txt published and well-structured | Essential | Critical | — | | `link-headers` — Discovery via Link response headers | Emerging | Medium | — | | `dns-aid` — DNS-AID discovery record | Emerging | Medium | — | | `canonical` — Canonical and hreflang discipline | Recommended | Medium | — | | `llms-full` — /llms-full.txt expanded context | Recommended | Low | — | | `agents-md` — AGENTS.md with the required sections | Recommended | High | — | --- # llms.txt: how to publish a site summary for AI agents > /llms.txt published and well-structured: The most widely adopted contract for making a site legible to agents. The fix: publish llms.txt. Standard: llmstxt.org. - Source: /checks/llms-txt - Site: AgenticWebScore - Language: English --- The most widely adopted contract for making a site legible to agents. In the curated corpus we measured, 46% of sites published one and the average quality score was 37 out of 100 — adoption is not the same as usefulness. | Property | Value | | --- | --- | | Check id | `llms-txt` | | Dimension | Discoverability (20%) | | Tier | Essential — pool 80 pts | | Weight inside tier | 3 | | Impact | Critical | | Maturity | Draft — A published specification that is not yet ratified. | | Conditional | No | | Publishing skill | `llms-txt` | | Standards | llmstxt.org | ## What the scanner requests - `/llms.txt` ## What is measured The scanner fetches https:///llms.txt (the exact path this check probes) and parses the markdown against the llmstxt.org contract. It then requests up to 6 same-origin links the file names, beyond the paths the scan already requests. A link on another origin is not requested, and a link that gets no answer is not measured. Pass = a 2xx response served as text/plain or text/markdown, opening with an H1, followed by a blockquote summary and at least one H2 section listing markdown links written as [name](url). No requested same-origin link may answer a status other than 2xx, and the pass states how many links were requested. Partial = the file is served with another content type, has no H1, has an H1 after other lines, has no H2 link list, has no blockquote, or names a requested same-origin link that answered a status other than 2xx. Fail = a non-2xx status for the file, or an HTML document returned for the path. A request for the file that gets no answer is not measured. ## Reproduce it yourself You do not have to take our word for any of this. Run the same measurement against your own domain: ```bash DOMAIN=example.com curl -sS "https://$DOMAIN/llms.txt" | head -25 ``` ## The fix This is the artifact to ship. It is the complete change, not a description of one. ```markdown # Example Inc > Example Inc runs a payments API for marketplaces. This file lists the pages an agent needs, with a short note on each. Example Inc is US-based; support is at support@example.com. API access uses OAuth 2.0 tokens, see the authentication guide below. ## Docs - [Quickstart](https://example.com/docs/quickstart.md): Install the CLI and make a first API call - [API reference](https://example.com/docs/api.md): Every endpoint, with request and response examples - [Authentication](https://example.com/docs/auth.md): OAuth 2.0 flows and token lifetimes ## Company - [Pricing](https://example.com/pricing.md): Plans, limits and overage rates - [Status](https://example.com/status): Live service status and incident history ## Optional - [Changelog](https://example.com/changelog.md): Release notes since 2024 ``` > The links should point at markdown versions of the pages, and the file must be served raw - an SPA catch-all that returns index.html for this path scores as a fail. ## Standards referenced - `llmstxt.org` ## Related checks | Check | Tier | Impact | Same skill | | --- | --- | --- | --- | | `reachable` — Homepage open to agent access | Essential | Critical | — | | `robots-txt` — robots.txt with agent directives | Essential | High | — | | `sitemap-xml` — sitemap.xml valid and current | Essential | High | — | | `link-headers` — Discovery via Link response headers | Emerging | Medium | — | | `dns-aid` — DNS-AID discovery record | Emerging | Medium | — | | `canonical` — Canonical and hreflang discipline | Recommended | Medium | — | | `llms-full` — /llms-full.txt expanded context | Recommended | Low | — | | `agents-md` — AGENTS.md with the required sections | Recommended | High | — | --- # Discovery via Link response headers > Discovery via Link response headers: RFC 8288 Link headers let an agent find your discovery resources without parsing HTML. - Source: /checks/link-headers - Site: AgenticWebScore - Language: English --- RFC 8288 Link headers let an agent find your discovery resources without parsing HTML. | Property | Value | | --- | --- | | Check id | `link-headers` | | Dimension | Discoverability (20%) | | Tier | Emerging — pool 5 pts | | Weight inside tier | 2 | | Impact | Medium | | Maturity | Adopted — A ratified standard with real deployment. | | Conditional | No | | Publishing skill | `link-headers` | | Standards | RFC 8288 | ## What is measured The scanner reads the Link response headers on https:/// ($home in the probe map) and parses them per RFC 8288: an angle-bracketed URI-reference followed by semicolon-separated parameters. Pass = at least one Link header that advertises a discovery resource with a registered relation, such as rel=describedby pointing at /llms.txt or rel=alternate with type=text/markdown. Partial = a Link header is present but carries no discovery relation (only preload or preconnect, for example). Fail = the homepage response carries no Link header at all. ## Reproduce it yourself You do not have to take our word for any of this. Run the same measurement against your own domain: ```bash DOMAIN=example.com curl -sS -D - -o /dev/null "https://$DOMAIN/" | grep -i '^link:' ``` ## The fix This is the artifact to ship. It is the complete change, not a description of one. ```text Link: ; rel="describedby"; type="text/plain", ; rel="alternate"; type="application/xml", ; rel="alternate"; type="text/markdown" # nginx equivalent add_header Link '; rel="describedby"; type="text/plain", ; rel="alternate"; type="application/xml"' always; ``` > Multiple links belong in one comma-separated Link header; relative targets are legal under RFC 8288 because they resolve against the request URI, but absolute URLs are safer for agents that do not track context. ## Standards referenced - `RFC 8288` ## Related checks | Check | Tier | Impact | Same skill | | --- | --- | --- | --- | | `reachable` — Homepage open to agent access | Essential | Critical | — | | `robots-txt` — robots.txt with agent directives | Essential | High | — | | `sitemap-xml` — sitemap.xml valid and current | Essential | High | — | | `llms-txt` — /llms.txt published and well-structured | Essential | Critical | — | | `dns-aid` — DNS-AID discovery record | Emerging | Medium | — | | `canonical` — Canonical and hreflang discipline | Recommended | Medium | — | | `llms-full` — /llms-full.txt expanded context | Recommended | Low | — | | `agents-md` — AGENTS.md with the required sections | Recommended | High | — | --- # DNS-AID discovery record > DNS-AID discovery record: Lets agents read discovery information over DNS without an HTTP round trip. Cloudflare added it to its readiness checklist. - Source: /checks/dns-aid - Site: AgenticWebScore - Language: English --- Lets agents read discovery information over DNS without an HTTP round trip. Cloudflare added it to its readiness checklist. | Property | Value | | --- | --- | | Check id | `dns-aid` | | Dimension | Discoverability (20%) | | Tier | Emerging — pool 5 pts | | Weight inside tier | 2 | | Impact | Medium | | Maturity | Experimental — An early convention that may still change shape. | | Conditional | No | | Publishing skill | `dns-aid` | | Standards | — | ## What is measured The scanner queries DNS-AID records over DNS: SVCB records (RR type 64) at the organization entry point _index._agents., as defined by DNS-AID (draft-mozleywilliams-dnsop-dnsaid), and at _agent., the older single-record form. It does not query the agent names an index advertises. Pass = at least one SVCB record resolves with a TargetName and at least one SvcParamKey such as well-known, alpn, port or cap. Partial = only the TXT fallback form is published, or a record exists but carries no SvcParamKeys. Fail = NXDOMAIN, or no SVCB and no TXT record at those names. Not measured = the DNS-over-HTTPS resolver answers none of the DNS-AID questions. ## Reproduce it yourself You do not have to take our word for any of this. Run the same measurement against your own domain: ```bash DOMAIN=example.com dig +short TYPE64 _index._agents.$DOMAIN; dig +short TYPE64 assistant.$DOMAIN ``` ## The fix This is the artifact to ship. It is the complete change, not a description of one. ```text ; DNS-AID records for example.com (draft-mozleywilliams-dnsop-dnsaid) ; Organization index entry point: the agents this domain advertises. _index._agents.example.com. 3600 IN SVCB 1 agent-index.example.com ( alpn="h2" port=443 well-known=agent-card.json ) ; One SVCB record per advertised agent. assistant.example.com. 3600 IN SVCB 1 . ( alpn="mcp,h2" port=443 ipv4hint=192.0.2.1 ipv6hint=2001:db8::1 well-known=agent-card.json cap=https://example.com/.well-known/agent-card.json ) ``` > TYPE64 is the SVCB record type by number, which also answers on older dig builds where the SVCB mnemonic silently returns nothing; publish on the authoritative nameservers for the apex domain, not on www. ## Related checks | Check | Tier | Impact | Same skill | | --- | --- | --- | --- | | `reachable` — Homepage open to agent access | Essential | Critical | — | | `robots-txt` — robots.txt with agent directives | Essential | High | — | | `sitemap-xml` — sitemap.xml valid and current | Essential | High | — | | `llms-txt` — /llms.txt published and well-structured | Essential | Critical | — | | `link-headers` — Discovery via Link response headers | Emerging | Medium | — | | `canonical` — Canonical and hreflang discipline | Recommended | Medium | — | | `llms-full` — /llms-full.txt expanded context | Recommended | Low | — | | `agents-md` — AGENTS.md with the required sections | Recommended | High | — | --- # Canonical and hreflang discipline > Canonical and hreflang discipline: An agent needs one consistent URL per important page. The fix: establish canonical and hreflang discipline. - Source: /checks/canonical - Site: AgenticWebScore - Language: English --- An agent needs one consistent URL per important page. | Property | Value | | --- | --- | | Check id | `canonical` | | Dimension | Discoverability (20%) | | Tier | Recommended — pool 20 pts | | Weight inside tier | 2 | | Impact | Medium | | Maturity | Adopted — A ratified standard with real deployment. | | Conditional | No | | Publishing skill | `canonical` | | Standards | — | ## What is measured The scanner extracts the link rel=canonical element and every link rel=alternate hreflang element from https:/// ($home in the probe map). Pass = exactly one absolute, self-referential canonical on https with no tracking parameters, plus, when translations exist, reciprocal hreflang alternates that include an x-default. Partial = a canonical that is relative to another host or points at a different URL, or hreflang values that no other language version links back to. Fail = no canonical element on the page. ## Reproduce it yourself You do not have to take our word for any of this. Run the same measurement against your own domain: ```bash DOMAIN=example.com curl -sS "https://$DOMAIN/" | grep -Eio ']+rel="(canonical|alternate)"[^>]*>' ``` ## The fix This is the artifact to ship. It is the complete change, not a description of one. ```html ``` > The canonical must be absolute and must repeat the exact URL an agent reached; hreflang only works when every language version lists all the others, including itself. ## Related checks | Check | Tier | Impact | Same skill | | --- | --- | --- | --- | | `reachable` — Homepage open to agent access | Essential | Critical | — | | `robots-txt` — robots.txt with agent directives | Essential | High | — | | `sitemap-xml` — sitemap.xml valid and current | Essential | High | — | | `llms-txt` — /llms.txt published and well-structured | Essential | Critical | — | | `link-headers` — Discovery via Link response headers | Emerging | Medium | — | | `dns-aid` — DNS-AID discovery record | Emerging | Medium | — | | `llms-full` — /llms-full.txt expanded context | Recommended | Low | — | | `agents-md` — AGENTS.md with the required sections | Recommended | High | — | --- # /llms-full.txt expanded context > /llms-full.txt expanded context: Lets an agent take in the full context in a single request instead of walking the site step by step. - Source: /checks/llms-full - Site: AgenticWebScore - Language: English --- Lets an agent take in the full context in a single request instead of walking the site step by step. | Property | Value | | --- | --- | | Check id | `llms-full` | | Dimension | Discoverability (20%) | | Tier | Recommended — pool 20 pts | | Weight inside tier | 1 | | Impact | Low | | Maturity | Draft — A published specification that is not yet ratified. | | Conditional | No | | Publishing skill | `llms-full-txt` | | Standards | — | ## What the scanner requests - `/llms-full.txt` - `/llms.txt` ## What is measured The scanner requests https:///llms-full.txt and also reads /llms.txt to see whether that file is advertised. Pass = /llms-full.txt returns 200 markdown containing the expanded text of the site's key pages, and /llms.txt links to it. Partial = the URL is linked from /llms.txt but 404s, or the file returns only a list of links instead of page text. Fail = neither file offers expanded context, or both paths return HTML. ## Reproduce it yourself You do not have to take our word for any of this. Run the same measurement against your own domain: ```bash DOMAIN=example.com curl -sS -o /dev/null -w 'llms-full.txt status=%{http_code} bytes=%{size_download}\n' "https://$DOMAIN/llms-full.txt"; curl -sS "https://$DOMAIN/llms.txt" | grep -i 'llms-full' ``` ## The fix This is the artifact to ship. It is the complete change, not a description of one. ```markdown # llms.txt - add this line to the Docs section - [Full context](https://example.com/llms-full.txt): Every page below as one document # llms-full.txt # Example Inc - full context > Complete text of the pages an agent needs, in a single request. Regenerated on every deploy. ## https://example.com/ (Home) Example Inc runs a payments API for marketplaces. Founded 2019, 40 staff, US-based. Production traffic is served from three regions. ## https://example.com/docs/quickstart (Quickstart) Install the CLI with `npm i -g example-cli`, authenticate with `example login`, then create a charge with `example charges create --amount 1000 --currency usd`. ## https://example.com/pricing (Pricing) Starter is $0 for 1,000 calls per month. Growth is $99 for 100,000 calls, then $0.001 per call. Enterprise is quoted annually. ``` > This file is the whole site minus navigation, so cap it at a few hundred KB and generate it from the same source as your pages or it will drift out of date. ## Related checks | Check | Tier | Impact | Same skill | | --- | --- | --- | --- | | `reachable` — Homepage open to agent access | Essential | Critical | — | | `robots-txt` — robots.txt with agent directives | Essential | High | — | | `sitemap-xml` — sitemap.xml valid and current | Essential | High | — | | `llms-txt` — /llms.txt published and well-structured | Essential | Critical | — | | `link-headers` — Discovery via Link response headers | Emerging | Medium | — | | `dns-aid` — DNS-AID discovery record | Emerging | Medium | — | | `canonical` — Canonical and hreflang discipline | Recommended | Medium | — | | `agents-md` — AGENTS.md with the required sections | Recommended | High | — | --- # AGENTS.md with the required sections > AGENTS.md with the required sections: The instruction file for coding and operations agents. The fix: publish AGENTS.md. - Source: /checks/agents-md - Site: AgenticWebScore - Language: English --- The instruction file for coding and operations agents. It fails more often than any other check in the curated corpus we measured, and the usual reason is not a missing file but a file without the sections an agent needs. | Property | Value | | --- | --- | | Check id | `agents-md` | | Dimension | Discoverability (20%) | | Tier | Recommended — pool 20 pts | | Weight inside tier | 2 | | Impact | High | | Maturity | Draft — A published specification that is not yet ratified. | | Conditional | No | | Publishing skill | `agents-md` | | Standards | — | ## What the scanner requests - `/AGENTS.md` ## What is measured The scanner fetches https:///AGENTS.md (the path this check probes) and reads it as markdown. Pass = 200 served as text/markdown or text/plain, with an H1 and the sections an agent needs to act: what the project or service is, setup or build commands, how to run tests, code or API conventions, and security or contact rules. Partial = the file is served but omits one or more of those sections, or is returned as text/html. Fail = 404 or an HTML page for the path. ## Reproduce it yourself You do not have to take our word for any of this. Run the same measurement against your own domain: ```bash DOMAIN=example.com curl -sS "https://$DOMAIN/AGENTS.md" | head -30 ``` ## The fix This is the artifact to ship. It is the complete change, not a description of one. ```markdown # AGENTS.md ## Project overview Example Inc is a payments API for marketplaces. Public docs: https://example.com/docs ## Setup and build - Install dependencies: `pnpm install` - Dev server: `pnpm dev` (http://localhost:3000) - Production build: `pnpm build` ## Testing - Tests: `pnpm test`; lint and types: `pnpm lint && pnpm typecheck` ## Conventions - TypeScript strict mode; no `any` in exported signatures. - Public API routes live in `src/routes/api/` and must be documented in the OpenAPI file. ## Security and contact - Never commit secrets; use `.env.local`. - Report vulnerabilities to security@example.com. ``` > AGENTS.md is plain markdown with no mandated fields, so the headings above are the sections this audit looks for - and in a monorepo the file nearest the edited code wins. ## Related checks | Check | Tier | Impact | Same skill | | --- | --- | --- | --- | | `reachable` — Homepage open to agent access | Essential | Critical | — | | `robots-txt` — robots.txt with agent directives | Essential | High | — | | `sitemap-xml` — sitemap.xml valid and current | Essential | High | — | | `llms-txt` — /llms.txt published and well-structured | Essential | Critical | — | | `link-headers` — Discovery via Link response headers | Emerging | Medium | — | | `dns-aid` — DNS-AID discovery record | Emerging | Medium | — | | `canonical` — Canonical and hreflang discipline | Recommended | Medium | — | | `llms-full` — /llms-full.txt expanded context | Recommended | Low | — | --- # /sitemap.md markdown site map > /sitemap.md markdown site map: Lets an agent read your site structure as markdown in a single file. The fix: publish a markdown sitemap. - Source: /checks/sitemap-md - Site: AgenticWebScore - Language: English --- Lets an agent read your site structure as markdown in a single file. Adoption is still very low, so this is an early-mover advantage. | Property | Value | | --- | --- | | Check id | `sitemap-md` | | Dimension | Discoverability (20%) | | Tier | Emerging — pool 5 pts | | Weight inside tier | 1 | | Impact | Low | | Maturity | Draft — A published specification that is not yet ratified. | | Conditional | No | | Publishing skill | `sitemap-md` | | Standards | — | ## What the scanner requests - `/sitemap.md` ## What is measured The scanner fetches https:///sitemap.md (the exact path this check probes) and parses it as markdown. Pass = 200 markdown whose body is an H1 plus markdown links to the site's key pages written as absolute URLs. Partial = markdown is served but the links are relative, are not a list, or cover only a couple of top-level pages. Fail = 404, or an HTML document returned for the path. ## Reproduce it yourself You do not have to take our word for any of this. Run the same measurement against your own domain: ```bash DOMAIN=example.com curl -sS "https://$DOMAIN/sitemap.md" | head -30 ``` ## The fix This is the artifact to ship. It is the complete change, not a description of one. ```markdown # Sitemap - [Home](https://example.com/): What Example Inc does and who it is for - [Quickstart](https://example.com/docs/quickstart): First API call in five minutes - [API reference](https://example.com/docs/api): Every endpoint and response field - [Authentication](https://example.com/docs/auth): OAuth 2.0 flows and token lifetimes - [Pricing](https://example.com/pricing): Plans, limits and overage rates - [Status](https://example.com/status): Live service status and incident history - [Contact](https://example.com/contact): Sales and support routes ``` > Keep it to the pages an agent should actually read and regenerate it whenever sitemap.xml changes, since the two drifting apart is the usual failure. ## Related checks | Check | Tier | Impact | Same skill | | --- | --- | --- | --- | | `reachable` — Homepage open to agent access | Essential | Critical | — | | `robots-txt` — robots.txt with agent directives | Essential | High | — | | `sitemap-xml` — sitemap.xml valid and current | Essential | High | — | | `llms-txt` — /llms.txt published and well-structured | Essential | Critical | — | | `link-headers` — Discovery via Link response headers | Emerging | Medium | — | | `dns-aid` — DNS-AID discovery record | Emerging | Medium | — | | `canonical` — Canonical and hreflang discipline | Recommended | Medium | — | | `llms-full` — /llms-full.txt expanded context | Recommended | Low | — | --- # Markdown content negotiation for AI agents > Markdown content negotiation: Agents can request a markup-free version with "Accept: text/markdown", which cuts token cost. - Source: /checks/markdown-negotiation - Site: AgenticWebScore - Language: English --- Agents can request a markup-free version with "Accept: text/markdown", which cuts token cost. | Property | Value | | --- | --- | | Check id | `markdown-negotiation` | | Dimension | Content Accessibility (22%) | | Tier | Recommended — pool 20 pts | | Weight inside tier | 3 | | Impact | Critical | | Maturity | Adopted — A ratified standard with real deployment. | | Conditional | No | | Publishing skill | `markdown-negotiation` | | Standards | RFC 9110 | ## What is measured The scanner re-requests the homepage `/` with `Accept: text/markdown` and inspects the response headers and body. Pass when the response carries `Content-Type: text/markdown`, the body is markdown rather than HTML (no ``, no `
` scaffolding) and it is materially shorter than the HTML page; partial when markdown is returned under another type such as `text/plain`, or when the response omits `Vary: Accept` so a shared cache can serve the markdown body to a browser; fail when the request still returns `text/html`. RFC 9110 proactive negotiation, one URL with two representations. ## Reproduce it yourself You do not have to take our word for any of this. Run the same measurement against your own domain: ```bash DOMAIN="https://example.com" curl -sSL -D /tmp/md.h -o /tmp/md.body -H 'Accept: text/markdown' "$DOMAIN/"; grep -iE '^(HTTP/|content-type|vary)' /tmp/md.h; head -3 /tmp/md.body ``` ## The fix This is the artifact to ship. It is the complete change, not a description of one. ```javascript // server.js — serve a prebuilt markdown twin on Accept: text/markdown (RFC 9110). import express from 'express'; import { readFile } from 'node:fs/promises'; const app = express(); app.use(async (req, res, next) => { if (req.method !== 'GET') return next(); res.vary('Accept'); // both representations share one URL, so caches must key on Accept if (req.accepts(['text/html', 'text/markdown']) !== 'text/markdown') return next(); const file = `./public${req.path.replace(/\/$/, '/index')}.md`; try { res.type('text/markdown').send(await readFile(file, 'utf8')); } catch { next(); // no markdown twin for this path: fall back to the HTML document } }); app.use(express.static('public')); app.listen(3000); ``` > Generate the `.md` twin at build time — converting HTML to markdown on every request is slower and lossy — and keep `Vary: Accept` on the HTML response too. ## Standards referenced - `RFC 9110` ## Related checks | Check | Tier | Impact | Same skill | | --- | --- | --- | --- | | `headings` — Semantic heading structure | Essential | High | — | | `meta` — Title and summary metadata | Essential | High | — | | `jsonld` — JSON-LD structured data | Essential | Critical | — | | `faq-schema` — FAQ / question-answer schema | Recommended | High | — | | `breadcrumb` — Breadcrumb / navigation schema | Emerging | Low | — | | `summary` — Prominent summary block | Recommended | Medium | — | | `lang` — Language declaration and multilingual access | Recommended | Medium | — | | `no-js-fallback` — Content that needs no JavaScript | Essential | High | — | --- # Semantic heading structure > Semantic heading structure: A single H1 and a consistent H2 structure let the content be split correctly. The fix: build a semantic heading structure. - Source: /checks/headings - Site: AgenticWebScore - Language: English --- A single H1 and a consistent H2 structure let the content be split correctly. | Property | Value | | --- | --- | | Check id | `headings` | | Dimension | Content Accessibility (22%) | | Tier | Essential — pool 80 pts | | Weight inside tier | 2 | | Impact | High | | Maturity | Adopted — A ratified standard with real deployment. | | Conditional | No | | Publishing skill | `semantic-headings` | | Standards | WCAG 2.2 | ## What is measured The scanner parses the headings in the homepage `/` HTML and rebuilds the outline. Pass when the page has exactly one `

` and no heading is more than one level deeper than the one before it (an `

` may be followed by `

`, never by `

`); partial when there is exactly one `

` but the outline skips a level, or when the page repeats `

` while the rest of the outline is well formed; fail when the page has no `

` at all. This is the WCAG 2.2 heading structure (1.3.1 Info and Relationships, 2.4.6 Headings and Labels). ## Reproduce it yourself You do not have to take our word for any of this. Run the same measurement against your own domain: ```bash DOMAIN="https://example.com" curl -sL "$DOMAIN/" | perl -0777 -ne 'while (m{<(h[1-6])\b[^>]*>(.*?)}gsi) { my ($l,$t)=(lc($1),$2); $t=~s/<[^>]*>//g; $t=~s/\s+/ /g; print "$l ",substr($t,0,60),"\n" }' ``` ## The fix This is the artifact to ship. It is the complete change, not a description of one. ```html

Agent readiness for e-commerce teams

A 5-dimension audit of how well your store serves autonomous AI agents.

What we measure

Discovery, content, bot access, protocol and commerce signals.

Structured data

Entity types an agent can quote without having to guess.

How the score works

61 weighted checks, graded from C to AAA.

``` > Never pick a heading tag for its font size: if a block has no heading, style a `

` instead and keep `

` for the page title only. ## Standards referenced - `WCAG 2.2` ## Related checks | Check | Tier | Impact | Same skill | | --- | --- | --- | --- | | `markdown-negotiation` — Markdown content negotiation | Recommended | Critical | — | | `meta` — Title and summary metadata | Essential | High | — | | `jsonld` — JSON-LD structured data | Essential | Critical | — | | `faq-schema` — FAQ / question-answer schema | Recommended | High | — | | `breadcrumb` — Breadcrumb / navigation schema | Emerging | Low | — | | `summary` — Prominent summary block | Recommended | Medium | — | | `lang` — Language declaration and multilingual access | Recommended | Medium | — | | `no-js-fallback` — Content that needs no JavaScript | Essential | High | — | --- # Title and summary metadata > Title and summary metadata: This is how an agent learns what a page is about without opening it. The fix: add a title and meta description. - Source: /checks/meta - Site: AgenticWebScore - Language: English --- This is how an agent learns what a page is about without opening it. | Property | Value | | --- | --- | | Check id | `meta` | | Dimension | Content Accessibility (22%) | | Tier | Essential — pool 80 pts | | Weight inside tier | 2 | | Impact | High | | Maturity | Adopted — A ratified standard with real deployment. | | Conditional | No | | Publishing skill | `page-metadata` | | Standards | — | ## What is measured The scanner reads the `` text and the `content` of `<meta name="description">` in the homepage `/` HTML and measures their length. Pass when the title is 50-60 characters and the description 120-160 characters, both non-empty; partial when both are present but one or both fall outside that window (too short to be informative, or long enough to be truncated), or when only one of the two exists; fail when the page has neither a title nor a description. ## Reproduce it yourself You do not have to take our word for any of this. Run the same measurement against your own domain: ```bash DOMAIN="https://example.com" curl -sL "$DOMAIN/" | perl -0777 -ne 'm{<title[^>]*>(.*?)}si and do { my $t=$1; $t=~s/\s+/ /g; print "title(", length($t), "): $t\n" }; m{]*\bname=["\x27]?description["\x27]?[^>]*>}i and print "description: ", $&, "\n"' ``` ## The fix This is the artifact to ship. It is the complete change, not a description of one. ```html Agent readiness audit for e-commerce teams | Acme Inc ``` > Write a distinct description per page: one templated string reused across 500 URLs tells an agent nothing about which page it is reading. ## Related checks | Check | Tier | Impact | Same skill | | --- | --- | --- | --- | | `markdown-negotiation` — Markdown content negotiation | Recommended | Critical | — | | `headings` — Semantic heading structure | Essential | High | — | | `jsonld` — JSON-LD structured data | Essential | Critical | — | | `faq-schema` — FAQ / question-answer schema | Recommended | High | — | | `breadcrumb` — Breadcrumb / navigation schema | Emerging | Low | — | | `summary` — Prominent summary block | Recommended | Medium | — | | `lang` — Language declaration and multilingual access | Recommended | Medium | — | | `no-js-fallback` — Content that needs no JavaScript | Essential | High | — | --- # JSON-LD structured data > JSON-LD structured data: The entity type becomes unambiguous to a machine. Without authoritative data, an agent answers from whatever it can scrape. - Source: /checks/jsonld - Site: AgenticWebScore - Language: English --- The entity type becomes unambiguous to a machine. Without authoritative data, an agent answers from whatever it can scrape. | Property | Value | | --- | --- | | Check id | `jsonld` | | Dimension | Content Accessibility (22%) | | Tier | Essential — pool 80 pts | | Weight inside tier | 3 | | Impact | Critical | | Maturity | Adopted — A ratified standard with real deployment. | | Conditional | No | | Publishing skill | `structured-data` | | Standards | schema.org | ## What is measured The scanner extracts every `}gsi) { print "$1\n" }' | jq -r '[(."@context"? // empty | tostring)] + [.. | objects | select(has("@type")) | ."@type" | tostring] | unique | @tsv' ``` ## The fix This is the artifact to ship. It is the complete change, not a description of one. ```html ``` > One valid block beats five broken ones: JSON-LD is parsed, not scraped, so a single trailing comma makes the whole entity invisible. ## Standards referenced - `schema.org` ## Related checks | Check | Tier | Impact | Same skill | | --- | --- | --- | --- | | `markdown-negotiation` — Markdown content negotiation | Recommended | Critical | — | | `headings` — Semantic heading structure | Essential | High | — | | `meta` — Title and summary metadata | Essential | High | — | | `faq-schema` — FAQ / question-answer schema | Recommended | High | — | | `breadcrumb` — Breadcrumb / navigation schema | Emerging | Low | — | | `summary` — Prominent summary block | Recommended | Medium | — | | `lang` — Language declaration and multilingual access | Recommended | Medium | — | | `no-js-fallback` — Content that needs no JavaScript | Essential | High | — | --- # FAQ / question-answer schema > FAQ / question-answer schema: Question-and-answer content is the type agents quote most. The fix: add FAQ schema. Standard: schema.org/FAQPage. - Source: /checks/faq-schema - Site: AgenticWebScore - Language: English --- Question-and-answer content is the type agents quote most. | Property | Value | | --- | --- | | Check id | `faq-schema` | | Dimension | Content Accessibility (22%) | | Tier | Recommended — pool 20 pts | | Weight inside tier | 2 | | Impact | High | | Maturity | Draft — A published specification that is not yet ratified. | | Conditional | No | | Publishing skill | `faq-schema` | | Standards | schema.org/FAQPage | ## What is measured This check declares no probe path, so the scanner works from the JSON-LD of the already fetched homepage `/` and looks for a `FAQPage` entity anywhere in the graph. Pass when `FAQPage` is present and `mainEntity` is a non-empty array of objects typed `Question` that each carry a `name` and an `acceptedAnswer` typed `Answer` with non-empty `text`; partial when `FAQPage` exists but `mainEntity` is empty, when an entry is not typed `Question`, or when a question lacks a typed, non-empty `acceptedAnswer`; fail when no `FAQPage` type appears. ## Reproduce it yourself You do not have to take our word for any of this. Run the same measurement against your own domain: ```bash DOMAIN="https://example.com" curl -sL "$DOMAIN/" | perl -0777 -ne 'while (m{]*application/ld\+json[^>]*>(.*?)}gsi) { print "$1\n" }' | jq -r '.. | objects | select((."@type"? | if type == "array" then .[] else . end) == "FAQPage") | .mainEntity[] | [.name, (.acceptedAnswer.text // "NO ANSWER")] | @tsv' ``` ## The fix This is the artifact to ship. It is the complete change, not a description of one. ```html ``` > The same questions must be visible as text on the page — structured data that does not match rendered content is treated as spam. ## Standards referenced - `schema.org/FAQPage` ## Related checks | Check | Tier | Impact | Same skill | | --- | --- | --- | --- | | `markdown-negotiation` — Markdown content negotiation | Recommended | Critical | — | | `headings` — Semantic heading structure | Essential | High | — | | `meta` — Title and summary metadata | Essential | High | — | | `jsonld` — JSON-LD structured data | Essential | Critical | — | | `breadcrumb` — Breadcrumb / navigation schema | Emerging | Low | — | | `summary` — Prominent summary block | Recommended | Medium | — | | `lang` — Language declaration and multilingual access | Recommended | Medium | — | | `no-js-fallback` — Content that needs no JavaScript | Essential | High | — | --- # Breadcrumb / navigation schema > Breadcrumb / navigation schema: Helps an agent make sense of where a page sits in your site. The fix: add breadcrumb schema. - Source: /checks/breadcrumb - Site: AgenticWebScore - Language: English --- Helps an agent make sense of where a page sits in your site. | Property | Value | | --- | --- | | Check id | `breadcrumb` | | Dimension | Content Accessibility (22%) | | Tier | Emerging — pool 5 pts | | Weight inside tier | 1 | | Impact | Low | | Maturity | Draft — A published specification that is not yet ratified. | | Conditional | No | | Publishing skill | `breadcrumb-schema` | | Standards | schema.org/BreadcrumbList | ## What is measured This check declares no probe path, so the scanner walks the JSON-LD of the fetched homepage `/` for a `BreadcrumbList` and inspects `itemListElement`. Pass when the list has at least two entries typed `ListItem` whose `position` values start at 1 and increase by one, each with a `name` and an `item` that is a resolvable URL (an absolute http(s) URL or a host-relative path — a bare string such as `garbage` is not an item URL). The last entry may omit `item` entirely, as Google's breadcrumb guidance allows, because it stands for the current page. Partial when `BreadcrumbList` is present but an entry is not typed `ListItem`, a position is missing or out of order, an entry before the last has no resolvable `item` URL, or any entry carries an `item` that is not one; fail when no `BreadcrumbList` appears. ## Reproduce it yourself You do not have to take our word for any of this. Run the same measurement against your own domain: ```bash DOMAIN="https://example.com" curl -sL "$DOMAIN/" | perl -0777 -ne 'while (m{]*application/ld\+json[^>]*>(.*?)}gsi) { print "$1\n" }' | jq -r '.. | objects | select((."@type"? | if type == "array" then .[] else . end) == "BreadcrumbList") | .itemListElement[] | [(.position|tostring), .name, ((.item."@id" // .item) // "NO URL")] | @tsv' ``` ## The fix This is the artifact to ship. It is the complete change, not a description of one. ```html ``` > Mirror the same trail as visible links in a `