AI Receipts: ENS-addressable, 0G-anchored, transferable proofs of multi-model AI consensus
Synod ships AI Receipts A new primitive for trust minimized AI consultation.
Ask a question: four AI models from two vendors deliberate independently, sign their votes with ed25519 keys, reach quorum over Gensyn AXL's encrypted P2P mesh, and produce a cryptographic receipt that is verifiable, transferable, and lives on three networks at once.
Live numbers at submission
0xc96835176b03b91e13907bab612ebdf79a0d5fe60647c76f2d6b06fa46ab8b82.The problem A single AI's answer is a single point of failure: prompt injection, model bias, vendor outage, or silent regression can corrupt the result, and you have no audit trail. Existing "AI oracle" patterns trust one model and one operator. There is no way today to ask a question, receive multi model consensus, and prove what was decided to a third party without trusting the asker.
What Synod does Four settlers run as independent services across two physical VPS in Frankfurt and Toronto, with four model variants: Anthropic Sonnet 4.6, Anthropic Haiku 4.5, Anthropic Opus 4.7, and Google Gemini 2.5 Flash. They communicate exclusively over Gensyn AXL (encrypted Yggdrasil + ed25519 identity, no central coordinator, no fallback transport). Each settler reasons independently and votes with a confidence weight.
The deterministic poster (lowest hex pubkey among voters) submits the canonical settlement to SynodRegistry on Gensyn L2 mainnet (chain 685689). The full deliberation transcript: every settler's reasoning, vote, signature, and the consensus arithmetic: is uploaded to 0G Storage Galileo and pinned by merkle root. Finally, the verdict is minted as a j-{shortHash}.synodai.eth ENS subname on Ethereum mainnet, owned by the question submitter and carrying eight text records (outcome, quorum, weighted score, transcript CID, settlement tx, prompt, parent, description).
Why ENS is load bearing
synodai.eth is the protocol's bootloader. Registry contract address, RPC URL, chain id, quorum threshold, and the canonical 4 settler list all live in on chain text records on Ethereum mainnet. Point a fresh UI at one ENS name and it self configures end to end: change synod.threshold from 2 to 3 on mainnet and the live /network page picks up the new quorum on the next cache refresh, with no redeploy. Each settler-{a,b,c,d}.synodai.eth subname carries its EVM address, ed25519 pubkey, and role; the UI cross checks all three against the live AXL daemon and the on chain registry. A green pulse dot requires all three sources to agree across two machines, two L2s, and one mainnet.
Why 0G is load bearing
0G Storage is the swarm's append only shared memory. Retrieval is pure HTTP: [https://indexer-storage-testnet-turbo.0g.ai/file?root=0x](https://indexer-storage-testnet-turbo.0g.ai/file?root=0x)...: no SDK, no auth, no key. Anyone, any browser, any future verifier can replay the swarm's reasoning chain. Each settler is also minted as an ERC 7857 iNFT on 0G Chain Galileo (AgentNFT proxy 0x4fF6712B364A06f4f23878dE3c4678E8F48f2D85), demonstrating the swarm's transferable on chain identity. Token #0 was transferred live to a fresh wallet to prove the surface works end to end.
The judgment subname is the novel primitive
ENS subnames have been used as usernames, agent profiles, and agent state stores. They have not, to our knowledge, been used as a portable proof of AI decision NFT: owned by the asker rather than the operator, cryptographically tied to an on chain settlement and an off chain decentralized transcript. Each j-{hash}.synodai.eth is an addressable, transferable receipt: anyone resolves the name and gets the verdict + transcript pointer; the owner can send it to another wallet or list it on OpenSea like any ERC 1155. The ENS team has explicitly endorsed subname per agent + text records + ERC 8004 reputation as the AI agent identity pattern; Synod implements that pattern faithfully and extends it with the judgment NFT layer.
Open source primitive
Synod is MIT licensed. We've drafted an ENSIP at docs/ENSIP DRAFT AI AGENT IDENTITY.md proposing the parent/subname/judgment subname schema as a standard for AI agent identity in ENS, so other projects can adopt the same pattern without re deriving it.
The Stack
Python 3.14 settler runtime (~600 LOC of business logic), Foundry tested Solidity for the Gensyn L2 registry contract, Next.js 16 + Tailwind + viem for the live UI, vendored Gensyn AXL daemon for transport, the 0g storage client Go CLI wrapped in Python for transcripts, and three ENS components on Ethereum mainnet (PublicResolver, NameWrapper, ENS v3 Registrar Controller) for the bootloader and judgment NFT layers.
Production deployment: Contabo VPS in Frankfurt (settlers A/B/C) + Servarica VPS in Toronto (settler D), each component on its own systemd unit with auto restart, nginx reverse proxy, certbot webroot for SSL.
Architecture & Logic
Settler runtime
Each settler is a Python service holding an ed25519 identity (PEM loaded at boot via cryptography), an LLM provider abstraction over Anthropic and Google Gemini SDKs, and an AXL HTTP wrapper. The agent loop is observe → reason → sign → broadcast → consensus: subscribe to AXL /recv, decode the message, run inference with the canonical SYSTEM_PROMPT, build a canonical JSON vote, sign it with ed25519, broadcast via AXL /send, accumulate peer votes, apply confidence weighted per outcome quorum (the winning outcome needs ≥N votes for THAT outcome: not a majority among all), and if you're the deterministic poster (lowest hex pubkey among voters) submit on chain. All four settlers share the same SYSTEM_PROMPT; heterogeneity is on the model/vendor/machine axis, not role.
Gensyn AXL Transport
No central coordinator, no HTTP fallback. Each settler runs a local axl node daemon with its own ed25519 mesh identity. Votes flow POST /send → encrypted Yggdrasil mesh → peer's daemon → GET /recv. Cross machine: Settler D peers with the Contabo nodes over the public Internet via tls://75.119.153.252:9101; UFW restricts inbound to Servarica's IP only. The mesh is bidirectional and verifiable: curl 127.0.0.1:9002/topology on Contabo shows D as inbound peer; the same query on Servarica shows A's public listener as outbound.
Gensyn L2 contract (SynodRegistry)
Solidity at 0xD387f749667590940d7c68CA350e57FbcE62b6ad on chain 685689. Admin curated allowlist, sealed settlement records, signed vote bundle per settlement. 37 Foundry tests including a 256 run fuzz on the settlement recording entrypoint. Fix for Web3.py footgun: recordSettlement fix involved simulate first (fn.call()) plus explicit estimate_gas before send to surface payload size reverts cleanly.
ENS: Bootloading & Judgment Minting
Protocol Bootloader
synodai.eth was registered via the ENS v3 Registrar Controller. Nine parent text records hold the runtime config: synod.registry, synod.chain id, synod.rpc, synod.threshold, url, description, com.github, synod.verify url, synod.network url. Four settler-{a,b,c,d}.synodai.eth subnames each carry addr, synod.role, synod.pubkey (ed25519 mesh key), and synod.parent. The Next.js UI reads everything via viem.getEnsText against Ethereum mainnet PublicResolver: no env vars, no config files, no hardcoded protocol parameters.
Judgment subname mint: the 3 tx flow
Minting j-{shortHash}.synodai.eth to the question submitter requires three transactions:
NameWrapper.setSubnodeRecord: Creates the subname owned by the deployer.PublicResolver.multicall: Writes all eight records (outcome, quorum, transcript CID, etc.) in a single tx.NameWrapper.safeTransferFrom: Hands ownership to the verified submitter.
Verification gate: The user signs a canonical declaration message. The server reconstructs the message, validates the 5 minute window, and checks the signature with viem.verifyMessage. The deployer never decides who owns a judgment: the signature does.Data Persistence & Identity
0G Storage: Append only swarm memory
After every successful settlement, the designated poster uploads the full transcript via the 0g storage client Go binary. We wrapped the Go CLI in synod_settler/storage_0g.py: a thin Python adapter that shells out, parses the JSON response, and returns the merkle root. Retrieval is pure HTTP via the 0G indexer: no SDK, no auth, no key required. The merkle root is written into the judgment subname's synod.transcript cid text record on Ethereum mainnet.
0G Chain ERC 7857 iNFT layer
Each settler is minted as an ERC 7857 iNFT on 0G Chain Galileo (AgentNFT proxy 0x4fF6712B364A06f4f23878dE3c4678E8F48f2D85). Token IDs 0–3, each owned by the settler's own EVM address; dataHash = keccak256(role ‖ ed25519 pubkey ‖ ENS fqn). The iNFT acts as an identity binding layer: token #0 was transferred live to a fresh wallet to prove the surface works end to end.
Verification & Trust
Three sources of truth
The /network UI cross checks:
axl node's /topology.settlers(addr) tuple on Gensyn L2.synod.pubkey ENS text record on Ethereum mainnet.
A green pulse dot requires all three to agree.Independent verification paths
getSettlement(questionId) on Gensyn L2 returns the canonical outcome and signed votes.GET /file?root=… on the 0G indexer returns the full transcript.verify_settlement.py (Python) and proof-verifier.ts (TypeScript): that recompute registry membership and quorum from raw chain bytes.Tests 83 total: 37 Python (protocol, identity, consensus, onchain, proof verifier), 37 Solidity Foundry (256 run fuzz), 9 TypeScript SDK smoke tests against the live deployment. CI runs the full suite on every commit.

