Rubric v0.7 · updated 2026-10-12
Methodology and rubric
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.
The scoring contract
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 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-txtpasses only while itsExpiresfield is in the future. -
status-pagereports 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-aidreads 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 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? |
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.
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
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. |
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.
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 = SHA-256( JSON( {
v: 2,
host: "<host, trimmed and lowercased>",
rubric: "<rubric version>",
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.
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.
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-txtandstatus-page, the 12 s request timeout, the 60 s scan deadline, and DNS fordns-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 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.
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.
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 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: 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: 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: The remotes sampled are those of the first card that offers a transport, which is the card the check reads. -
mcp-card,api-catalog,agent-skills,oauth-discovery,status-page,docs, andsandbox-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: 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: 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: 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: 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,openapi, andapi-catalog: The detail adds sentences prefixed “Not scored:” about the endpoints the document declares. They never change the status or the points. -
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: The detail names the remotes the scan did not request, instead of saying it requested them. -
openapi: A partial names the missing info.title or info.version, instead of saying the document has no callable operation. -
dns-aid: One TXT record that both resolvers return counts once in the detail. -
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: The measures text names the homepage statuses that make the whole scan not measured, which the engine already did. -
llms-txt: The measures text names every partial the check returns, including a missing blockquote and an H1 after other lines. -
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,docs, andoauth-discovery: The measures text describes the requests the scan now makes for these checks. -
dns-aid: The measures text names _agent.<domain>, 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 |