Proof of response.

Assay gives every open-weight AI response a receipt. It names the model and the host, the host signs it and anchors it on Monad, and you can co-sign it with your passkey.

It proves who served which bytes and what they claimed. Not which weights ran.

Your prompt and answer never go onchain. Only salted hashes do, and you keep the salt.

An animation of dots: a printed receipt becomes a Merkle batch, then a passkey fingerprint, then the Assay mark.

[ SIGNED ] The host signs every response it serves. X-Assay-Receipt: ES256 JWS

Every answer comes with a receipt.

This receipt lives on mainnet. A receipt never moves between chains, so it looks the same on either network.

This is the first receipt Assay anchored on Monad mainnet, on 5 Oct 2026. Every value on it is real. Scroll, and each part is stamped as it's explained.

ASSAY RECEIPT No. 0x1b44…c5f2 Monad mainnet, chain 143 2026-10-05 06:46:51 UTC
HOST10278 MODELclaimed ANCHORmonad YOUnot yet

MODEL
gemma-4-31b-it
HOST
erc8004:143:10278
SIGNED
ES256, key 2Jc6…qg0
PROMPT
0xdc6d…6e23sha256(salt ‖ prompt)
ANSWER
0xdd16…b6ddsha256(salt ‖ output)
TOKENS
in 8, out 1, stop
MAX TOKENS
256

BATCH ROOT
0x4066…60cb1 receipt
ANCHORED
block 110,684,366
TX
0x48bc…a9a4
CO-SIGNED
not co-signed

0x1b443b45…2e35c5f2
TERMS

This receipt proves which host served these bytes and what it claimed. It does not prove which weights ran. Your prompt and answer never go onchain. Only salted hashes do.

KEEP YOUR SALTassay-ten-xi.vercel.app

Assay receipt for response 0x1b44…c5f2: model gemma-4-31b-it, served by host erc8004:143:10278, signed ES256, anchored on Monad mainnet in block 110,684,366, not co-signed.

Read from the host's public API, 11 Oct 2026

  1. HOST

    Signed by the host.

    Host 10278 signed these exact bytes with an ES256 key tied to its ERC-8004 identity. Your browser checks the signature against the host's published key.

  2. MODEL

    The model it claimed.

    gemma-4-31b-it sits inside the signed body. If the claim were false, it would be a signed false claim the host can't take back.

  3. ANCHOR

    Anchored on Monad.

    The receipt sits in a batch whose root landed in block 110,684,366. Monad's P256 precompile checked the host's signature on that root.

  4. YOU

    Co-signed by you, when you ask.

    Nobody co-signed this one, so its YOU stamp stays empty. When you ask through Assay, your passkey can add the fourth mark. No wallet needed.

  5. TERMS

    The limits are printed on it.

    It proves who served which bytes and what they claimed. It doesn't prove which weights ran. That gap is why hosts also get graded against the lab's own endpoint.

Every check runs in your browser.

Open any receipt on its own page: the host's signature, its batch on Monad, the host's grade from verifiers you trust, and a line that reproduces each check.

Same model. Different hosts. Different bills.

The text you get back from an open-weight model carries no proof of who served it, or of what they did with your request.

126×

I asked 16 hosts serving Kimi K2.6 for at most 16 tokens. Thirteen stopped at 16. Three kept going in 59 of 60 tries, and billed up to 126 times what Moonshot's own endpoint charged.

One model, one prompt, one day: 8 Oct 2026, 350 requests. Hosts are named on 25 Oct, after their 7 days to reply. Read the write-up

13 hosts stopped at 16 3 hosts returned about 1,750 to 2,160
GLM-5.3 on OpenRouter, 26 Sep 202637

endpoints serving one open-weight model, from different providers.

16

of them don't state their precision at all.

8

declare a 4-bit format.

$1.19 to $8.80

per million output tokens, cheapest endpoint to priciest.

90% vs 75%

DeepSeek V4 Flash on GPQA through the lab's own API, and through one third-party host. Measured by Olly.

39%

of 735 endpoints across 140 open-weight models list their precision as unknown.

Source: the Assay hosting report v0, built from OpenRouter's public endpoints API on 26 Sep 2026. Read the report

What a receipt proves, and what it doesn't.

A receipt proves

  • Which host served these exact bytes.
  • Which model the host claimed, signed so it can't be denied later.
  • That it sits in a batch the host anchored on Monad.
  • Who asked, if you co-signed with your passkey.

It doesn't prove

  • Which weights actually ran. A host can still sign a claim it didn't keep.

That gap is why hosts get graded against the lab's own endpoint, with the raw logs published. Hosts that sign from inside a TEE, with a model hash in the attestation, are next on the roadmap.

Read the threat model
  1. Level 0, live on mainnetSigned and anchored

    The host signed what it served and the batch is on Monad.

  2. Level 1, live on mainnetHost graded

    Open verifiers test the host against the lab's own endpoint.

  3. Level 2, roadmapRe-executable

    A deterministic runtime lets anyone re-run a revealed request.

  4. Level 3, roadmapTEE attested

    The host signs from an enclave whose attestation names the model.

Wrap fetch. Keep the receipt.

The SDK sends the salt and your co-signer key with each request, parses the receipt from the response and checks that the output commit matches what you received.

$ npm install assay-receipts

From an empty folder, it verifies the first mainnet receipt in about a second.

  • Monad P256VERIFY
  • ERC-8004
  • OpenZeppelin WebAuthn
  • Envio HyperIndex
  • Mera passkeys
  • Chainlink CRE
assay-receipts
$ npm install assay-receipts
+ assay-receipts@0.1.1
$ npx tsx verify.ts 0x1b443b45...12e35c5f2
jws pass, hash pass, kid pass, merkle pass, anchored pass, outputCommit skipped, promptCommit skipped, cosigned skipped.
Skipped means the check needs your salt, or the receipt names no co-signer.

Got an AI answer? Check where it came from.

Paste a receipt, and the salt and output if you kept them. Every check runs in your browser or as a free onchain read. No wallet needed.