The big picture
Three layers
1 · Policy & gate
A typed access policy — which agent can read which namespace — enforced at retrieval, before the model is called.
2 · Storage
Every memory is a real content-addressed blob on Walrus, optionally encrypted through Seal + MemWal.
3 · Proof
The policy and a tamper-evident receipt chain live on Sui — the verdict is computed on-chain, not asserted by the app.
Typed contracts
The system is designed around a few typed contracts in@carry/core — get the boundaries right and the rest composes.
The recall loop, step by step
This is whatPOST /api/chat does — and every step assumes the model might be wrong about what it’s allowed to see.
1
Trigger
An agent receives a query.
2
Gate
recall(agentId, query, memories, policy) returns only the memories in namespaces this agent is allowed to read, plus the namespaces that matched the query but were blocked by policy. Blocked content is never loaded into the prompt. The on-chain AccessPolicy is the authoritative allow/deny — recomputed on anchor and re-checkable by anyone via devInspect.3
Verify
Each allowed memory’s Walrus blob is re-checked against the aggregator (
GET /v1/blobs/{id}). “Verified” means the blob genuinely resolves on-chain — it is not a flag set by the app.4
Generate
The gated memories (and only those) are passed to the agent’s model. With no allowed memory, the agent truthfully says it can’t access what it needs.
5
Receipt
buildReceipt(...) assembles the Answer Receipt: used memories with authorization + verification status, the blocked namespaces, and the source agent.6
Anchor (optional)
The receipt is stored to Walrus and anchored on Sui as a
Receipt object — chained by blake2b256 — for tamper-evident provenance.The contrast that sells it
Revokeagent-b × health, ask the allergy question again, and the gate returns zero memories plus blocked: ["health"]. The model never sees the health memory, the answer is an honest refusal, and the receipt proves the block.
Because the gate runs server-side before
getLLM().complete(...), there is no code path where a disallowed memory reaches the model — even by accident.