What 0G Storage Anchoring Means for AI Outputs
AI output notarization produces a tamper-evident receipt for an AI inference and anchors it on decentralized storage so anyone can verify what the model produced, when, and on whose behalf. EVIDIQ Notary writes each receipt to 0G Storage Aristotle (chain 16661), where the merkle root and on-chain transaction make the proof independently verifiable.
A receipt from an AI agent is only useful if nobody can rewrite it after the fact. That's the entire game. In 2026 we're past the point where "the agent said so" is enough — counterparties want a hash, a transaction, and a way to check both. AI output notarization is the practice of turning a model's response into a sealed artifact that survives the agent, the operator, and the platform that produced it.
EVIDIQ Notary is our implementation of that practice. Each call to the Notary produces a JSON receipt containing the model identifier, the prompt hash, the inference hash, the operator's EVM address, a UTC timestamp, and a recommendation. Before that JSON ever leaves our service, it is anchored on 0G Storage Aristotle — mainnet chain id 16661 — which returns two values we keep on the receipt itself: a merkle storageRoot and an storageTx you can paste into any 0G block explorer.
If you've already read the EVIDIQ docs you'll notice we treat notarization as a first-class primitive, not a nice-to-have. The same receipt that gets stored also feeds the deterministic trust score produced by EVIDIQ Sentinel — they're the same artifact, looked at from two angles. EVIDIQ doesn't custody your inference — it just proves one happened.
The Upload Flow: ZgFile to 0G Mainnet

Here's the concrete walk. When a caller invokes notarize_inference, we build the receipt object, serialize it once to canonical JSON, hash it with keccak256, and pin both the hash and the canonical bytes on the receipt envelope. Then we hand the file to the 0G TS SDK.
- We instantiate
ZgFile.fromFilePath(tempPath)against the canonical JSON blob. - We call
indexer.upload(zgFile, { txOpts: { gasLimit: ... } })against the mainnet indexer endpoint. - If the standard indexer times out or stalls, we fall back to the turbo indexer URL — same SDK call, different host, same merkle semantics.
- The indexer responds with
{ root: storageRoot, tx: storageTx }. - We write those two fields back into the receipt and return the signed envelope.
The whole upload is bounded by a 30-second timeout. Honest opinion: that's enough budget for everything we care about, but it's tight. Anything longer than that and the caller's HTTP client has usually already given up. We chose 30 seconds because it's the floor where we can absorb a merkle batch flush without holding the agent hostage.
For the underlying storage write, we use @0gfoundation/0g-ts-sdk pinned to the version that targets Aristotle mainnet. The SDK handles the erasure-encoding step and the proof generation against the storage node's BLS signer; we only orchestrate. If you want to reproduce the upload outside our wrapper, the EVIDIQ Notary docs walk through the exact environment variables.
Why Decentralized Storage Beats a Database for Audit Trails
Here's the thing about centralized audit logs: they belong to whoever runs them. If a regulator shows up, the operator can edit the row. If a customer disputes an inference, the operator can delete the row. If the operator's database gets compromised, every prior log entry becomes suspect at once. A centralized store is a private ledger dressed up as a public one.
A 0G Storage anchor changes the geometry:
- Storage root. Each uploaded file is encoded, sharded across storage nodes, and committed under a merkle root that's recorded on-chain.
- On-chain tx. The act of writing that root is itself a transaction with a hash, a block height, a fee, and a signer you can look up.
- Independent verification. Anyone holding the receipt can fetch the file from any 0G node, re-hash it, and confirm it matches the root recorded in the original transaction. No cooperation from the original notifier required.
- No backdoor edit. Rewriting the artifact would require rewriting enough shards to recompute the merkle root, then bribing or compromising the chain's consensus to accept a new transaction that points to the rewritten blob. That isn't free.
What this means for AI output notarization specifically: a notarized inference is checkable years later by a stranger with no relationship to the original operator. That's the property that matters. It's not enough to say "we logged it" — the log has to be log-able by the auditor, not by you. We built Notary so that the verification flow doesn't even ping our infrastructure if you have the receipt hash in hand.
This is also why EVIDIQ Notary never stores the underlying prompt or response payload — only the hashes and the envelope. The receipt is proof of an inference, not the inference itself. That's a privacy posture worth holding the line on.
Six Tools, Four Free — the Notary MCP Surface

The Notary MCP server exposes six tools. Four are free and rate-limited, two are gated by an x402 payment challenge. Here's the surface that makes AI output notarization mintable from any agent runtime:
notarize_inference(paid) — takes an inference payload, builds a receipt, anchors it on 0G Storage, and returns the signed envelope.notarize_batch(paid) — same as above but bundles up to 50 receipts into one merkle root. Useful when an operator wants a single transaction for an hour of agent activity.verify_attestation(free) — given a receipt hash, fetch it from 0G, re-hash it, and return a pass/fail with the storage tx.get_receipt(free) — returns the raw JSON of a previously anchored receipt by its id.notary_stats(free) — returns aggregate counters: total anchored, average upload latency, p95, last error.notary_pubkey(free) — returns the EVIDIQ signing public key so callers can independently verify that a receipt really came from us.
On the payment side, we follow the standard x402 flow. A paid call returns HTTP 402 with an accepts[] entry per the x402 v2 spec, scheme exact, network X Layer, asset USDT0, settled via EIP-3009 transferWithAuthorization. Once the signed authorization lands in the X-PAYMENT header, we settle on X Layer, anchor the receipt on 0G Storage, and return the envelope. No account, no API key, no signup. The full protocol write-up lives in the EVIDIQ Operator docs for anyone wiring this into an agent runtime.
Worth noting: we don't gate the verification path. If you have a receipt, you can verify it for free, forever. The cost is on the side that needs the proof minted — which feels honest.
