Your AI agent just executed a $50,000 trade on behalf of a user. An hour later, the user disputes it. "Show me the inference," they say. Show me the prompt, the model output, and the evidence that nobody changed it afterward. If you can't — or worse, if your audit log lives in a Postgres database someone with shell access can UPDATE — you've got nothing. This is the gap AI output notarization is built to close. And this is where EVIDIQ Notary does its work.
What 0G Storage Anchoring Means for AI Outputs
AI output notarization is hashing an AI inference receipt and anchoring it on decentralized storage so the receipt cannot be edited after the fact. EVIDIQ Notary writes each receipt to 0G Storage Aristotle (chain 16661), returning a keccak256 storage root and on-chain transaction hash anyone can re-fetch and re-hash. The result: a tamper-evident audit trail for agent decisions.
Here's the thing: most "AI audit" products stop at signing a JSON blob and stashing it in S3. That's not an audit trail, that's a polite suggestion. A signed receipt nobody can independently re-verify from a public, censorship-resistant ledger is just a vendor's word. We built EVIDIQ Notary because we wanted better — storage is a first-class primitive, not a footnote. This is the exact reason AI output notarization earns its keep in 2026, when every agent ship needs an evidence trail that survives the vendor.
The choice of 0G Storage Aristotle (chain ID 16661, mainnet) was deliberate. It's a decentralized data availability layer with content addressing, merkle commitments, and a public indexer. Anchoring on chain 16661 means the merkle root of your inference receipt sits next to every other major artifact in the EVIDIQ pipeline — the EIP-191 signature, the AI risk verdict from 0G Compute, and the trust score from our scoring formula. Same chain. Same anchor. Same evidence a developer (or a lawyer, or a regulator) can reconstruct from raw bytes.
The math is simple: take the canonical receipt, hash it with keccak256, upload it via ZgFile, capture the merkle root plus tx hash, and return both in the response. Anyone holding those two values can re-fetch the blob, re-hash it, and confirm bit-for-bit identity with what was originally notarized. The EVIDIQ Notary docs walks through the canonical schema, but the short version is: if you can re-fetch and re-hash, you've verified the audit trail — no trust required.
The Upload Flow: ZgFile to 0G Mainnet
The actual upload pipeline is four steps inside a 30-second timeout budget. We've optimized it to fit agent flows without becoming a bottleneck:
-
Canonicalize the receipt. We sort the keys, lowercase hex fields, drop nulls, and stringify in a deterministic shape. Two servers serializing the same receipt must produce byte-identical strings — otherwise the hash diverges and verification silently breaks downstream.
-
Wrap as ZgFile.
ZgFile.fromFilePath(tempPath)from the@0gfoundation/0g-ts-sdkpackage takes the canonical JSON and chunks it for the indexer. The SDK handles erasure coding and merkle tree construction under the hood, so our layer just calls one method. -
Submit via indexer.upload. We POST to the 0G indexer, with a turbo indexer fallback triggered when p95 latency on the primary crosses 8 seconds — we've observed mainnet spikes during periods of high demand in early 2026. The SDK returns
{ root: storageRoot, txHash: storageTx }once the upload lands on chain 16661. -
Sign and return. The receipt is signed EIP-191 with the EVIDIQ operator key. The response includes the canonical hash, the storageRoot, the storageTx, the signature, and the EVIDIQ signer address.
[IMAGE_PROMPT: A clean flat illustration of a JSON receipt being chunked and encoded into a stylized merkle tree of teal hexagonal blocks, then uploaded to a glowing 0G Storage mainnet node shown as a larger amber crystal, with a tx hash badge floating to the right — developer terminal aesthetic, dark navy background, monospace accents, no real brand logos]
The 30-second timeout is a hard wall. If the primary indexer stalls, we fail over to the turbo indexer; if both stall, the call returns a 503 with a retry_after hint rather than blocking the caller. We'd rather give you a clean refusal than a half-anchored receipt — a partial anchor is worse than no anchor because it creates a false sense of evidence.
Worth noting: we're not pinning the receipt to IPFS, Arweave, or any other DA layer right now. The roadmap includes redundancy across layers, but in 2026 the single 0G anchor is the source of truth. If you need belt-and-suspenders for a high-stakes deployment, mirror the canonical JSON yourself before calling notarize_inference — the storage root we return will still match.
Why Decentralized Storage Beats a Database for Audit Trails
A traditional audit log has three failure modes a centralized database can't escape:
- The editor problem. Someone with
UPDATEprivileges on the audit table changes a row. The log now says something false, and there's no external witness to contradict it. The receipt is lost to the audit trail forever. - The deletion problem. A
DELETEstatement or a 90-day retention policy wipes a row. The receipt is gone before anyone notices. The merchant says "prove it," you reach for the log, and it's empty. - The custody problem. The company hosting the log goes bankrupt, gets acquired, or simply changes its terms. Your audit trail evaporates with the vendor — and so does your defense.
A 0G Storage anchor sidesteps all three. The merkle root lives on chain 16661 — a public mainnet anyone can read. The blob lives in a decentralized network of storage nodes with economic incentives to retain it. The hash in your response is what you'd recompute today, tomorrow, or ten years from now if the data is still there. There's no admin path that edits a keccak256 root once it's committed on chain.
Here's the practical difference. Imagine a regulator in 2027 asking your agent operator for proof that a specific inference happened on a specific date with a specific prompt and model. With a Postgres log, you produce a screenshot — and the regulator has no way to know if the screenshot is genuine. With a 0G-anchored receipt, you hand over the storageRoot and storageTx. The regulator (or their auditor) fetches the blob directly from 0G, re-hashes it, and compares. Disagreement is impossible if the anchor is real.
This is also why we tie the trust score evidence to the same anchor. The EVIDIQ scoring formula — identity*0.3 + capability*0.3 + reputation*0.2 + (100-risk)*0.2 — produces a deterministic number, but the evidence behind it (endpoint probe results, capability declarations, risk verdict from 0G Compute) is what makes the score auditable. That evidence rides the same Notary pipeline. See the EVIDIQ Operator docs for how operators expose audit hooks, and the EVIDIQ Sentinel docs for the runtime monitor that calls Notary on every state-changing agent action.
Six Tools, Four Free — the Notary MCP Surface
We expose Notary as an MCP server with six tools, and the pricing reflects what actually costs us money to run:
notarize_inference— single-receipt notarization. Paid (x402, ~$0.02 per call in USDT0 on X Layer).notarize_batch— up to 100 receipts in one upload, amortized cost. Paid (x402, per-batch flat).verify_attestation— given a storageRoot + storageTx + payload, recompute the keccak256 and compare. Free.get_receipt— fetch the original canonical JSON by storageRoot. Free.notary_stats— public counters (total anchored, uptime, last 100 receipts). Free.notary_pubkey— returns the EVIDIQ signer address so you can verify signatures locally withecrecover. Free.
The split is deliberate. Verifying is cheap and should be free — it's a public good. Anchoring writes data to 0G mainnet, which costs gas and storage fees, and that's what the two paid tools cover. Payment follows the x402 protocol: the server returns HTTP 402 with an accepts[] payload, your client signs an EIP-3009 transferWithAuthorization, and the request goes through. Full EVIDIQ docs on the payment handshake if you want the bytes. The headline is: you only spend when you actually notarize something — verification is unmetered, always.
Honestly? We could charge for verify too, but that would defeat the purpose. Verification is what makes the anchor credible. Charging for it would turn the audit trail into a paywall, and a paywalled audit trail isn't a trust signal — it's a marketing claim. So we left four of six tools unmetered and let the two that hit mainnet pay their own way.
[IMAGE_PROMPT: A flat technical illustration of a developer terminal window showing six MCP tool icons arranged in a 2x3 grid — two icons highlighted in amber (paid: notarize_inference, notarize_batch) and four in teal (free: verify_attestation, get_receipt, notary_stats, notary_pubkey) — with a stylized x402 HTTP 402 challenge floating beside the paid pair, dark slate background, monospace type accents, abstract blockchain blocks]