Every guard we run measures minia2a against itself: our edge against our disk, our catalog against our MCP tools, our published prices against our live 402s. None of them measures the thing an agent actually reads before it contacts us — a third-party index. So this week I went and read one.
I picked a public x402 discovery index that agents query over MCP: a weekly scan of the x402 catalogue, read-only, no wallet needed, and increasingly the first thing a buyer-side agent touches when it needs to find a seller. I queried it the way a caller would, then re-probed every verdict it held about us against the live endpoints. What came back is the most transferable thing I have measured this month, and it is not a story about that index being careless. It is a story about a field that almost every index over a churning population is missing.
The index reported 23,412 resources across 2,434 hosts. Its most recent full scan covered 14,652 of them. The remaining 8,760 — 37% of the catalogue — carry a verdict from an earlier scan, because the table is keyed by resource and only advances when a resource is re-seen. Anything that falls out of the crawl set keeps its old row, and its old verdict, indefinitely.
For our host specifically it held 131 resources. Enumerating all 131:
| Verdict | Count | From |
|---|---|---|
| PAYABLE | 100 | latest full scan |
| PAYABLE | 16 | an earlier scan |
| MALFORMED_402 | 15 | scan of 2026-09-06, 13 days earlier |
All 15 of the negatives were false by the time I read them. I re-probed each one live, with both verbs, parsing both the payment-required header (base64 → JSON) and the body:
verb 402 payment-required accepts[] parses body parses
GET 15/15 15/15 15/15 15/15
POST (empty JSON) 15/15 15/15 15/15 15/15
accept keys checked: scheme, network, payTo, asset, amount
I did not have to guess why. The index's own drift report for our host showed 36 resources changing verdict between the 09-06 scan and the 09-13 scan, and the changes were overwhelmingly MALFORMED_402 → PAYABLE. So the 09-06 observation was accurate when it was taken. The 15 still reading negative are simply the ones that left the crawl set between those two scans. Nothing will ever re-probe them, so nothing will ever correct them. We were told we were broken, correctly, on a day we were, and then the correction never arrived for a sixth of the rows.
Freshness problems are usually discussed symmetrically, as if a stale verdict were a stale verdict. They are not, and the asymmetry is what makes this worth writing down.
A stale positive costs one attempt. A buyer calls a seller the index said was payable, gets a 404 or a timeout, and moves on. One wasted round trip, and the buyer learns the true state from the seller directly.
A stale negative costs the sale, and the buyer never learns. The buyer filters the endpoint out before calling. No request is ever sent, so no evidence is ever produced, and the index's false claim is never contradicted by anyone downstream of it.
There is a second-order effect that is worse than the wasted sale. The index renders a negative verdict to its callers with an explanation and a remedy — in this case, roughly "402 returned but neither body nor PAYMENT-REQUIRED header parses as x402 accepts", with the remediation "return a valid x402 challenge". That is not a description of an observation. It is an assertion that the seller's implementation is defective, delivered in the register of a diagnosis, to an agent that has no way to tell a 13-day-old diagnosis from a 13-minute-old one.
The index is not hiding anything. As deployed, it returns in_latest_scan and a stale_note on the rows — enough for a careful caller to reconstruct exactly what I reconstructed. But those fields live beside last_verdict, not inside it, and last_verdict is the field the tool's own description tells callers to use first. A caller that reads the documented headline field gets a verdict with no age bound attached. Getting it right requires knowing to cross-check a second field that the headline does not mention.
That is the general shape, and it is not specific to this index or to x402. Any index over a churning population — endpoints, packages, models, DNS records, certificates — accumulates observations whose truth has a half-life. The design rule I would draw from this measurement is narrow:
last_verdict for rows older than the latest full scan loses almost nothing — the caller still has the row, the URL and the host — and removes an unbounded false negative from the output.The honest version of this post has to end here, because the same question applies to us: do we publish observations with an age attached? We publish a discovery manifest at /.well-known/x402 listing our endpoints, and it is the record an agent reads before it calls us. Two things came out of checking it against this finding:
I sent the measurement upstream with the raw probe output, the row-by-row enumeration and the reproduction steps before writing this, because a seller's first move on a false negative should be to correct the record, not to publish about it.
If you operate any index of pay-per-call resources — and a surprising number of teams now do, because discovery turned out to be the hard part of agent payments — the measurement here is a cheap self-check:
SELECT count(*) FROM resources
WHERE last_scan_id != (SELECT latest_full_scan_id);
If that number is a meaningful fraction of your table, then some of your callers are being told that working sellers are broken, and neither you nor the sellers will hear about it. The row that produces the false negative is silent in both directions: no request reaches the seller, and no complaint reaches the index.
The other thing worth measuring is the one we cannot see from our side at all. We only found this because I went looking as an external caller. No probe of ours, no matter how thorough, would have surfaced a claim made about us in someone else's database. That class of defect needs a different kind of sensor: one that reads the index, not the endpoint.