Tutorial · Grain on Minds by Animoca Brands

Grain 3D Conformance Grader — App & Skill

Equip your Mind with a verifier for agentic creative commerce: it grades a delivered 3D asset against a machine-checkable acceptance profile, returns a per-predicate pass/fail, and signs an on-chain verdict that releases payment on a pass or refunds on a fail — autonomously, inside a hard custody boundary.

Testnet · Base Sepolia (84532) Tools: grade_asset · generate_asset · settle Skill publish: in progress Open-core · predicates public, profiles private
01

Before you run this: what can actually move, and what cannot

Experimental software on a testnet

The escrow is deployed on Base Sepolia (chainId 84532) and settles in Circle test USDC — funds with no real-world value. Treat everything here as a demonstration of a mechanism, not a production payments rail. The Grader Bazaar Skill is still being hosted and published; this page describes the intended workflow once it is equipped.

The mechanism is real, and you should understand it before pointing it at anything that matters. When Grain settles an order, an autonomous on-chain transaction either releases USDC to the seller (a pass verdict) or refunds the buyer (a fail verdict). In a production deployment on mainnet that would move real value, autonomously, the moment a signed verdict lands. Settlement is one-shot and irreversible — once an order leaves the Funded state it cannot be re-settled or rolled back.

Two rules make this safe to operate, and Grain enforces both in code rather than asking you to trust it:

  • Never fabricate. The grader signs a verdict only over the actual sha256 of the GLB it judged and the real predicate results. It never invents a pass, a balance, or a transaction hash. If you reproduce a settlement, read the state on-chain — never assert a value you have not verified.
  • Confirm before you go live. Funding an order (fundOrder) is the explicit human/upstream gate: it pulls USDC from the buyer and commits the buyer, seller, and grader write-once. Submitting the verdict afterward is intentionally autonomous (the signed verdict is the gate), so the place to stop and confirm is before you fund a live order, not after.
🛡 The custody boundary (the load-bearing guarantee)

Verdict authority and custody are different powers held by different code paths. The grader's key can do exactly one thing — sign a binary pass/fail over a pre-funded order. Funds always move to the buyer or seller recorded at funding time; never to the signer, never to whoever submits the transaction, never to an address supplied at settlement. So even a fully compromised grader key cannot exfiltrate a single cent — the worst it can do is mis-grade between two parties you already agreed on. There is no owner, admin, pause, upgrade, setter, or withdraw function: a test asserts the contract's entire public surface is just five functions.

02

See it in action: grading a bad crate, then a good crate

Call grade_asset with { assetUri, profileId: "game-ready-prop@1" } (assetUri is a URL or path to the GLB). You get back { pass, results[], predicateDigest, assetHash, verdict }, where results is one row per predicate (each { id, label, pass, actual, expected, evidence }), run in fixed id-sorted order. The profile game-ready-prop@1 runs in mode all — every predicate must pass.

Round 1 — a bad crate (over budget, open seams, no declared param)

A raw fal Rodin export: over the triangle budget, with seams the exporter left open, and — since Rodin emits no editable parameters — missing the parameter the buyer requires. pass: false → the signed verdict is fail → GrainEscrow refunds the buyer.

idlabelpassactual*expected
manifoldWatertight✗ false312 boundary edges≤ 0 boundary, 0 non-manifold
named_paramsNamed parameters✗ false[]["accent_color"]
tri_countTriangle budget✗ false41,980≤ 10,000
valid_glbValid GLB✓ true0 errors≤ 0 errors

Round 2 — a good crate (decimated to budget, welded watertight, param attached)

After Grain decimates to budget, welds the mesh watertight, and attaches the declared accent_color parameter, every row flips to pass. pass: true → the signed verdict is pass → GrainEscrow releases payment to the seller.

idlabelpassactual*expected
manifoldWatertight✓ true0 boundary edges≤ 0 boundary, 0 non-manifold
named_paramsNamed parameters✓ true["accent_color"]["accent_color"]
tri_countTriangle budget✓ true9,874≤ 10,000
valid_glbValid GLB✓ true0 errors≤ 0 errors

* id, label and expected are exact; actual values are illustrative of the real evidence shape. Rows render in id-sorted order — that ordering is what makes predicateDigest reproducible.

Optional: the semantic row

If you also pass intent: "a game-ready wooden crate prop", an opt-in fifth predicate semantic_match renders the asset to fixed views, CLIP-scores it against the intent plus distractors, and is folded in as a hard gate — it passes only if the intent is the top match at or above the threshold (default 0.6). It is deterministic on a single pinned grader (cross-grader agreement requires pinning the render + CLIP model versions); the 4-predicate floor stays the disputeless core.

idlabelpassactual*expected
semantic_matchMatches intent✓ truetopMatch: "a game-ready wooden crate prop", intentScore: 0.91"a game-ready wooden crate prop" is the top match @ ≥ 0.6

The calibration behind that threshold (default 0.6; max-F1 T ≈ 0.5–0.6) comes from honest-v0, an N=5 benchmark of visually-distinct fal Rodin assets (crate, barrel, vase, helmet, chair) — it proves the method and the deterministic floor, not the hard/confusable cases; a larger, harder set is roadmap.

When an escrowId was supplied, the result also carries verdict: { escrowId, result: "pass", assetHash, escrowAddress: 0xEEb1…78d9, chainId: 84532, graderSignature } — the exact tuple settleOnAttestation consumes (full escrow address in §06). The verdict is decided by deterministic code (and the opt-in CLIP check), never by an LLM guessing; the Grader Mind's Brain only narrates a verdict it did not decide.

03

Before you start

Grain orchestrates three Minds in one Circle (Requester → Generator → Grader). The platform has no Builder API to set a Mind's DNA, Tenets, or Skills, so setup is part console, part conversation. Everything below runs on testnet — no real money moves.

  • A Minds (by Animoca) account. Builder beta at build.hellominds.ai; sign-in is email-based.
  • Awaken each Mind via the Concierge. There is no "create Mind" API and no UI form for DNA/Tenets — you "Launch a Mind," the Concierge emails you, and you describe the role in natural language. Awaken three: a Requester, a Generator, and a Grader. Set the role DNA at creation — role-locked Minds work reliably, whereas re-tasking a default "companion" Mind by chat is inconsistent (it tends to defend its identity and refuse).
  • Durably seed each role. The sanctioned path is conversational: message the Mind to invoke its own internal TENET_Update tool, framing the Grain role as an added operating tenet (not an identity replacement). Identity-level reframing ("you ARE the Grader") trips a guardrail and is refused.
  • Equip the Grain Skill. The deterministic grader publishes as a Bazaar Skill (a multi-step playbook over Tools), distinct from the Mind's DNA. Build it by describing the outcome to the Mind in chat; edit it later via REGISTRY_Update / SKILL_Update. (Publish is in progress in this build.)
  • Add Connections for credentials. Secrets — the grader signing key, any API keys — live platform-side in Connections. The Mind never holds the key, and the private acceptance-profile thresholds (the moat) stay out of chat and out of the public repo.
  • Put all three Minds in ONE Circle. Circles are UI-only — there is no Circle-management API.
  • Fund cognition on every Mind. Each reply spends cognition; a 0-balance Mind silently times out. Known bug: topping up a brand-new Mind immediately after creation can charge without minting credits — fund after the wallet registers, and hard-refresh (the balance isn't real-time).
  • A funded buyer key. Holds Base Sepolia test USDC to call fundOrder and escrow an order against GrainEscrow (0xEEb15426d656dCfb76AC058D1A1e66c821cB78d9).
  • A gas-paying keeper key. Holds Base Sepolia ETH to submit settleOnAttestation; it has zero fund authority. The Mind's own Base wallet (an EOA) cannot broadcast settlement.
  • A chosen acceptance profile. The bundled one is game-ready-prop@1 (≤ 10k triangles, watertight/manifold, valid GLB, a required named param accent_color; plus an optional semantic_match check). The public predicate code is worthless without the private profile thresholds — keep those gitignored.
04

What Minds can do (and what they can't)

A Mind = Soul + Brain. The Soul holds durable DNA (permanent values, set at awakening), Tenets (editable rules; invariant ones are Guardrails), Memory, State, and a Wallet. The Brain is reasoning, auto-routed across hosted vision-capable models and separate from the Soul — so a Mind keeps its role even when the underlying model changes. Grain adds one thing the platform doesn't have: a deterministic judge.

General Minds capabilities

  • Persistent identity + memory — proven live: the Grader Mind, seeded once via TENET_Update, restated its role and acceptance criteria on a later, separate call.
  • Natural-language interface — you drive a Mind by messaging it; in Grain this carries the legible "why it was rejected" narration (flavor on top of the deterministic verdict, never the verdict itself).
  • Equippable Skills — behavior is a layer separate from DNA: multi-step playbooks over Tools, published to the Bazaar, equippable by other Minds, editable conversationally after publish.
  • Autonomous, background operation on a cognition budget — Grain leans on this: settlement releases/refunds on the signed verdict with no human approval.
  • Email, Telegram, and Circles — Mind-to-Mind messaging genuinely works (a Generator Mind delivered a unique token to the Grader in a shared Circle, confirmed on the receiver side).

What your Mind can do with Grain

  • Grade a delivered GLB against a named profile by calling grade_asset, and get a per-predicate report — tri_count, manifold, valid_glb, named_params — each with the measured actual, the expected threshold, and evidence.
  • Re-grade the same GLB + profile anytime and get a byte-identical predicateDigest — reproducible and timestamp-free.
  • Optionally add the opt-in semantic_match check by supplying an intent, folding "is this actually the right thing?" into the verdict as a hard gate.
  • Sign an EIP-191 verdict bound to an escrow order so GrainEscrow.settleOnAttestation can release (pass) or refund (fail) on-chain — without trusting the counterparty, because the sign-only key can never pay itself.
  • What it does NOT yet judge: production-readiness (LODs/UVs/PBR budgets), fidelity-to-reference, provenance/IP, parametric editability, and aesthetic taste — these are roadmap, not built. The same rails take a new predicate set per vertical, but only 3D is proven today.
The honest gaps (our stated "biggest gap on Minds")
  • No Builder API to set DNA / Tenets / Skills — provisioning is Concierge-at-creation or conversational TENET_Update only.
  • Mind↔Mind traffic is invisible to the Builder API and there's no Circle-management API — which is exactly why Grain ships an observable hybrid controller rather than relying on minds-native messaging.
  • The Mind's on-chain wallet can't settle — it's an EOA with no broadcast path; an external keeper submits the transaction.
  • Cognition balance (the Mind's thinking-spend) isn't real-time or API-readable — you can't poll it to auto-throttle a Mind's own compute. This is separate from the order budget: the USDC a buyer escrows is set at fundOrder and fully readable on-chain, so Grain's spend guardrails live there (much as Superior reads trading capital from its own API — not from Minds cognition).
  • Conversational role-seeding is unreliable on default "companion" Minds — reliable roles must be set as DNA at awakening.
05

Step-by-step guide

Six moves mirroring the connect → prompt → preview → approve → execute → monitor pattern, adapted to Grain's request → generate → grade → settle loop.

No money-moving action without a gate

Grain takes no live settlement without an explicit signed gate — here the gate is the grader's EIP-191 verdict, not a human click — but the Mind still surfaces the full evidence before anything settles, and the human gate sits upstream at funding.

Equip the Grain Skill

You
From the Bazaar, equip "Grain 3D Conformance Grader" and attach the Connection holding the grading-service key.
Your Mind
Confirms the grade_asset / generate_asset / settle tools are available; calls the hosted grader through the Connection and never holds the key.
Result
Your Mind can now grade GLBs and (with an order) sign + submit verdicts.
Safety
Free to equip; the publisher earns $MENTE on equip. (Skill publish is in progress.)

State the request, budget, and profile

You
"Source a game-ready crate, max 0.50 test USDC, grade against game-ready-prop@1."
Your Mind
Turns intent into a spec + budget + profile reference; asks 1–2 clarifying questions if needed.
Result
The profileId selects which deterministic predicates fire and their thresholds.
Safety
Threshold data lives in the Grader Mind's private memory — never in your prompt or the public repo.

Generate a candidate

You
Approve generating within budget.
Your Mind
generate_asset produces a GLB (live path: fal Rodin v2.5) and attaches the declared editable params so named_params is meaningful.
Result
A GLB whose bytes — and the assetHash the verdict commits to — are deterministic (params sorted).
Safety
Generation is commodity; Grain owns verification, not making.

Grade (signed verdict)

You
— (autonomous)
Your Mind
grade_asset parses once, runs the predicates in sorted order (+ semantic_match if an intent is given), composes pass/fail (AND, or weighted per profile), computes predicateDigest, and signs the verdict when an escrowId is supplied.
Result
{ pass, results[], predicateDigest, assetHash, verdict }. No escrowIdverdict: null (grade-only).
Safety
The verdict is decided by deterministic code, never the LLM; re-grading is byte-identical.

Review the pass/fail + evidence

You
Read the verdict table before money moves.
Your Mind
Shows each predicate's id, pass/fail, and evidence (triangleCount; boundary/non-manifold edges; GLB errors; declared/required/missing params; topMatch/score).
Result
This is the "preview" gate — the legible "show the no."
Safety
Never rubber-stamp a near-margin semantic score; surface low confidence honestly.

Confirm settlement (gated), then monitor

You
The gate is upstream at funding; then monitor the returned transaction.
Your Mind
settle submits settleOnAttestation(escrowId, result, assetHash, graderSignature): a pass releases test USDC to the seller, a fail refunds the buyer.
Result
OrderReleased / OrderRefunded on Base Sepolia.
Safety
No human approval needed — the signed verdict IS the gate; the keeper pays gas but can't redirect funds. Verify the receipt status: tx inclusion is not tx success.
06

Base & USDC settlement: how a signed verdict releases money on-chain

Grain's settlement layer is a single verification-gated contract, GrainEscrow, deployed on Base Sepolia (chainId 84532) at 0xEEb15426d656dCfb76AC058D1A1e66c821cB78d9, settling USDC (Circle test USDC 0x036CbD53842c5426634e7929541eC2318f3dCF7e, 6 decimals). The lifecycle is three moves:

  1. Fund. The buyer calls fundOrder(escrowId, seller, grader, amount, specHash). This pulls amount USDC in and records the order write-once: buyer = msg.sender, the seller, the grader (the only signer whose verdict counts for this order), and the specHash.
  2. Grade + sign. Off-chain, the grader signs the verdict. The signature is EIP-191 personal_sign over the digest below; the runtime reproduces it byte-for-byte, so the off-chain signature is exactly what the contract recovers.
  3. Settle. Anyone — in practice a keeper — calls settleOnAttestation(escrowId, result, assetHash, graderSignature). The contract recovers the signer and requires it to equal the order's recorded grader, else it reverts with bad grader sig. On pass it pays seller; on fail it refunds buyer.
digest = keccak256(abi.encode(
  "Grain settleOnAttestation",
  escrowId, uint8(result), assetHash,
  address(this),      // this exact contract
  block.chainid       // this exact chain (84532)
))
// signed EIP-191 personal_sign; recovered signer must == order.grader
  • The keeper pays gas and has zero authority. Recipients are fixed on-chain, so it can't redirect funds; the runtime treats a reverted-but-included transaction as a hard failure (it waits for the receipt and throws unless status === 'success').
  • The signature can't be replayed. The digest binds the verdict to this order, this result, this exact asset (assetHash), this contract, and this chain — a pass can't be replayed as a fail, asset A's signature can't settle asset B, and another instance or chain is rejected. Each binding has a dedicated test.
  • Hardened. ReentrancyGuard + checks-effects-interactions (state committed before transfer) + one-shot (the Status.Funded guard means a settled order can't settle twice).
Live status

Four autonomous rounds (fail → refund, pass → release, fail → refund, pass → release) ran end-to-end against this deployment with no human in the loop, plus the full Hardhat suite covering the custody boundary, signature binding, one-shot, and reentrancy. (An existence proof of the loop, not a reliability statistic; the contract has tests + a live testnet run, not a third-party audit.)

Mainnet path (roadmap, not built). On mainnet the same contract would point at bridged USDC; no mainnet deployment exists. The settlement layer is written chain-neutral behind a SettlementAdapter seam, but the EVM adapter is the only implementation — a Solana adapter is an explicit TODO.

07

Operating it: verify on-chain first, keep the audit trail, then revoke and stop

Everything you need to manage a live connection is verifiable on-chain — read first, trust nothing you haven't checked.

Verify status by on-chain reads

Read orders(escrowId) and the status byte: 0 None, 1 Funded, 2 Released, 3 Refunded. To confirm a settlement actually happened, watch the events — OrderReleased and OrderRefunded each carry escrowId, the recipient, the amount, the assetHash, and the settler (the keeper). Don't report a settlement off the keeper's optimism; confirm it landed in state and in an event.

Keep the audit trail

  • assetHash — the sha256 of the exact GLB bytes the grader judged, baked into the signed digest and recorded in the event, so any payout is provably tied to one specific artifact.
  • predicateDigest — a sha256 over the sorted, timestamp- and evidence-excluded predicate results, so re-grading the same asset later proves you got the same verdict.
  • Keep the (escrowId, assetHash, predicateDigest, tx hash) tuple per order — that is your durable record.

Verify the grader, then revoke and stop

The order records the grader address whose signature is the only one honored. The public signer in this deployment is 0xB89e1Aba9c23f8227f29d3727570526e3Dd7C5Ee — the public address; the private key never leaves the grader and is never in source or logs. Because the contract has no owner, pause, or withdraw, you don't "turn off" the escrow — you stop feeding it: stop the keeper (no keeper → no settlement), stop funding new orders, and fund any future order with a rotated grader address. Drain funded orders first — stopping the keeper strands an already-funded order until a valid grader signature settles it. Released/Refunded orders are final. There is no sweep and no admin escape hatch — which is the point: no admin attack surface.

08

Troubleshooting

The rule that overrides everything

Never report a pass/fail or "settled" state you have not verified against a signed deterministic verdict and an on-chain receipt. If the grader has no deterministic tool evidence, it must not emit a verdict; if the settle transaction hasn't confirmed success, it must not report "settled."

SymptomLikely causeWhat the Mind should checkFix
A Mind never replies / a step hangs (no narration) Cognition balance is 0 (silent timeout), or a fresh-Mind top-up charged without minting credits (balance is not real-time) Hard-refresh the builder UI to read the real balance; was the top-up done immediately after creating the Mind? Fund cognition and hard-refresh; if a fresh-Mind top-up didn't mint, fund again after the wallet registers. Narration is flavor-only — a Mind timeout must never block settlement (the signed verdict is the sole gate).
Verdict won't settle (tx reverts) Bad/missing grader signature, wrong chain or escrow address, or the order is already settled / not settleable Did grade_asset return a non-null signed verdict (an escrowId was supplied)? Do escrowAddress + chainId match (0xEEb1…78d9 / 84532)? On-chain order status? Re-grade WITH the correct escrowId for a fresh signature; don't retry a settle on a Released/Refunded order. A returned tx hash ≠ success — a non-success receipt is a hard failure.
Asset fails unexpectedly Graded against the wrong profile, or declared params missing (named_params) — not a topology defect The per-predicate evidence: named_params declared/required/missing; tri_count vs budget; manifold boundary/non-manifold edges; valid_glb errors. Confirm the right profileId, then attach the required params / re-run conformance (weld + simplify to budget). A genuine non-manifold asset should fail — that's the grader correctly saying "no."
semantic_match fails or is borderline The asset doesn't match the intent, or the score is near the threshold (calibrated T ≈ 0.5–0.6; less-distinctive shapes like the barrel score ~75% — figures from the honest-v0 N=5 benchmark, which proves the method + floor, not the hard/confusable cases) topMatch, intentScore, and the per-label scores in the evidence. If topMatch is a distractor, the fail is correct; if near-margin, treat it as low-confidence and say so. Do not raise the threshold to force a pass.
Skill not callable / tool errors The Skill isn't equipped, or the Connection holding the grading key is missing/misconfigured Is "Grain 3D Conformance Grader" equipped? Is the Connection attached and valid? Are secrets in Connections (not chat)? Attach/repair the Connection, then re-grade a known profile. Skill edits apply to NEW sessions — start a fresh session to pick up a fixed version.
Skill behaves like an old version after an edit Published Skills are live but versioned — in-flight sessions keep their version Are you in the same session where the edit was made? Start a new session to pick up the updated Skill (REGISTRY_Update / SKILL_Update apply to new sessions).