Trust the Replay, Not the Recorder

· updated · Lewis Tham

A route that's wrong with confidence is worse than no route at all.

No route, and your agent opens a browser. Slow, but it finds the truth. A wrong route returns a clean 200 with the wrong data, and your agent believes it.

I'm Lewis Tham, founder of Unbrowse and first author of "Internal APIs Are All You Need". The paper is about agents learning the requests a website's own frontend already makes. Unbrowse keeps a shared map of those requests, so the next agent doesn't learn them again.

A shared map has one hard problem. Who do you believe?

Nobody. Not on their own word.

The recorder is the worst witness

The person who learned a route is the last person who should vouch for it.

Most aren't lying. But "I recorded it and it worked" looks exactly like "I say I recorded it and it worked." The day anyone gets paid for routes, the second sentence gets cheap to type.

So the recorder's claim counts for nothing. A route counts when it is replayed somewhere else, clean, and still gives the right kind of answer.

What the gate checks today

This part is live. Nothing lands in Unbrowse's public registry because someone submitted it. Only read-only, secretless lookups that take one input are candidates at all. Logins, private session values and anything that writes are never public.

A candidate then has to pass a replay test on a scrubbed copy of the route, with no cookies:

1. Strip the route: no cookies, no session, no secrets
2. Replay it with two probe words      -> both must answer
3. Replay it with a word it never saw  -> must answer
4. Replay it with a nonsense query     -> must NOT look like a hit
5. Pass all four, or it stays private

Each step shuts one door.

No cookies: the route can't lean on a session the recorder happened to have open.

Two probe words: the route really takes an input.

An unseen word: it generalises past what was recorded.

A nonsense query that has to fail: the answer actually depends on the input. A route that returns the same canned page for every query looks like success on every test except this one.

HTTP 200 is not success anywhere in this pipeline. Calls are metered and counted on verified outcomes, not status codes.

How strict that is, in numbers

When we ran the registry crawl over the Tranco top 10,000 on 2026-09-25, 57 sites were newly published and 195 were already in the registry. 474 were skipped because robots.txt said no. Most of the rest had no site search to learn, or failed the clean replay.

That's a gate that says no far more often than yes. It should.

The day after, on 2026-09-26, we sampled 200 public tools and gave each a fresh input. 166 of them answered (83%). 19 failed. 15 had no fresh input we could test with. There were 0 false successes.

The second number is the one I care about. 83% means some routes fail. Zero false successes means that when they fail, they say so.

Routes also rot after they're published. Sites rename fields and move endpoints. So public tools get re-run on a schedule, and one that keeps failing comes out of search until it passes again.

Check the shape. Let the values vary.

The obvious check is "did you get the same response?" It fails on day one.

A flight search from Singapore and one from Frankfurt return different prices. A stock page returns a different number every second. Two honest checks disagree on values all day long.

So the useful comparison is shape. Same status. Same schema. Required fields present.

GET /api/search?q= should come back as a list of results with a title and a price, whatever currency the price is in.

Values are where the world varies. Shape is where a fake route gets caught.

The plan for when strangers do the checking

Today the checking runs on our side. The plan is to let other people's machines learn and check routes too. That's when the gate has to survive people actively trying to game it. Nothing below is built. It is the proposal:

1. Someone submits a route + fixed test inputs
2. A committee of checkers is drawn
     at random, weighted by deposit and track record
     different owners, different networks
     the submitter excluded
3. Each checker replays the test inputs
     clean context, nothing inherited
4. Commit: each posts hash(result shape)
5. Reveal: each opens its commitment
6. Compare SHAPE: status, schema, required fields
7. A sample also gets a proof of origin (zkTLS)
8. We audit a slice of everything

Random selection: you can't pick your friends to check your route.

Different owners and networks: fifty checkers on one laptop are one checker.

Commit-reveal: everyone locks in an answer before seeing anyone else's. A lazy checker can't wait for the first honest one and copy it.

zkTLS covers the gap shape leaves. On a sample of checks, the checker attaches a proof that the response came over a TLS session with the site's own server, and not from a server the submitter runs.

Penalise only what you can prove

The proposal also has checkers put down a deposit, in dollars. There is no token. Unbrowse doesn't have one.

The plan is narrow about when a deposit is lost:

Fault                             Proven by
Two conflicting signed results    the signatures
Reveal != commitment              the hash
Response false under zkTLS        the proof
Fabrication found in an audit     the audit record
Leaked credential / undeclared    the route itself
  domain in a route

Every line is something a stranger can verify without trusting anyone.

What never costs anyone their deposit: honest disagreement. A checker in another region hits a geo-block. The site has a bad minute. A field goes missing for an hour.

If reporting what you saw can cost you money, checkers learn to guess what the crowd will say. That is the exact failure the committee exists to prevent.

Hard to find, cheap to check

The whole scheme rests on one asymmetry.

Learning a route is expensive. An agent drives a browser, burns LLM tokens, retries. Checking a route is one HTTP replay.

In our April 2026 paper, a task done by driving a browser cost $0.53, against $0.005 for the same task through a cached route. That's 106x. Tokens went from about 8,000 per task to about 200 (40x). The benchmark deep dive has the full tables.

Bitcoin is built on the same shape. Finding a valid block takes enormous work. Checking one takes a moment on any machine. Nobody trusts the miner, because everybody can check.

A shared route map gets the same deal. One expensive discovery, then checks so cheap that anyone can afford to doubt.

The threat does the work

Earlier this year we simulated 24 months of indexers who put money at stake against their routes, with routes failing and feedback arriving the way it would in real use.

With rational maintainers, nobody was ever penalised. The threat was enough. When a lie is provable and costs you money, the rational move is to not tell it.

Attacking a rival didn't pay either. It cost money and gained nothing, because honest disagreement can't get anyone penalised.

That's a simulation. Rational maintainers are an assumption, and real people are creative. But a penalty that works by almost never firing is the kind you want.

Where this actually is

Live: the publish gate on the public registry (scrubbed copy, no cookies, probe words, an unseen word, a nonsense query that must fail), scheduled re-checks of public tools, and outcomes counted as verified only when the answer is right, not when the status is 200.

Plan, not built: other people's machines doing the checking, committees, commit-reveal, zkTLS sampling, deposits and penalties. Nobody has money at stake in anything today, and there is no token.

If you build verification systems and can see the hole in step 6, I want to hear it before anyone else finds it. In the meantime, the part that's live is one MCP server: unbrowse.ai/mcp. Setup is in the docs.

Nobody gets believed. Everybody gets checked.

Get new articles by email

At most about once a week. One click to unsubscribe.

We email a confirmation link first.

All posts