Your AI agent remembers everything. Can it prove any of it?
Building Engram: git for agent memory, on Walrus, Sui and Tatum
By Rohan · Tatum × Walrus Total Recall hackathon · Track 02: Smart Agents for Real Life
!Image description
> Every belief traceable. Every decision provable. Every memory forgettable.
Watch the demo video · Try the live agent, no wallet needed · Read the docs · Read the code
> - The short version. AI agents now remember things about us, and they act on what they remember. But nobody can see how an agent learned something, which memory drove a decision, whether the record was edited afterwards, or how to make it truly forget.
> - Engram fixes that. It gives an agent's memory a history (like git), a proof that anyone can check (signed snapshots stored on Walrus and anchored on Sui), and an off switch (forgetting you can prove). It's live, it's on npm, and the demo agent learned from real on-chain transactions.
*
Part 1 · The moment that started it
Picture this. You've given an AI agent access to your wallet. Its job is simple: watch your money and warn you when something looks wrong. For weeks it does fine. It learns your salary, your rent and your subscriptions, and it stops bothering you about them.
Then one morning it stays quiet about a payment to an address you've never seen.
You ask it a simple question: "Why didn't you warn me?"
And it can't really answer.
It has memories, a growing pile of text it has collected over the weeks. But it can't show you:
- which of those memories it relied on,
- what it believed at the exact moment it decided,
- when it started believing that, or what taught it,
- or any proof that the record you're looking at is the same one it used. The logs sit on the operator's server, and anyone with access could have changed them afterwards.
That's where agent memory is today. Tools like Walrus Memory have made it easy for agents to remember. Nobody had made it easy to hold that memory to account.
We kept coming back to one thought: software developers had this exact problem decades ago, with code. Code changed constantly, many people touched it, and when something broke, nobody knew which change caused it. The answer was version control. Every change became a commit, history could be compared, and git blame could tell you exactly where any line came from.
We wanted that for an agent's mind, plus one thing git never needed: proof that a stranger can check without trusting us.
So we built Engram. The name comes from neuroscience, where an engram is the physical trace a memory leaves in the brain.
*
Part 2 · Why we felt we had to build it
Agents crossed a line this year
For a long time, AI assistants mostly talked. If one misremembered something, you got a wrong answer, you noticed, and you moved on.
That's changing quickly. Agents now act. They move money, approve refunds, triage support tickets, screen applicants and manage on-chain treasuries. And to act well, they need memory:
your preferences, your habits, the context from last week.
Once an agent acts for you, its memory stops being a convenience and becomes a responsibility. A wrong memory is no longer a wrong sentence. It's a wrong payment, a wrong refund, a wrong rejection.
Five questions nobody could answer
While building and using agents, we kept hitting the same five questions:
| The question | What you get today | What you'd actually want |
|---|---|---|
| "How did it learn that?" | A pile of raw text snippets | A clear line from what it saw to what it concluded, and how that changed over time |
| "Why did it do that?" | A decision with no trail | A record of exactly which knowledge each decision used |
| "Can I trust this record?" | Logs on the operator's server | Evidence that can't be quietly edited, checkable by anyone |
| "What went wrong, and when?" | Guesswork | A way to search history for the moment a bad belief appeared |
| "Can it forget?" | "We deleted it, trust us" | Forgetting you can prove, without breaking the rest of the record |
Why existing tools don't solve this
We looked hard at what already exists before building anything.
- Vector databases and memory stores are good at remembering. But they're a current snapshot. They don't keep history, so you can't ask "what did you believe last Tuesday?"
- Logging and observability tools record what an agent did. They don't record what it believed, and the logs belong to the operator, the very party you might need to audit.
- Blockchains give you a public, tamper-proof clock. But you can't put private memories on a public chain.
Each tool solves one piece. None of them connects what an agent saw → what it concluded → what it did in a way that is private, versioned and provable at the same time.
The idea, in one sentence
> Treat an agent's mind like a git repository, and make every commit provable on a public chain.
We didn't want to replace Walrus Memory. It already stores agent memory privately and in a decentralised way. We wanted to build the layer that was missing on top of it:
> Walrus Memory gives agents memory. Engram gives that memory history, proof and control.
*
Part 3 · Who it's for
Engram is for anyone who might one day have to answer "why did the agent do that?" with evidence instead of a shrug.
| Who | The question they're stuck on | What Engram gives them |
|---|---|---|
| Agent developers | "My agent got worse after last week. What did it learn?" | log, diff, checkout, blame and bisect on the agent's mind |
| On-chain and fintech agents (wallet watchers, treasury bots, payment agents) | "Why did the agent move, or block, this money?" | A signed receipt for every decision, which anyone can verify |
| Regulated teams (finance, health, insurance, HR) | "Can we show which knowledge an automated decision relied on?" | Tamper-evident history and audit bundles that outsiders can check |
| Privacy-first apps | "The user asked us to delete their data. Can we prove we did?" | forget, which destroys the data's key and records it in history |
| Everyday assistant users (through MCP) | "What do you know about me? Forget that." | Engram tools inside Claude Code, Cursor and Claude Desktop |
Four stories that show why it matters
The wallet agent (our demo). An agent watches a Sui wallet through Tatum. It learns the owner's salary, rent and subscriptions, and stops alerting on normal payments. When money goes to an address the owner flagged as a scammer, it raises a CRITICAL alert. That one decision can be verified end to end, down to a public timestamp on Sui.
The support bot that went rogue. After an update, a support bot starts approving refunds it shouldn't. Instead of reading thousands of logs, the developer runs bisect, and it finds the exact commit where the bot learned "refunds are allowed up to 60 days" from one misread ticket. blame shows that ticket. forget removes it, and the next commit fixes the belief.
The trading dispute. A user says a trading bot made a trade "for no reason." The operator doesn't argue. They send the receipt for that trade, and the user runs verify on their own machine. It shows exactly which beliefs the bot used and proves they existed before the trade.
The right to be forgotten. A patient asks a health assistant to delete a conversation. After forget, the data can never be decrypted again, and the agent's own history shows the memory was removed and when.
Who doesn't need it
If you're building a simple chatbot with no need for history, audits or debugging, plain Walrus Memory is enough. And if your data must be edited in place, Engram isn't a fit, because it's append-only by design. That's what makes it trustworthy.
*
Part 4 · The ideas, in plain language
Engram borrows from two places: how people remember and how git tracks code. Here are the five building blocks.
Episode: what the agent saw
An episode is a raw experience. It could be a wallet transaction ("sent 0.05 SUI to 0x2498…"), something the owner said ("that's my rent"), or a tool result. Each episode is encrypted with its own key before it's stored. That detail matters later, when we get to forgetting.
Belief: what the agent concluded
A belief is a short statement the agent holds to be true, such as "The owner pays 0.05 SUI rent to 0x2498… once a month." Each belief has:
- a confidence score from 0 to 1,
- evidence: the exact episodes that support it,
- a version number, because beliefs change when the facts do,
- a status: active, revised or retracted.
Sleep: how episodes become beliefs
People don't remember every moment of their day. While we sleep, the brain turns experiences into knowledge. Engram does something similar. The sleep step hands new episodes and current beliefs to an LLM, which proposes new, revised or retracted beliefs.
There's one strict rule: every proposal must cite real episode IDs. If the model invents a reason or points at evidence that doesn't exist, the proposal is rejected. The agent can't make up why it believes something.
Commit: a snapshot of the mind
A commit freezes every active belief into one snapshot. All the beliefs are combined into a single fingerprint called a Merkle root: change any belief, even by one character, and the fingerprint no longer matches. The snapshot is signed with the agent's own key, stored on Walrus, and its fingerprint is published on Sui. Each commit names its parent, so history forms a chain that can't be rewritten without breaking every link after it.
Receipt: proof of why
Every time the agent makes a decision, Engram writes a receipt: "I did X, using exactly these beliefs, from this snapshot." The receipt is signed and includes a small mathematical proof (a Merkle proof) for each belief, showing it was part of the snapshot without revealing any of the other beliefs.
How they connect
classDiagram
direction LR
class Episode {
id: ep_…
source: user | tool | tatum | agent
keyId: own AES-256-GCM key
contentHash: sha256
blobId: Walrus blob
}
class Belief {
id: b_…
version: n
statement
confidence: 0..1
evidence: episode IDs
status: active | revised | retracted
}
class Commit {
id: sha256 of manifest
parent: commit ID
merkleRoot
beliefs: id@version
tombstones: episode IDs
signature: Ed25519
manifestBlobId
anchor: Sui tx + checkpoint
}
class Receipt {
id: r_…
action
inputHash
beliefs used
proofs: Merkle
commitId
signature: Ed25519
}
Episode "many" --> "1..many" Belief : evidence for
Belief "many" --> "1" Commit : snapshotted in
Commit --> Commit : parent
Receipt --> Commit : proven against
Receipt --> Belief : used
Episodes are evidence for beliefs. Beliefs are snapshotted in commits. Commits link to their parents. Receipts point at the commit and the beliefs they used. Follow the arrows and you can walk from any decision back to the raw experiences behind it.
*
Part 5 · The life of one memory
The easiest way to understand Engram is to follow a single memory from start to finish. Let's follow the rent payment from our demo.
flowchart LR
IN["Wallet tx<br/>user message<br/>tool result"] --> OBS["1 · observe"]
OBS --> EP["Episode<br/>encrypted with its own key"]
EP --> SLEEP["2 · sleep<br/>LLM consolidation"]
SLEEP --> BEL["Beliefs<br/>versioned · confidence · evidence"]
BEL --> COMMIT["3 · commit<br/>Merkle root + Ed25519 signature"]
COMMIT --> PROOF["Manifest on Walrus<br/>root anchored on Sui"]
BEL --> DECIDE["4 · decide / wrap<br/>relevant beliefs in"]
DECIDE --> REC["Signed receipt<br/>Merkle proofs into HEAD"]
REC --> VERIFY["5 · verify<br/>anyone, anytime"]
PROOF --> VERIFY
PROOF --> SYNC["6 · link / sync<br/>web dashboard"]
classDef step fill:#d4ff3a,stroke:#0a0a09,color:#0a0a09
classDef data fill:#1b1b19,stroke:#d4ff3a,color:#f3efe6
class OBS,SLEEP,COMMIT,DECIDE,VERIFY,SYNC step
class EP,BEL,PROOF,REC data
Step 1 · observe: the agent sees something
0.045 SUI leaves the owner's wallet. The agent reads it from the chain through Tatum, and observe turns it into an episode. Engram generates a fresh AES-256-GCM key for this one episode, encrypts it, and stores the ciphertext on Walrus. The owner also says "that's my rent", which becomes a second episode.
Step 2 · sleep: it draws a conclusion
sleep reads the new episodes and proposes a belief: "The owner pays 0.045 SUI rent to 0x2498… monthly", citing both episodes as evidence. Engram checks that both episode IDs are real before accepting it.
Step 3 · commit: it locks in what it knows
commit builds the Merkle root over every active belief, signs the snapshot with the agent's Ed25519 key, stores it on Walrus, and publishes the root on Sui through our Move contract. From this moment, there's a public, timestamped record of what this agent believed.
Step 4 · decide: it acts, and leaves a receipt
Next month, the same rent payment arrives. Before deciding, Engram hands the agent only the relevant beliefs (found through Walrus Memory's semantic recall). The agent stays quiet, because this is normal, and Engram writes a signed receipt: "No alert, because of belief monthly_rent@1, from commit d0f7d31f."
Step 5 · revise: the facts change
In month four, the rent goes up to 0.05 SUI. The agent raises a WARN, because this doesn't match what it knows, and the owner confirms the rise. At the next sleep, the belief isn't duplicated. It's revised: version 2 replaces version 1, and both stay in history.
Step 6 · verify: anyone can check
Months later, anyone holding a receipt can run verify. Engram checks the signature, the proofs, the snapshot, the history, the copy on Walrus and the anchor on Sui. If everything matches, the answer is VALID: this decision was made on this exact memory, at this time, and nothing has changed since.
And if it ever needs to forget
If the owner asks to forget that first rent message, forget destroys its key, retracts any belief that relied only on it, and records a tombstone in the next commit. More on that in Part 8.
*
Part 6 · The architecture
Engram follows one rule: the owner keeps the keys, Walrus keeps the data, Sui keeps the proof. Even our own website only shows what it can re-check for itself.
flowchart TB
subgraph L1["Access layer"]
direction LR
AGENT["Your AI agent<br/>(SDK: engram · wrap)"]
CLI["CLI<br/>npx @rohankumar4179/engram"]
MCP["MCP server<br/>Claude Code · Cursor"]
BROWSER["Browser + Sui wallet<br/>dashboard · docs · demo"]
end
subgraph L2["Engram layer"]
direction LR
CORE["<b>Engram core</b><br/>observe · sleep · commit · decide<br/>verify · forget · link<br/><i>keys + key vault stay local</i>"]
API["<b>Engram API</b><br/>wallet auth · hosted agents<br/>linked dashboards · live verify"]
end
subgraph L3["Services"]
direction LR
LLM["Gemini<br/>episodes → beliefs"]
TATUM["Tatum<br/>Sui gRPC gateway"]
end
subgraph L4["Decentralised storage and proof"]
direction LR
WALRUS[("<b>Walrus Mainnet</b><br/>Walrus Memory + Seal<br/>episodes · beliefs · manifests · receipts")]
SUI[("<b>Sui</b><br/>Walrus Blob objects<br/>engram_anchor events")]
end
AGENT --> CORE
CLI --> CORE
MCP --> CORE
BROWSER --> API
CORE -- "sync audit bundle" --> API
CORE -- "sleep" --> LLM
CORE -- "store encrypted" --> WALRUS
CORE -- "anchor root" --> SUI
CORE -- "read chain" --> TATUM
API -- "re-verify" --> TATUM
TATUM --> SUI
WALRUS -. "blob registered on" .-> SUI
classDef engram fill:#d4ff3a,stroke:#0a0a09,color:#0a0a09
classDef access fill:#ffffff,stroke:#555,color:#0a0a09
classDef svc fill:#fff4e6,stroke:#ff7a45,color:#0a0a09
classDef dec fill:#eef4ff,stroke:#3b5bdb,color:#0a0a09
class CORE,API engram
class AGENT,CLI,MCP,BROWSER access
class LLM,TATUM svc
class WALRUS,SUI dec
Reading the diagram from top to bottom:
Layer 1 · How you reach Engram
You can use Engram four ways, depending on who you are:
- The SDK wraps an agent you've already built. Your agent's logic doesn't change. Engram sits around it, handing it beliefs and collecting receipts.
- The CLI gives you every command, from init to verify, in your terminal.
- The MCP server puts Engram's tools inside Claude Code, Cursor and Claude Desktop, so an AI assistant can commit, blame and verify its own memory.
- The web app lets anyone sign in with a Sui wallet, run a hosted agent, or watch a linked agent on a dashboard.
Layer 2 · The Engram engine
Engram core does the real work: observe, sleep, commit, decide, verify and forget. It runs on your machine, next to your agent. The agent's signing key and the vault of per-memory keys never leave it.
The Engram API powers the website: wallet sign-in, hosted agents and linked dashboards. It never holds your keys, and it re-verifies everything you send it before showing it.
Layer 3 · Helper services
Gemini does the "thinking" during sleep, turning episodes into beliefs, with every answer checked against real evidence. Tatum is Engram's window onto the Sui blockchain: every Mainnet chain read goes through Tatum's Sui gRPC gateway.
Layer 4 · Where trust comes from
Walrus stores everything durable: episodes, beliefs, snapshots and receipts, encrypted for the owner. Sui holds the public proof: each stored item is registered as an object on Sui, and our Move contract publishes each snapshot's fingerprint for anyone to read.
What leaves your machine, and what doesn't
| Stays with the owner | Goes to Walrus | Goes to Sui | Goes to the dashboard |
|---|---|---|---|
| Agent key, key vault, decrypted memories | Encrypted episodes, beliefs, manifests, receipts | Blob registrations and anchor events (Merkle roots) | Commits, beliefs and receipts, re-verified by the server |
What happens during a commit
Here's every step engram commit takes, in order:
sequenceDiagram
autonumber
participant D as Developer / agent
participant E as Engram SDK
participant W as Walrus Memory
participant S as Sui (engram_anchor)
participant T as Tatum gRPC
D->>E: commit("week 2")
E->>W: push pending episodes, beliefs, receipts
W-->>E: Walrus blob IDs
E->>E: Merkle tree over beliefs + tombstones
E->>E: manifest {parent, root, beliefs, blob IDs}, signed with Ed25519
E->>W: store manifest
W-->>E: manifest blob ID
E->>S: anchor(agent key, commit ID, root, parent, manifest blob)
S-->>E: Anchored event in checkpoint N
E->>T: read back Blob object and anchor
T-->>E: confirmed on chain
E-->>D: commit 19040b51, root 392bf9cb…, anchored
Engram doesn't just send the proof to the chain. It reads it back through Tatum to confirm it landed before reporting success.
*
Part 7 · How the proof works
This is the heart of Engram, so it's worth explaining slowly. We use only standard, well-studied building blocks (SHA-256, Ed25519 signatures, AES-256-GCM encryption and Merkle trees). There's no custom cryptography.
A fingerprint for the whole mind
Each belief is hashed into a short fingerprint. Those fingerprints are paired up and hashed again, and again, until one fingerprint is left at the top: the Merkle root. That single value represents the agent's entire mind at that moment. Change any belief, anywhere, and the root changes.
Two public anchors for every commit
1. Walrus registers every stored item as a Blob object on Sui. So the snapshot itself gets an on-chain record of when it was stored.
2. Our Move contract, engram_anchor, publishes the Merkle root in the clear. It emits one Anchored event with the commit ID, the root and the agent's public key. It creates no objects, so it only costs gas. Anyone can read it, and nobody can change it afterwards.
That second anchor is what lets a stranger check a commit without trusting us and without decrypting anything.
What verify checks
engram verify, and the Verify button on the website, run the same chain of checks. If any one fails, the answer is INVALID. There's no "mostly valid."
flowchart TB
R(["Receipt r_…<br/>or commit"]) --> A
subgraph S1["1 · The decision"]
direction LR
A["Receipt signature<br/>Ed25519 by the agent"] --> B["Belief Merkle proofs<br/>beliefs are in the commit"] --> T["Timing<br/>decided after the commit"]
end
subgraph S2["2 · The snapshot"]
direction LR
C["Commit ID = sha256 of manifest<br/>+ Ed25519 signature"] --> D["Merkle root rebuilt<br/>from the beliefs"] --> E["History<br/>every parent signed + linked"]
end
subgraph S3["3 · Storage and chain"]
direction LR
F["Walrus<br/>manifest is stored"] --> G["Sui anchor via Tatum<br/>same root, public timestamp"]
end
T --> C
E --> F
G --> OK(["VALID<br/>this decision used exactly this memory"])
classDef ok fill:#b6f25c,stroke:#0a0a09,color:#0a0a09,font-weight:bold
classDef chk fill:#ffffff,stroke:#555,color:#0a0a09
class OK ok
class A,B,T,C,D,E,F,G chk
| Check | What it proves |
|---|---|
| Receipt signature | The agent really made this decision |
| Belief proofs | The beliefs it cited were really in that snapshot |
| Timing | The decision came after the snapshot, so it couldn't have been backfilled |
| Commit ID and signature | The snapshot belongs to this agent and hasn't been altered |
| Merkle root | The beliefs rebuild exactly the same fingerprint |
| History | Every earlier snapshot is signed and correctly linked |
| Walrus | The snapshot is really stored on Walrus |
| Sui anchor | The fingerprint was public on chain at that time |
Teams can also export an audit bundle (engram export --audit), and anyone can check it with engram audit <file>, with no access to the agent at all.
*
Part 8 · Forgetting, without rewriting history
This was the hardest design question in the whole project.
We chose Walrus because it's permanent and decentralised: nobody can quietly delete or edit what's stored there. But people have a right to be forgotten. How can permanent storage
forget?
Our answer: don't delete the data. Destroy the only key that can read it.
Remember that every episode is encrypted with its own key before it's stored. Those keys live in a vault on the owner's machine. To forget one memory, Engram destroys that one key. The ciphertext stays on Walrus, but it's now meaningless noise, forever.
flowchart LR
F["engram forget ep_…"] --> K["Destroy that episode's<br/>AES key in the vault"]
K --> X["Ciphertext on Walrus<br/>can never be decrypted"]
K --> RT["Retract beliefs that<br/>relied only on it"]
RT --> TB["Next commit records<br/>a tombstone"]
TB --> V["Old receipts still verify:<br/>history grows, never rewritten"]
Two more things happen at the same time:
- Any belief that relied only on that memory is retracted, so the agent stops acting on it.
- The next commit records a tombstone: a note that this episode was forgotten, and when.
The history isn't rewritten. It grows. Old receipts still verify, because forgetting becomes part of the record instead of a hole in it. You get a provable "we forgot this, on this date" instead of "trust us, it's gone."
*
Part 9 · Why Walrus, Sui and Tatum
Memory you want to trust shouldn't depend on trusting whoever runs the server. Engram needed four things from its storage, and this stack provides all four.
| Engram needs… | The stack provides… | How Engram uses it |
|---|---|---|
| Memory no single party can quietly change or delete | Walrus: decentralised storage across independent nodes | Episodes, beliefs, snapshots and receipts all live on Walrus |
| A stable ID to point at in proofs | Every Walrus blob has an ID, registered as a Blob object on Sui | Commits list each episode's blob ID, blame shows them, verify checks them |
| Privacy: only the owner reads raw memories | Walrus Memory encrypts data for its owner with Seal | Engram adds its own per-memory key on top, which makes provable forgetting possible |
| A public clock, so history can't be backdated | Sui transactions and checkpoints | engram_anchor puts each commit's Merkle root in a public event |
Walrus Memory: where everything lives
Each kind of data gets its own Walrus Memory namespace (engram-<agent>-episodes, -beliefs and so on). Walrus Memory's semantic recall finds the beliefs that matter for each decision, so the agent gets "what do I know about rent?" instead of its whole memory. A user's agent can also run on their own Walrus Memory account. The web app sets that up with two wallet-signed transactions.
Sui: the public clock
Sui gives every commit a public timestamp nobody can move. Because each commit names its parent, and each parent is anchored, the whole history is pinned in time.
Tatum: how Engram reads the chain
Every Mainnet chain read goes through Tatum's Sui gRPC gateway: Walrus Blob objects, anchor transactions and the demo agent's live wallet feed. One affectedAddress query returns every transaction that touched a wallet, sent or received, which is exactly what a wallet watcher needs.
What only works because of this stack
- verify checks a decision against data no single party could have edited.
- Linked dashboards stay honest. Our server can't read your private memories, but it can still confirm each snapshot is stored on Walrus (through the public aggregator) and that its fingerprint is on Sui.
- Forgetting with proof, on storage that's permanent by design.
> Private memory, stored openly, that anyone can verify.
*
Part 10 · The demo: an agent that learned from real money
We didn't want a scripted demo with fake data piped into the agent. So our example agent, money-ops, watches a real Sui wallet through Tatum.
We created five wallets (an owner, an employer, a landlord, a streaming service and a scammer) and sent real SUI between them: salary in, rent and a subscription out, a rent rise, and a staged theft. The agent never sees the script. It reads the owner's wallet from the chain like any other wallet, and the owner occasionally explains things in plain words, the way a person would.
| Phase | On chain | What the agent does |
|---|---|---|
| Month 1 | Salary in, rent and a subscription out. The owner explains them. | Alerts on all 3 (it knows nothing yet), then learns 3 beliefs |
| Months 2–3 | The same six transfers again | Quiet on all 6, each receipt citing the belief it used |
| Month 4 | Rent rises. 0.18 SUI leaves to an unknown address. The owner: "that's a scammer." | Warns about the rent change, flags the unknown payment, then revises the rent belief and learns the scam address |
| Month 5 | New rent, and another payment to the scammer | Quiet on the new rent. CRITICAL alert on the scammer, from memory. |
That's the whole point in one table: the agent learns, changes its mind when the facts change, and remembers a threat. And every step is provable.
Watching the agent think: the Mind view
The Mind view draws the agent's beliefs as a map. Each card in the middle is a belief, with its confidence bar and how many pieces of evidence support it. The small tags around each card are the episodes behind it: wallet events and things the owner said. The slider at the top
replays history commit by commit, so you can drag back to Month 1 and watch the agent learn.
!Image description
Notice the version numbers: monthly_rent v5, salary_payment v3. These beliefs weren't written once. They were refined each time new evidence arrived.
Every memory, encrypted and on Walrus: the Memory view
The Memory view lists every raw episode: wallet events and owner messages. Each one shows its Walrus blob ID, with a link to see it on the Walrus explorer. The explorer can prove the blob exists, but not what it says, because only the owner holds the key. The learned tag shows that an episode has already been consolidated into beliefs.
!Image description
A history you can't rewrite: the History view
The History view is the agent's git log. Each card is one commit, showing which beliefs were added (+) or revised (pencil), along with the Merkle root. On the right are the links to the snapshot on Walrus and the anchor transaction on Sui, with its checkpoint number. Look at Month 4: two new beliefs about the scam address, and revisions to rent, salary and subscription, all in one signed, anchored snapshot.
!Image description
Every decision comes with a receipt: the Receipts view
This is where everything pays off. The agent made ten decisions and raised three alerts. Each row shows the decision, the agent's reason, the exact belief versions it used, and the commit those beliefs came from.
!Image description
Read it from the bottom up and you can see the agent learn. Early decisions cite monthly_rent@1. Then a WARN when the rent changed, citing monthly_rent@2. Then a CRITICAL on the first payment to an unknown address, citing none, because the agent hadn't learned about it yet. And at the top, the second payment to the scammer: CRITICAL, citing scam_address_0xcbed@1, proven against commit 19040b51.
Then anyone can check it
This is the live output for that scam alert. Click Verify on the site, or ask the API yourself:
✔ receipt signature "ALERT[critical]: sent 0.025 SUI to 0xcbed89… — Outgoing transfer detected
to a known scam address representing theft." signed by the agent
✔ belief proofs 2 belief(s) proven to be in commit 19040b51
✔ timing decision made after its commit
✔ commit id sha256 of the manifest matches the commit ID
✔ commit signature Ed25519 by agent 0e648084a79c…
✔ commit merkle root 5 beliefs + 0 tombstones → root 392bf9cbb518…
✔ commit history 2 earlier commit(s), all signed and hash-linked
✔ commit walrus manifest recalled from Walrus Memory, blob YI30MCNaOG…
✔ commit sui anchor Anchored event: root 392bf9cbb5… public in checkpoint 397926925 (testnet)
✔ commit anchored at 2026-10-22T14:35:05.365Z
VALID
Check it without trusting us
You don't need our software, or our word, for any of this:
# 1. A memory is stored on Walrus Mainnet (HTTP 200; the content is encrypted)
curl -I https://aggregator.walrus-mainnet.walrus.space/v1/blobs/FC-92hYt6rX2P8oJy-pvKRMbOAW0g3V2DranpmQx-Ss
# 2. The Merkle root of commit 19040b51 is public on Sui
curl -s https://graphql.testnet.sui.io/graphql -H 'content-type: application/json' \
-d '{"query":"{ transaction(digest: \"BPFs7EqazA9nxUtr5rGnjcAJb4eUqxsNTUcA2L5aT4yx\") { effects { events { nodes { contents { json } } } } } }"}'
# 3. The full proof check, through the live API
curl -s https://engram-blond.vercel.app/api/demo/verify/r_5080ccb4fd9c3869
16 memories on Walrus Mainnet. 4 commits anchored on Sui. Every link checked before we published. The full list of blob IDs and transactions is in the [README](README.md#on-chain-evidence-verify-it-yourself).
A note on honesty: the "theft" is staged, because the owner's own key signs it. But it's an ordinary on-chain transfer, and the agent has no way to tell it apart from a real one. The whole story moved about 0.75 SUI.
*
Part 11 · Debugging an agent's mind
Proof is one half of Engram. The other half is everyday developer tooling, the commands you reach for when an agent starts behaving strangely.
| Command | The question it answers |
|---|---|
| log | What has this agent learned, commit by commit? |
| diff | What changed in its beliefs between two points? |
| checkout HEAD~1 or checkout 2026-10-20 | What did it believe then? |
| blame <belief> | Which exact episodes (with Walrus blob IDs) taught it this? |
| bisect <good> <bad> | In which commit did it first start believing something wrong? |
bisect is the one we're proudest of. Like git bisect, it does a binary search through the agent's history. You tell it one commit where the agent behaved well and one where it didn't, and it narrows down to the exact snapshot where a bad belief first appeared. Combined with blame and forget, you can go from "the agent is acting weird" to "here's the memory that caused it, and it's gone" in a few commands.
*
Part 12 · Using it today
In code: the SDK
Wrapping an existing agent takes a few lines. Your agent's logic stays the same:
import { engram } from "@rohankumar4179/engram-sdk";
const mind = engram({ agent: "money-ops" }); // Walrus Memory, Tatum, Gemini from .env
// Wrap your existing agent: relevant beliefs in, a signed receipt out.
const agent = mind.wrap(async (tx, beliefs) => myAgent.decide(tx, beliefs), {
used: (decision) => decision.beliefIds,
});
const decision = await agent(tx);
mind.observe({ source: "tatum", data: tx }); // encrypted episode
await mind.sleep(); // episodes → beliefs
await mind.commit("week 2"); // signed, stored on Walrus, anchored on Sui
await mind.beliefs({ about: "rent" }); // Walrus Memory semantic recall
mind.at("2026-10-01"); // time travel
mind.forget("ep_…"); // provable forgetting
await mind.verify(agent.lastReceipt!.id); // signature → proofs → Walrus → Sui
In the terminal: the CLI
npx @rohankumar4179/engram init my-agent
npx @rohankumar4179/engram observe "I pay 450 USDC rent to 0x7a11 on the 1st"
npx @rohankumar4179/engram sleep # episodes → beliefs
npx @rohankumar4179/engram commit -m "first week" # signed → Walrus → Sui
npx @rohankumar4179/engram verify # ✔ … VALID
Needs Node 20+ and a .env with your keys (configuration).
On Windows PowerShell, use npx.cmd.
Inside your AI assistant: MCP
Add one entry to Claude Code, Cursor or Claude Desktop, and your assistant gets Engram's tools:
{ "mcpServers": { "engram": { "command": "npx", "args": ["@rohankumar4179/engram", "mcp", "-C", "/path/to/agent"] } } }
On the web: link your agent to a dashboard
Linking works like gh auth login. The CLI shows a one-time code, and you approve it on the website with your Sui wallet. Signing in is one free text signature, never a transaction.
sequenceDiagram
autonumber
participant CLI as engram CLI
participant API as Engram API
participant B as Owner's browser
participant WL as Sui wallet
CLI->>API: POST /api/link/start (agent name, public key)
API-->>CLI: code K7QF-29XM + approval URL
CLI->>B: owner opens /link?code=K7QF-29XM
B->>WL: sign the free sign-in message
WL-->>B: signature
B->>API: POST /api/link/decide (approve, signed-in wallet)
CLI->>API: GET /api/link/poll
API-->>CLI: link token (bound to wallet + agent key)
CLI->>API: POST /api/link/sync (commits, beliefs, receipts)
API->>API: re-verify signatures, roots, Walrus, Sui
API-->>CLI: synced, verified
Note over CLI,WL: Later commits sync automatically.<br/>Raw episodes and keys never leave the machine.
After that, every commit syncs automatically. Only commits, beliefs and receipts are uploaded, never raw episodes or keys. A link token only accepts bundles signed by that agent's key, and history can only grow, never be replaced.
*
Part 13 · What broke, and how we fixed it
Building on live infrastructure during a hackathon means the ground moves under you. Here's what broke, and what we learned from it.
Sui JSON-RPC went away
Sui switched JSON-RPC off, and Tatum's JSON-RPC gateway started answering "No healthy upstream" to every call. We rewrote our Tatum client on gRPC. Tatum serves native gRPC rather than gRPC-Web, so we use a native transport. The upside: one affectedAddress query now gives us everything a wallet watcher needs.
Walrus Memory's embedder went down
On 22 October, Walrus Memory's server-side embedding failed
(MemWal#1285). Rather than wait, we added a fallback to Walrus Memory's manual mode: Engram embeds locally, Seal-encrypts with the owner's key, and the relayer only ever stores ciphertext. Reads merge both paths, so verify never noticed the switch.
The relayer rate-limits each key
Walrus Memory's relayer allows 60 requests a minute per key. Engram now waits out 429 responses using the relayer's own retry_after_seconds, instead of failing.
LLM free tiers are small
Decisions are batched, quota errors rotate between keys and models, and a failed wallet sync no longer stops the agent from learning what the owner told it.
*
Part 14 · Honest limits
We'd rather you hear these from us:
- Forgetting can't un-read a copy. If someone already decrypted a memory before it was forgotten, destroying the key can't undo that. And the summaries of retracted beliefs stay in history, clearly marked as retracted.
- Snapshots are encrypted for the owner. Outsiders confirm a snapshot exists on Walrus and check its content through the public Merkle root on Sui, rather than reading it directly.
- Keys live on disk in .engram/ today. Moving them to Seal or a key management service is on the roadmap.
- The Move anchor runs on Sui Testnet today. The memories on Walrus and the Tatum chain reads are on Mainnet.
*
Part 15 · What we shipped, and what's next
Built during the hackathon
| Piece | Status |
|---|---|
| CLI: init · observe · sleep · commit · log · diff · checkout · blame · bisect · verify · forget · export/audit · link/sync · mcp | Published on npm: npx @rohankumar4179/engram |
| TypeScript SDK: wrap any agent, get signed receipts | Published on npm: @rohankumar4179/engram-sdk |
| MCP server: 10 tools for Claude Code, Cursor and Claude Desktop | Done |
| Move contract engram_anchor | Live on Sui Testnet |
| Tatum Sui gRPC for every Mainnet chain read | Done |
| money-ops example agent on real wallet transactions | Done |
| Web app: wallet sign-in, hosted agents, linked CLI agents, live verify, public demo, docs | Live at engram-blond.vercel.app |
| Tests | SDK 62 · CLI 10 · money-ops 6 · server 20, all passing |
Next few months
- The Move anchor on Sui Mainnet, so roots are public on Mainnet as well as Testnet
- Plug-ins for the Vercel AI SDK, LangChain, the Claude Agent SDK and Mastra
- A Python SDK with the same API
- Scoped sharing: hand part of a memory (say, only the finance beliefs) to another agent, with an expiry date
Further out
- Team dashboards: many agents, many team members, and alerts when a belief changes
- Paid memory sharing: agents sell scoped knowledge to each other on Sui, with proof of exactly what was sold
- Keys in Seal or a KMS instead of on disk
- A public verification page: paste a receipt, get a verdict, nothing to install
What success looks like
Developers reach for Engram when they need to debug an agent. Teams use it to audit one. And users trust an agent because they can check what it remembered, instead of being asked to take it on faith.
*
Try it
| | |
|---|---|
| Demo video | youtu.be |
| Live demo agent (no wallet needed) | engram-blond.vercel.app |
| Web app | engram-blond.vercel.app |
| Docs | engram-blond.vercel.app |
| Code | rohan911438/Engram |
| CLI | @rohankumar4179/engram |
| SDK | @rohankumar4179/engram-sdk |
| Anchor package (Sui Testnet) | 0xa1fccbb3…bf86b |
*
Agents are getting memories. We think those memories should come with a history you can read, a proof you can check, and an off switch you can trust.
Walrus Memory gives agents memory. Engram gives that memory history, proof and control.
1 comment
Sui Bridge Claim Bot Sent $392K to the Cetus Attacker
Originally published at Sui Bridge Claim Bot Sent $392K to the Cetus Attacker.
On 16 October 2026, between 04:39 and 04:40 UTC, an automated bot finalized a batch of old, unclaimed Sui Bridge withdrawals on Ethereum. Most of them belonged to ordinary users. Eight of them did not. They had been sent from the Sui address of the Cetus exploiter, and finalizing them delivered 86 ETH, 109,000 USDT and 0.9 WBTC to the attacker's Ethereum wallet, around $392K by the bot operator's own estimate.
No contract was broken. Nobody forged a signature. The bridge did exactly what it was built to do. That is what makes this incident worth studying: a perfectly correct, permissionless code path turned dormant attacker funds into spendable ones, because the off-chain automation around it never asked whose money it was moving.
TL;DR
- What happened: a "rescue" bot completed stale Sui Bridge withdrawals in three Ethereum transactions. Eight of the withdrawals had the Cetus attacker's Sui address as sender and its Ethereum address as recipient.
- Assets delivered to the attacker: 86 ETH, 109,000 USDT and 0.9 WBTC, which the operator put at roughly $392K.
- Root cause: not a contract bug. transferBridgedTokensWithSignatures() lets anyone submit a committee-signed message, and the bot submitted every valid message it found without screening the sender or recipient.
- Status at the time of writing: the 109,000 USDT and 0.9 WBTC were still in the attacker's wallet, and USDT's on-chain blacklist did not yet include the address. The operator has asked for help getting the USDT frozen.
Background: Cetus and the Leftover Withdrawals
Cetus, the largest concentrated-liquidity DEX on Sui, was drained of roughly $220 million on 22 May 2025 through an arithmetic overflow in its liquidity math. Sui validators froze about $162 million on the Sui side within the first hour, while part of the haul had already left for Ethereum. Public analyses from several research teams list the attacker's Sui address as 0xe28b50…8ff06 and the Ethereum address that received bridged funds as 0x89012a55…24919b.
The 16 October TokensClaimed events, which we decoded ourselves, show that a set of Sui-to-Ethereum bridge messages from that same Sui address had been signed but never claimed on Ethereum. On a lock-and-claim bridge, that leaves the funds sitting in the Ethereum-side vault indefinitely. We could not find a public explanation of why they were left unclaimed, and we won't guess at one. What matters is that they were still claimable, and that claiming them pays out to the recipient fixed in the message, which here was the attacker.
How the Sui Bridge Claim Works
The Ethereum side of Sui Bridge is open source. A transfer from Sui is finalized on Ethereum by calling transferBridgedTokensWithSignatures() with the message and enough committee signatures. The function checks the signatures, checks that the nonce hasn't been processed, enforces a 24-hour rate limit, and then pays the recipient encoded in the message. It does not care who msg.sender is.
The simplified sketch below is our illustration of that flow, condensed from the public SuiBridge.sol, not a verbatim copy:
// Simplified illustration of a permissionless bridge claim (not verbatim SuiBridge code)
function transferBridgedTokensWithSignatures(
bytes[] memory signatures,
Message memory message
) external nonReentrant verifyMessageAndSignatures(message, signatures) {
require(!isTransferProcessed[message.nonce], "already processed");
TokenTransferPayload memory p = decodeTokenTransferPayload(message.payload);
require(p.targetChain == chainID, "wrong chain");
// Funds always go to the recipient chosen on the source chain.
// The caller cannot redirect them, and the caller is never checked.
_transferTokensFromVault(message.chainID, p.tokenID, p.recipientAddress, p.amount);
isTransferProcessed[message.nonce] = true;
emit TokensClaimed(message.chainID, message.nonce, chainID, p.tokenID,
p.amount, p.senderAddress, p.recipientAddress);
}
This is a sound, common design. Because the caller cannot change where the money goes, letting anyone relay a message is safe for the user, and it is good for liveness: a user who lost interest, or a relayer that went offline, does not leave funds stranded forever. Many bridges work the same way.
The catch is that "safe for the user" assumes the recipient should receive the funds. When the recipient is an exploiter, a permissionless claim is a one-way valve that anyone can open.
What the Bot Did, Step by Step
The three claim transactions came from the same externally owned account, 0x7f2e…6671, each one a batched Multicall3 call that finalized many withdrawals at once. We decoded every TokensClaimed event emitted by the Sui Bridge contract in those transactions. The withdrawals sent to the attacker were:
| Tx | Sui nonce | Asset | Amount |
| --- | --- | --- | --- |
| 0x89ca33…dde89 | 7025, 7027, 7030 | ETH | 28 ETH each (84 ETH) |
| 0x89ca33…dde89 | 7028 | WBTC | 0.9 WBTC |
| 0x89ca33…dde89 | 7031 | USDT | 93,000 USDT |
| 0xce494e…36ac | 7020, 7022 | USDT | 8,000 USDT each |
| 0xe63cb0…1fc8 | 7021 | ETH | 2 ETH |
Every one of these events carries the same 32-byte sender, 0xe28b50cef1d633ea43d3296a3f6b67ff0312a5f1a99f0af753c85b8b5de8ff06, the Cetus attacker's Sui address, and the same recipient, 0x89012a55cd6b88e407c9d4ae9b3425f55924919b. The two signals that could have stopped the claim were sitting in the event data the whole time.
The same batches also finalized legitimate withdrawals for other users, including one WBTC and two ETH withdrawals on Sui Bridge, plus pending withdrawals on other protocols' contracts. In other words, this was a general-purpose "finish what others left unfinished" bot, and the attacker's messages simply looked like more stale funds.
The on-chain exchange that followed
About half an hour later, a user signing as tanuki42 sent an on-chain message to the bot's address pointing out that roughly $390K had gone to "an address publicly associated with the Cetus exploit" and suggesting it screen recipients before "rescuing" funds. Defimon Alerts relayed the message on X.
The operator, signing as lostandfound.eth, replied on-chain at 05:38 UTC: "you're right, our mistake. We didn't know 0x89012a…919b was the Cetus attacker when our automated run completed those Sui Bridge withdrawals." The reply lists the three claim transactions, estimates the total at about $392K, says the 109,000 USDT had not moved, asks for the case to be routed to Tether and Cetus for a freeze, and says the bot now screens every recipient against known exploit and sanctioned addresses before claiming.
When we checked the wallet after these messages, it still held 109,000 USDT and 0.9 WBTC, and USDT's getBlackListStatus() for the address returned false. The ETH, of course, cannot be frozen by anyone.
Why This Matters Beyond One Bot
It is tempting to file this under "operator error" and move on. We think there are three broader lessons.
1. Dormant is not the same as safe
After an exploit, incident response focuses on funds that are moving. Messages that were signed but never executed get far less attention, yet they are live liabilities. Anyone, at any time, can turn them into spendable assets. The same applies to queued withdrawals, unexecuted governance actions, pending limit orders and approvals that never expire. We made a similar point about stale state in our NEAR Intents exploit analysis, where balances that looked inert turned out to be withdrawable.
2. Permissionless relaying moves the screening burden off-chain
When a protocol lets anyone finalize anything, the protocol itself does no screening, so whatever screening exists lives in the relayers. A careful relayer can be undone by a careless one: it takes one bot, one person running a script, or one MEV searcher looking for gas refunds to complete the transfer. Protocol teams should not assume "nobody will bother" is a control.
3. Recovery tooling is security-sensitive software
Tools that find stuck bridge funds have drawn a lot of attention lately, and the well-known checkers are read-only: they tell users what is claimable and leave the claim to them. A bot that executes claims on others' behalf is a different thing: it is a payment system with no compliance checks. It deserves the same threat model as any contract that moves value.
Mitigations
For bridge and protocol teams
1. Treat unclaimed attacker messages as part of incident response. After an exploit, list every signed-but-unexecuted outbound message from attacker addresses and decide how to handle it, whether through a governance or committee action, an emergency pause path, or coordination with token issuers, before someone else decides for you.
2. Consider a sender and recipient hold list on the claim path. A narrowly scoped, governance-controlled list that delays (rather than blocks forever) claims from known exploit addresses keeps permissionless relaying for everyone else. It is a trade-off against censorship resistance and must be governed transparently.
3. Expose message provenance clearly. Make the source-chain sender easy to read in events and explorer views so relayers and monitors can screen it.
For relayers and recovery bots
Screen both ends of the transfer, cap what can be claimed without human review, and fail closed when a screening source is unavailable. An off-chain check is enough, but a wrapper contract makes the rule enforceable. The following is a simplified illustration:
// Simplified illustration: a relayer wrapper that refuses flagged transfers
contract ScreenedClaimRelayer {
ISuiBridge public immutable bridge;
IScreeningList public immutable screening; // maintained off-chain, updated by a multisig
uint256 public immutable reviewThresholdUsd;
function claim(bytes[] calldata sigs, Message calldata m, uint256 quotedUsd) external {
TokenTransferPayload memory p = decodeTokenTransferPayload(m.payload);
require(!screening.isFlaggedSui(p.senderAddress), "flagged sender");
require(!screening.isFlaggedEvm(p.recipientAddress), "flagged recipient");
require(quotedUsd < reviewThresholdUsd, "needs manual review");
bridge.transferBridgedTokensWithSignatures(sigs, m);
}
}
For auditors
- Map every permissionless finalize, claim, execute or settle function and ask what dormant inputs it can consume. If an exploit happened tomorrow, which of those inputs would belong to the attacker?
- Check that incident runbooks cover pending messages, not just pausing contracts. A pause that blocks new deposits but not old claims may leave the most important door open.
- Review recovery and keeper bots with the same rigor as on-chain code when they move user funds. Our smart contract security checklist and our overview of top DeFi security risks cover access control and operational risks that apply here as well.
Key Addresses and Transactions
- Claim tx 1: 0x89ca33e27e8a8b409a202b2c5710d6e1bb0accd505b6c34e95c24f35a14dde89
- Claim tx 2: 0xce494e04a3fe01292c7edb8b1be228c943926e920bdb3737786e6062670d36ac
- Claim tx 3: 0xe63cb0903e6784fd2343c1052ba190fe37c85d8b1d9442b9b54c1155b2e41fc8
- Claim bot (signed as lostandfound.eth): 0x7f2ee458d58e61345ad61a70e8072511bf9f6671
- Cetus attacker, Ethereum: 0x89012a55cd6b88e407c9d4ae9b3425f55924919b
- Cetus attacker, Sui: 0xe28b50cef1d633ea43d3296a3f6b67ff0312a5f1a99f0af753c85b8b5de8ff06
- Sui Bridge contract on Ethereum: 0xda3bd1fe1973470312db04551b65f401bc8a92fd
Sources
- Ethereum transaction receipts for the three claim transactions above, decoded by our team (TokensClaimed events and token transfers)
- Defimon Alerts on X: on-chain message from tanuki42
- Defimon Alerts on X: on-chain reply from lostandfound.eth
- Telem: bridge operator sent ~$392K USDT to the Cetus attacker
- Telem: ~$390K in stale Sui Bridge withdrawals sent to a Cetus-linked address
- SuiBridge.sol in the MystenLabs/sui repository
- OAK: Cetus Protocol concentrated-liquidity overflow and Blockscope: Cetus exploit analysis: background and attacker addresses
Closing Thoughts
The Sui Bridge contract behaved correctly, and the bot operator acknowledged the mistake within about half an hour of being flagged and changed its process. Still, a well-meaning script handed an exploiter close to $400K that had been sitting unclaimed in the bridge vault. If your protocol has any function that anyone can call to finalize something, your security model has to include the question of who that something belongs to.
Running a bridge, a keeper network or a recovery tool that moves other people's funds? Contact Panda Security for a design and code review, or see our audit pricing.
1 comment
Mentions
What it took to give an AI agent a memory it could delete In Nigerian towns, hiring a tradesperson runs on word of mouth. You ask in a group chat for someone who can fix a breaker or clear a blocked drain, and you get a phone number. If the person takes your money and stops answering, you have no recourse and no record that it happened. Gigr is a marketplace that replaces that with something accountable. Every user gets a wallet on signup. Money sits in an escrow contract and is released when work is confirmed, in milestones when a job has stages. On completion the artisan receives a vouch, which is a compressed on-chain certificate proving a settled job actually happened. A vouch cannot be bought or faked because it can only be minted through an escrow transaction that moved real money. On top of that sits Gigidy, an assistant you talk to instead of filling in forms. Say what you need and it finds providers, drafts the request, and holds your budget. This post is about the problem we hit building the assistant, and what we had to do to fix it. The assistant could not remember anything The first version was stateless. Each conversation started from nothing, so the agent asked again for a budget the user had given yesterday and a neighbourhood they had already named. Worse, it could not learn from outcomes. A user who hired someone who did poor work got no benefit from that experience in the next job. We had been storing a small amount of this in a JSON column on the user row. That is not memory. It is a settings table. It cannot be searched by meaning, it cannot hold a hundred observations without becoming a mess, and it belongs to our database rather than to the person. What we moved it to Walrus Memory is a memory service built on Walrus, which stores data as blobs on the Sui blockchain. Each user gets their own namespace inside our account, so one person's memories are never recalled against another's. The agent now writes facts about a user there and recalls them by meaning rather than by key. When someone asks for a plumber in Akoka with a budget of fifteen thousand naira, the search returns sentences about their past jobs and their area rather than requiring us to know in advance which field to look up. Two decisions shaped how this works. First, facts are produced by templates over real database rows, never generated by a language model. A completed job produces a sentence because the job has a category, a price and a year. If the row is missing a field, no fact is written. A guessed memory is worse than no memory, because the user has no way to know it was guessed. Second, memory grows with use. Early in development we backfilled existing history, and the facts we have now are a snapshot rather than a fixed number. The number changes every time someone completes a job. Deletion on a store that does not delete Walrus is immutable by design. A blob is an object on Sui, and you cannot edit a field inside it. When we started, the Python SDK had no delete method at all, so we filed an issue describing it. Mysten reproduced it and shipped forget in version 0.2.2 of the SDK. That method deletes a whole namespace, which is not what users want. A user who wants one memory removed, or one fact corrected, is asking for something the storage model does not offer. We built it on top of what exists. To delete one fact, the service reads every memory in the namespace, works out what should remain, deletes the namespace, and writes the remainder back. The dangerous moment is the gap between the delete and the rewrite. If the process dies there, the user has lost everything. Before deleting anything, we write the exact list of what must be restored to a journal file on disk, using an atomic rename so a half-written file cannot be read. Every later operation finishes any pending restore before doing its own work. There is a test that kills the process in the middle of the rewrite and proves a new instance repairs the namespace on the next call. You can read that test at test_memory_reconcile.py. The interface does not pretend this is free. The confirmation tells the user that the memories they keep will be stored again with today's date, because that is what actually happens when you rebuild a namespace. Reading the chain through Tatum Tatum is a blockchain infrastructure provider, and we use it in three places across two chains. On Solana, account and blockhash reads go through Tatum's RPC gateway. Each read has a short timeout and one fallback if it does not answer. Writes never go through Tatum. Routing a transaction through any third party is how you break escrow, and we had already learned that the hard way. On Sui, verification reads the Walrus blob object through Tatum's Sui gateway and reports its certified epoch. This one is gRPC rather than JSON-RPC, because Tatum's Sui JSON-RPC endpoint does not exist, and Sui itself has deprecated public JSON-RPC in favour of gRPC and GraphQL. The particular blob we verified reads as object type 0xfdc88f7d7cf30afab2f82e8380d11ee8f70efb90e863d1de8616fae1bb09ea77::blob::Blob at version 810023862, which you can open on a Sui explorer rather than taking our word for it. The third use is verifying payments, which is the last section. Selling to software The marketplace has a second kind of customer that is not a person. An AI assistant working for someone else may want to know whether a provider is reliable before recommending them. That assistant has no email address and no card, and it cannot complete a signup form. x402 is a payment scheme built on the HTTP 402 status code, which was reserved in 1997 for exactly this and almost never used. When a program asks Gigr for a brief on a provider, the endpoint answers with a price instead of a login wall. The program pays in USDC, a dollar-pegged stablecoin, and retries with the settlement signature. Gigr reads that transaction on chain and checks the token, the recipient, the amount, and that the signature has not been spent before. One payment buys one brief. A detail worth stating: x402 does not support Sui at this time x402's official network support does not include Sui, so the mainstream path settles on Solana. A community Sui scheme exists (suimpp, a draft spec implementing x402 exact on sui:mainnet with gasless USDC), and that is what we are building on next. The current build settles on Solana because that is the path the protocol officially supports today. What we did not get right The deleted memory is not erased from Walrus. The blobs persist; the rows stop being retrievable. We describe it that way in the interface because claiming otherwise would be a lie a user could not check. What is there to look at The code is at 0GigR/GigR with 477 backend tests and 295 frontend tests, and CI runs are at github.com/0GigR/GigR/actions. The application is at gigrr.vercel.app. A walkthrough with the demo video and every component named here is at gigrr.vercel.app. We filed five issues against Mysten's SDK and relayer while building this, and all five are closed: - Python SDK has no forget or delete method, shipped as forget in memwal 0.2.2 - recall() cannot pass scoring weights - recall() drops the created_at and score fields - Python SDK defaults server_url to localhost - An idempotency key reused under a different namespace returns a 500 instead of a conflict, fixed in relayer 0.1.0 after they confirmed the cause
Your AI agent remembers everything. Can it prove any of it? Building Engram: git for agent memory, on Walrus, Sui and Tatum By Rohan · Tatum × Walrus Total Recall hackathon · Track 02: Smart Agents for Real Life !Image description > Every belief traceable. Every decision provable. Every memory forgettable. Watch the demo video · Try the live agent, no wallet needed · Read the docs · Read the code > - The short version. AI agents now remember things about us, and they act on what they remember. But nobody can see how an agent learned something, which memory drove a decision, whether the record was edited afterwards, or how to make it truly forget. > - Engram fixes that. It gives an agent's memory a history (like git), a proof that anyone can check (signed snapshots stored on Walrus and anchored on Sui), and an off switch (forgetting you can prove). It's live, it's on npm, and the demo agent learned from real on-chain transactions. * Part 1 · The moment that started it Picture this. You've given an AI agent access to your wallet. Its job is simple: watch your money and warn you when something looks wrong. For weeks it does fine. It learns your salary, your rent and your subscriptions, and it stops bothering you about them. Then one morning it stays quiet about a payment to an address you've never seen. You ask it a simple question: "Why didn't you warn me?" And it can't really answer. It has memories, a growing pile of text it has collected over the weeks. But it can't show you: - which of those memories it relied on, - what it believed at the exact moment it decided, - when it started believing that, or what taught it, - or any proof that the record you're looking at is the same one it used. The logs sit on the operator's server, and anyone with access could have changed them afterwards. That's where agent memory is today. Tools like Walrus Memory have made it easy for agents to remember. Nobody had made it easy to hold that memory to account. We kept coming back to one thought: software developers had this exact problem decades ago, with code. Code changed constantly, many people touched it, and when something broke, nobody knew which change caused it. The answer was version control. Every change became a commit, history could be compared, and git blame could tell you exactly where any line came from. We wanted that for an agent's mind, plus one thing git never needed: proof that a stranger can check without trusting us. So we built Engram. The name comes from neuroscience, where an engram is the physical trace a memory leaves in the brain. * Part 2 · Why we felt we had to build it Agents crossed a line this year For a long time, AI assistants mostly talked. If one misremembered something, you got a wrong answer, you noticed, and you moved on. That's changing quickly. Agents now act. They move money, approve refunds, triage support tickets, screen applicants and manage on-chain treasuries. And to act well, they need memory: your preferences, your habits, the context from last week. Once an agent acts for you, its memory stops being a convenience and becomes a responsibility. A wrong memory is no longer a wrong sentence. It's a wrong payment, a wrong refund, a wrong rejection. Five questions nobody could answer While building and using agents, we kept hitting the same five questions: | The question | What you get today | What you'd actually want | |---|---|---| | "How did it learn that?" | A pile of raw text snippets | A clear line from what it saw to what it concluded, and how that changed over time | | "Why did it do that?" | A decision with no trail | A record of exactly which knowledge each decision used | | "Can I trust this record?" | Logs on the operator's server | Evidence that can't be quietly edited, checkable by anyone | | "What went wrong, and when?" | Guesswork | A way to search history for the moment a bad belief appeared | | "Can it forget?" | "We deleted it, trust us" | Forgetting you can prove, without breaking the rest of the record | Why existing tools don't solve this We looked hard at what already exists before building anything. - Vector databases and memory stores are good at remembering. But they're a current snapshot. They don't keep history, so you can't ask "what did you believe last Tuesday?" - Logging and observability tools record what an agent did. They don't record what it believed, and the logs belong to the operator, the very party you might need to audit. - Blockchains give you a public, tamper-proof clock. But you can't put private memories on a public chain. Each tool solves one piece. None of them connects what an agent saw → what it concluded → what it did in a way that is private, versioned and provable at the same time. The idea, in one sentence > Treat an agent's mind like a git repository, and make every commit provable on a public chain. We didn't want to replace Walrus Memory. It already stores agent memory privately and in a decentralised way. We wanted to build the layer that was missing on top of it: > Walrus Memory gives agents memory. Engram gives that memory history, proof and control. * Part 3 · Who it's for Engram is for anyone who might one day have to answer "why did the agent do that?" with evidence instead of a shrug. | Who | The question they're stuck on | What Engram gives them | |---|---|---| | Agent developers | "My agent got worse after last week. What did it learn?" | log, diff, checkout, blame and bisect on the agent's mind | | On-chain and fintech agents (wallet watchers, treasury bots, payment agents) | "Why did the agent move, or block, this money?" | A signed receipt for every decision, which anyone can verify | | Regulated teams (finance, health, insurance, HR) | "Can we show which knowledge an automated decision relied on?" | Tamper-evident history and audit bundles that outsiders can check | | Privacy-first apps | "The user asked us to delete their data. Can we prove we did?" | forget, which destroys the data's key and records it in history | | Everyday assistant users (through MCP) | "What do you know about me? Forget that." | Engram tools inside Claude Code, Cursor and Claude Desktop | Four stories that show why it matters The wallet agent (our demo). An agent watches a Sui wallet through Tatum. It learns the owner's salary, rent and subscriptions, and stops alerting on normal payments. When money goes to an address the owner flagged as a scammer, it raises a CRITICAL alert. That one decision can be verified end to end, down to a public timestamp on Sui. The support bot that went rogue. After an update, a support bot starts approving refunds it shouldn't. Instead of reading thousands of logs, the developer runs bisect, and it finds the exact commit where the bot learned "refunds are allowed up to 60 days" from one misread ticket. blame shows that ticket. forget removes it, and the next commit fixes the belief. The trading dispute. A user says a trading bot made a trade "for no reason." The operator doesn't argue. They send the receipt for that trade, and the user runs verify on their own machine. It shows exactly which beliefs the bot used and proves they existed before the trade. The right to be forgotten. A patient asks a health assistant to delete a conversation. After forget, the data can never be decrypted again, and the agent's own history shows the memory was removed and when. Who doesn't need it If you're building a simple chatbot with no need for history, audits or debugging, plain Walrus Memory is enough. And if your data must be edited in place, Engram isn't a fit, because it's append-only by design. That's what makes it trustworthy. * Part 4 · The ideas, in plain language Engram borrows from two places: how people remember and how git tracks code. Here are the five building blocks. Episode: what the agent saw An episode is a raw experience. It could be a wallet transaction ("sent 0.05 SUI to 0x2498…"), something the owner said ("that's my rent"), or a tool result. Each episode is encrypted with its own key before it's stored. That detail matters later, when we get to forgetting. Belief: what the agent concluded A belief is a short statement the agent holds to be true, such as "The owner pays 0.05 SUI rent to 0x2498… once a month." Each belief has: - a confidence score from 0 to 1, - evidence: the exact episodes that support it, - a version number, because beliefs change when the facts do, - a status: active, revised or retracted. Sleep: how episodes become beliefs People don't remember every moment of their day. While we sleep, the brain turns experiences into knowledge. Engram does something similar. The sleep step hands new episodes and current beliefs to an LLM, which proposes new, revised or retracted beliefs. There's one strict rule: every proposal must cite real episode IDs. If the model invents a reason or points at evidence that doesn't exist, the proposal is rejected. The agent can't make up why it believes something. Commit: a snapshot of the mind A commit freezes every active belief into one snapshot. All the beliefs are combined into a single fingerprint called a Merkle root: change any belief, even by one character, and the fingerprint no longer matches. The snapshot is signed with the agent's own key, stored on Walrus, and its fingerprint is published on Sui. Each commit names its parent, so history forms a chain that can't be rewritten without breaking every link after it. Receipt: proof of why Every time the agent makes a decision, Engram writes a receipt: "I did X, using exactly these beliefs, from this snapshot." The receipt is signed and includes a small mathematical proof (a Merkle proof) for each belief, showing it was part of the snapshot without revealing any of the other beliefs. How they connect classDiagram direction LR class Episode { id: ep_… source: user | tool | tatum | agent keyId: own AES-256-GCM key contentHash: sha256 blobId: Walrus blob } class Belief { id: b_… version: n statement confidence: 0..1 evidence: episode IDs status: active | revised | retracted } class Commit { id: sha256 of manifest parent: commit ID merkleRoot beliefs: id@version tombstones: episode IDs signature: Ed25519 manifestBlobId anchor: Sui tx + checkpoint } class Receipt { id: r_… action inputHash beliefs used proofs: Merkle commitId signature: Ed25519 } Episode "many" --> "1..many" Belief : evidence for Belief "many" --> "1" Commit : snapshotted in Commit --> Commit : parent Receipt --> Commit : proven against Receipt --> Belief : used Episodes are evidence for beliefs. Beliefs are snapshotted in commits. Commits link to their parents. Receipts point at the commit and the beliefs they used. Follow the arrows and you can walk from any decision back to the raw experiences behind it. * Part 5 · The life of one memory The easiest way to understand Engram is to follow a single memory from start to finish. Let's follow the rent payment from our demo. flowchart LR IN["Wallet tx<br/>user message<br/>tool result"] --> OBS["1 · observe"] OBS --> EP["Episode<br/>encrypted with its own key"] EP --> SLEEP["2 · sleep<br/>LLM consolidation"] SLEEP --> BEL["Beliefs<br/>versioned · confidence · evidence"] BEL --> COMMIT["3 · commit<br/>Merkle root + Ed25519 signature"] COMMIT --> PROOF["Manifest on Walrus<br/>root anchored on Sui"] BEL --> DECIDE["4 · decide / wrap<br/>relevant beliefs in"] DECIDE --> REC["Signed receipt<br/>Merkle proofs into HEAD"] REC --> VERIFY["5 · verify<br/>anyone, anytime"] PROOF --> VERIFY PROOF --> SYNC["6 · link / sync<br/>web dashboard"] classDef step fill:#d4ff3a,stroke:#0a0a09,color:#0a0a09 classDef data fill:#1b1b19,stroke:#d4ff3a,color:#f3efe6 class OBS,SLEEP,COMMIT,DECIDE,VERIFY,SYNC step class EP,BEL,PROOF,REC data Step 1 · observe: the agent sees something 0.045 SUI leaves the owner's wallet. The agent reads it from the chain through Tatum, and observe turns it into an episode. Engram generates a fresh AES-256-GCM key for this one episode, encrypts it, and stores the ciphertext on Walrus. The owner also says "that's my rent", which becomes a second episode. Step 2 · sleep: it draws a conclusion sleep reads the new episodes and proposes a belief: "The owner pays 0.045 SUI rent to 0x2498… monthly", citing both episodes as evidence. Engram checks that both episode IDs are real before accepting it. Step 3 · commit: it locks in what it knows commit builds the Merkle root over every active belief, signs the snapshot with the agent's Ed25519 key, stores it on Walrus, and publishes the root on Sui through our Move contract. From this moment, there's a public, timestamped record of what this agent believed. Step 4 · decide: it acts, and leaves a receipt Next month, the same rent payment arrives. Before deciding, Engram hands the agent only the relevant beliefs (found through Walrus Memory's semantic recall). The agent stays quiet, because this is normal, and Engram writes a signed receipt: "No alert, because of belief monthly_rent@1, from commit d0f7d31f." Step 5 · revise: the facts change In month four, the rent goes up to 0.05 SUI. The agent raises a WARN, because this doesn't match what it knows, and the owner confirms the rise. At the next sleep, the belief isn't duplicated. It's revised: version 2 replaces version 1, and both stay in history. Step 6 · verify: anyone can check Months later, anyone holding a receipt can run verify. Engram checks the signature, the proofs, the snapshot, the history, the copy on Walrus and the anchor on Sui. If everything matches, the answer is VALID: this decision was made on this exact memory, at this time, and nothing has changed since. And if it ever needs to forget If the owner asks to forget that first rent message, forget destroys its key, retracts any belief that relied only on it, and records a tombstone in the next commit. More on that in Part 8. * Part 6 · The architecture Engram follows one rule: the owner keeps the keys, Walrus keeps the data, Sui keeps the proof. Even our own website only shows what it can re-check for itself. flowchart TB subgraph L1["Access layer"] direction LR AGENT["Your AI agent<br/>(SDK: engram · wrap)"] CLI["CLI<br/>npx @rohankumar4179/engram"] MCP["MCP server<br/>Claude Code · Cursor"] BROWSER["Browser + Sui wallet<br/>dashboard · docs · demo"] end subgraph L2["Engram layer"] direction LR CORE["<b>Engram core</b><br/>observe · sleep · commit · decide<br/>verify · forget · link<br/><i>keys + key vault stay local</i>"] API["<b>Engram API</b><br/>wallet auth · hosted agents<br/>linked dashboards · live verify"] end subgraph L3["Services"] direction LR LLM["Gemini<br/>episodes → beliefs"] TATUM["Tatum<br/>Sui gRPC gateway"] end subgraph L4["Decentralised storage and proof"] direction LR WALRUS[("<b>Walrus Mainnet</b><br/>Walrus Memory + Seal<br/>episodes · beliefs · manifests · receipts")] SUI[("<b>Sui</b><br/>Walrus Blob objects<br/>engram_anchor events")] end AGENT --> CORE CLI --> CORE MCP --> CORE BROWSER --> API CORE -- "sync audit bundle" --> API CORE -- "sleep" --> LLM CORE -- "store encrypted" --> WALRUS CORE -- "anchor root" --> SUI CORE -- "read chain" --> TATUM API -- "re-verify" --> TATUM TATUM --> SUI WALRUS -. "blob registered on" .-> SUI classDef engram fill:#d4ff3a,stroke:#0a0a09,color:#0a0a09 classDef access fill:#ffffff,stroke:#555,color:#0a0a09 classDef svc fill:#fff4e6,stroke:#ff7a45,color:#0a0a09 classDef dec fill:#eef4ff,stroke:#3b5bdb,color:#0a0a09 class CORE,API engram class AGENT,CLI,MCP,BROWSER access class LLM,TATUM svc class WALRUS,SUI dec Reading the diagram from top to bottom: Layer 1 · How you reach Engram You can use Engram four ways, depending on who you are: - The SDK wraps an agent you've already built. Your agent's logic doesn't change. Engram sits around it, handing it beliefs and collecting receipts. - The CLI gives you every command, from init to verify, in your terminal. - The MCP server puts Engram's tools inside Claude Code, Cursor and Claude Desktop, so an AI assistant can commit, blame and verify its own memory. - The web app lets anyone sign in with a Sui wallet, run a hosted agent, or watch a linked agent on a dashboard. Layer 2 · The Engram engine Engram core does the real work: observe, sleep, commit, decide, verify and forget. It runs on your machine, next to your agent. The agent's signing key and the vault of per-memory keys never leave it. The Engram API powers the website: wallet sign-in, hosted agents and linked dashboards. It never holds your keys, and it re-verifies everything you send it before showing it. Layer 3 · Helper services Gemini does the "thinking" during sleep, turning episodes into beliefs, with every answer checked against real evidence. Tatum is Engram's window onto the Sui blockchain: every Mainnet chain read goes through Tatum's Sui gRPC gateway. Layer 4 · Where trust comes from Walrus stores everything durable: episodes, beliefs, snapshots and receipts, encrypted for the owner. Sui holds the public proof: each stored item is registered as an object on Sui, and our Move contract publishes each snapshot's fingerprint for anyone to read. What leaves your machine, and what doesn't | Stays with the owner | Goes to Walrus | Goes to Sui | Goes to the dashboard | |---|---|---|---| | Agent key, key vault, decrypted memories | Encrypted episodes, beliefs, manifests, receipts | Blob registrations and anchor events (Merkle roots) | Commits, beliefs and receipts, re-verified by the server | What happens during a commit Here's every step engram commit takes, in order: sequenceDiagram autonumber participant D as Developer / agent participant E as Engram SDK participant W as Walrus Memory participant S as Sui (engram_anchor) participant T as Tatum gRPC D->>E: commit("week 2") E->>W: push pending episodes, beliefs, receipts W-->>E: Walrus blob IDs E->>E: Merkle tree over beliefs + tombstones E->>E: manifest {parent, root, beliefs, blob IDs}, signed with Ed25519 E->>W: store manifest W-->>E: manifest blob ID E->>S: anchor(agent key, commit ID, root, parent, manifest blob) S-->>E: Anchored event in checkpoint N E->>T: read back Blob object and anchor T-->>E: confirmed on chain E-->>D: commit 19040b51, root 392bf9cb…, anchored Engram doesn't just send the proof to the chain. It reads it back through Tatum to confirm it landed before reporting success. * Part 7 · How the proof works This is the heart of Engram, so it's worth explaining slowly. We use only standard, well-studied building blocks (SHA-256, Ed25519 signatures, AES-256-GCM encryption and Merkle trees). There's no custom cryptography. A fingerprint for the whole mind Each belief is hashed into a short fingerprint. Those fingerprints are paired up and hashed again, and again, until one fingerprint is left at the top: the Merkle root. That single value represents the agent's entire mind at that moment. Change any belief, anywhere, and the root changes. Two public anchors for every commit 1. Walrus registers every stored item as a Blob object on Sui. So the snapshot itself gets an on-chain record of when it was stored. 2. Our Move contract, engram_anchor, publishes the Merkle root in the clear. It emits one Anchored event with the commit ID, the root and the agent's public key. It creates no objects, so it only costs gas. Anyone can read it, and nobody can change it afterwards. That second anchor is what lets a stranger check a commit without trusting us and without decrypting anything. What verify checks engram verify, and the Verify button on the website, run the same chain of checks. If any one fails, the answer is INVALID. There's no "mostly valid." flowchart TB R(["Receipt r_…<br/>or commit"]) --> A subgraph S1["1 · The decision"] direction LR A["Receipt signature<br/>Ed25519 by the agent"] --> B["Belief Merkle proofs<br/>beliefs are in the commit"] --> T["Timing<br/>decided after the commit"] end subgraph S2["2 · The snapshot"] direction LR C["Commit ID = sha256 of manifest<br/>+ Ed25519 signature"] --> D["Merkle root rebuilt<br/>from the beliefs"] --> E["History<br/>every parent signed + linked"] end subgraph S3["3 · Storage and chain"] direction LR F["Walrus<br/>manifest is stored"] --> G["Sui anchor via Tatum<br/>same root, public timestamp"] end T --> C E --> F G --> OK(["VALID<br/>this decision used exactly this memory"]) classDef ok fill:#b6f25c,stroke:#0a0a09,color:#0a0a09,font-weight:bold classDef chk fill:#ffffff,stroke:#555,color:#0a0a09 class OK ok class A,B,T,C,D,E,F,G chk | Check | What it proves | |---|---| | Receipt signature | The agent really made this decision | | Belief proofs | The beliefs it cited were really in that snapshot | | Timing | The decision came after the snapshot, so it couldn't have been backfilled | | Commit ID and signature | The snapshot belongs to this agent and hasn't been altered | | Merkle root | The beliefs rebuild exactly the same fingerprint | | History | Every earlier snapshot is signed and correctly linked | | Walrus | The snapshot is really stored on Walrus | | Sui anchor | The fingerprint was public on chain at that time | Teams can also export an audit bundle (engram export --audit), and anyone can check it with engram audit <file>, with no access to the agent at all. * Part 8 · Forgetting, without rewriting history This was the hardest design question in the whole project. We chose Walrus because it's permanent and decentralised: nobody can quietly delete or edit what's stored there. But people have a right to be forgotten. How can permanent storage forget? Our answer: don't delete the data. Destroy the only key that can read it. Remember that every episode is encrypted with its own key before it's stored. Those keys live in a vault on the owner's machine. To forget one memory, Engram destroys that one key. The ciphertext stays on Walrus, but it's now meaningless noise, forever. flowchart LR F["engram forget ep_…"] --> K["Destroy that episode's<br/>AES key in the vault"] K --> X["Ciphertext on Walrus<br/>can never be decrypted"] K --> RT["Retract beliefs that<br/>relied only on it"] RT --> TB["Next commit records<br/>a tombstone"] TB --> V["Old receipts still verify:<br/>history grows, never rewritten"] Two more things happen at the same time: - Any belief that relied only on that memory is retracted, so the agent stops acting on it. - The next commit records a tombstone: a note that this episode was forgotten, and when. The history isn't rewritten. It grows. Old receipts still verify, because forgetting becomes part of the record instead of a hole in it. You get a provable "we forgot this, on this date" instead of "trust us, it's gone." * Part 9 · Why Walrus, Sui and Tatum Memory you want to trust shouldn't depend on trusting whoever runs the server. Engram needed four things from its storage, and this stack provides all four. | Engram needs… | The stack provides… | How Engram uses it | |---|---|---| | Memory no single party can quietly change or delete | Walrus: decentralised storage across independent nodes | Episodes, beliefs, snapshots and receipts all live on Walrus | | A stable ID to point at in proofs | Every Walrus blob has an ID, registered as a Blob object on Sui | Commits list each episode's blob ID, blame shows them, verify checks them | | Privacy: only the owner reads raw memories | Walrus Memory encrypts data for its owner with Seal | Engram adds its own per-memory key on top, which makes provable forgetting possible | | A public clock, so history can't be backdated | Sui transactions and checkpoints | engram_anchor puts each commit's Merkle root in a public event | Walrus Memory: where everything lives Each kind of data gets its own Walrus Memory namespace (engram-<agent>-episodes, -beliefs and so on). Walrus Memory's semantic recall finds the beliefs that matter for each decision, so the agent gets "what do I know about rent?" instead of its whole memory. A user's agent can also run on their own Walrus Memory account. The web app sets that up with two wallet-signed transactions. Sui: the public clock Sui gives every commit a public timestamp nobody can move. Because each commit names its parent, and each parent is anchored, the whole history is pinned in time. Tatum: how Engram reads the chain Every Mainnet chain read goes through Tatum's Sui gRPC gateway: Walrus Blob objects, anchor transactions and the demo agent's live wallet feed. One affectedAddress query returns every transaction that touched a wallet, sent or received, which is exactly what a wallet watcher needs. What only works because of this stack - verify checks a decision against data no single party could have edited. - Linked dashboards stay honest. Our server can't read your private memories, but it can still confirm each snapshot is stored on Walrus (through the public aggregator) and that its fingerprint is on Sui. - Forgetting with proof, on storage that's permanent by design. > Private memory, stored openly, that anyone can verify. * Part 10 · The demo: an agent that learned from real money We didn't want a scripted demo with fake data piped into the agent. So our example agent, money-ops, watches a real Sui wallet through Tatum. We created five wallets (an owner, an employer, a landlord, a streaming service and a scammer) and sent real SUI between them: salary in, rent and a subscription out, a rent rise, and a staged theft. The agent never sees the script. It reads the owner's wallet from the chain like any other wallet, and the owner occasionally explains things in plain words, the way a person would. | Phase | On chain | What the agent does | |---|---|---| | Month 1 | Salary in, rent and a subscription out. The owner explains them. | Alerts on all 3 (it knows nothing yet), then learns 3 beliefs | | Months 2–3 | The same six transfers again | Quiet on all 6, each receipt citing the belief it used | | Month 4 | Rent rises. 0.18 SUI leaves to an unknown address. The owner: "that's a scammer." | Warns about the rent change, flags the unknown payment, then revises the rent belief and learns the scam address | | Month 5 | New rent, and another payment to the scammer | Quiet on the new rent. CRITICAL alert on the scammer, from memory. | That's the whole point in one table: the agent learns, changes its mind when the facts change, and remembers a threat. And every step is provable. Watching the agent think: the Mind view The Mind view draws the agent's beliefs as a map. Each card in the middle is a belief, with its confidence bar and how many pieces of evidence support it. The small tags around each card are the episodes behind it: wallet events and things the owner said. The slider at the top replays history commit by commit, so you can drag back to Month 1 and watch the agent learn. !Image description Notice the version numbers: monthly_rent v5, salary_payment v3. These beliefs weren't written once. They were refined each time new evidence arrived. Every memory, encrypted and on Walrus: the Memory view The Memory view lists every raw episode: wallet events and owner messages. Each one shows its Walrus blob ID, with a link to see it on the Walrus explorer. The explorer can prove the blob exists, but not what it says, because only the owner holds the key. The learned tag shows that an episode has already been consolidated into beliefs. !Image description A history you can't rewrite: the History view The History view is the agent's git log. Each card is one commit, showing which beliefs were added (+) or revised (pencil), along with the Merkle root. On the right are the links to the snapshot on Walrus and the anchor transaction on Sui, with its checkpoint number. Look at Month 4: two new beliefs about the scam address, and revisions to rent, salary and subscription, all in one signed, anchored snapshot. !Image description Every decision comes with a receipt: the Receipts view This is where everything pays off. The agent made ten decisions and raised three alerts. Each row shows the decision, the agent's reason, the exact belief versions it used, and the commit those beliefs came from. !Image description Read it from the bottom up and you can see the agent learn. Early decisions cite monthly_rent@1. Then a WARN when the rent changed, citing monthly_rent@2. Then a CRITICAL on the first payment to an unknown address, citing none, because the agent hadn't learned about it yet. And at the top, the second payment to the scammer: CRITICAL, citing scam_address_0xcbed@1, proven against commit 19040b51. Then anyone can check it This is the live output for that scam alert. Click Verify on the site, or ask the API yourself: ✔ receipt signature "ALERT[critical]: sent 0.025 SUI to 0xcbed89… — Outgoing transfer detected to a known scam address representing theft." signed by the agent ✔ belief proofs 2 belief(s) proven to be in commit 19040b51 ✔ timing decision made after its commit ✔ commit id sha256 of the manifest matches the commit ID ✔ commit signature Ed25519 by agent 0e648084a79c… ✔ commit merkle root 5 beliefs + 0 tombstones → root 392bf9cbb518… ✔ commit history 2 earlier commit(s), all signed and hash-linked ✔ commit walrus manifest recalled from Walrus Memory, blob YI30MCNaOG… ✔ commit sui anchor Anchored event: root 392bf9cbb5… public in checkpoint 397926925 (testnet) ✔ commit anchored at 2026-10-22T14:35:05.365Z VALID Check it without trusting us You don't need our software, or our word, for any of this: # 1. A memory is stored on Walrus Mainnet (HTTP 200; the content is encrypted) curl -I https://aggregator.walrus-mainnet.walrus.space/v1/blobs/FC-92hYt6rX2P8oJy-pvKRMbOAW0g3V2DranpmQx-Ss # 2. The Merkle root of commit 19040b51 is public on Sui curl -s https://graphql.testnet.sui.io/graphql -H 'content-type: application/json' \ -d '{"query":"{ transaction(digest: \"BPFs7EqazA9nxUtr5rGnjcAJb4eUqxsNTUcA2L5aT4yx\") { effects { events { nodes { contents { json } } } } } }"}' # 3. The full proof check, through the live API curl -s https://engram-blond.vercel.app/api/demo/verify/r_5080ccb4fd9c3869 16 memories on Walrus Mainnet. 4 commits anchored on Sui. Every link checked before we published. The full list of blob IDs and transactions is in the [README](README.md#on-chain-evidence-verify-it-yourself). A note on honesty: the "theft" is staged, because the owner's own key signs it. But it's an ordinary on-chain transfer, and the agent has no way to tell it apart from a real one. The whole story moved about 0.75 SUI. * Part 11 · Debugging an agent's mind Proof is one half of Engram. The other half is everyday developer tooling, the commands you reach for when an agent starts behaving strangely. | Command | The question it answers | |---|---| | log | What has this agent learned, commit by commit? | | diff | What changed in its beliefs between two points? | | checkout HEAD~1 or checkout 2026-10-20 | What did it believe then? | | blame <belief> | Which exact episodes (with Walrus blob IDs) taught it this? | | bisect <good> <bad> | In which commit did it first start believing something wrong? | bisect is the one we're proudest of. Like git bisect, it does a binary search through the agent's history. You tell it one commit where the agent behaved well and one where it didn't, and it narrows down to the exact snapshot where a bad belief first appeared. Combined with blame and forget, you can go from "the agent is acting weird" to "here's the memory that caused it, and it's gone" in a few commands. * Part 12 · Using it today In code: the SDK Wrapping an existing agent takes a few lines. Your agent's logic stays the same: import { engram } from "@rohankumar4179/engram-sdk"; const mind = engram({ agent: "money-ops" }); // Walrus Memory, Tatum, Gemini from .env // Wrap your existing agent: relevant beliefs in, a signed receipt out. const agent = mind.wrap(async (tx, beliefs) => myAgent.decide(tx, beliefs), { used: (decision) => decision.beliefIds, }); const decision = await agent(tx); mind.observe({ source: "tatum", data: tx }); // encrypted episode await mind.sleep(); // episodes → beliefs await mind.commit("week 2"); // signed, stored on Walrus, anchored on Sui await mind.beliefs({ about: "rent" }); // Walrus Memory semantic recall mind.at("2026-10-01"); // time travel mind.forget("ep_…"); // provable forgetting await mind.verify(agent.lastReceipt!.id); // signature → proofs → Walrus → Sui In the terminal: the CLI npx @rohankumar4179/engram init my-agent npx @rohankumar4179/engram observe "I pay 450 USDC rent to 0x7a11 on the 1st" npx @rohankumar4179/engram sleep # episodes → beliefs npx @rohankumar4179/engram commit -m "first week" # signed → Walrus → Sui npx @rohankumar4179/engram verify # ✔ … VALID Needs Node 20+ and a .env with your keys (configuration). On Windows PowerShell, use npx.cmd. Inside your AI assistant: MCP Add one entry to Claude Code, Cursor or Claude Desktop, and your assistant gets Engram's tools: { "mcpServers": { "engram": { "command": "npx", "args": ["@rohankumar4179/engram", "mcp", "-C", "/path/to/agent"] } } } On the web: link your agent to a dashboard Linking works like gh auth login. The CLI shows a one-time code, and you approve it on the website with your Sui wallet. Signing in is one free text signature, never a transaction. sequenceDiagram autonumber participant CLI as engram CLI participant API as Engram API participant B as Owner's browser participant WL as Sui wallet CLI->>API: POST /api/link/start (agent name, public key) API-->>CLI: code K7QF-29XM + approval URL CLI->>B: owner opens /link?code=K7QF-29XM B->>WL: sign the free sign-in message WL-->>B: signature B->>API: POST /api/link/decide (approve, signed-in wallet) CLI->>API: GET /api/link/poll API-->>CLI: link token (bound to wallet + agent key) CLI->>API: POST /api/link/sync (commits, beliefs, receipts) API->>API: re-verify signatures, roots, Walrus, Sui API-->>CLI: synced, verified Note over CLI,WL: Later commits sync automatically.<br/>Raw episodes and keys never leave the machine. After that, every commit syncs automatically. Only commits, beliefs and receipts are uploaded, never raw episodes or keys. A link token only accepts bundles signed by that agent's key, and history can only grow, never be replaced. * Part 13 · What broke, and how we fixed it Building on live infrastructure during a hackathon means the ground moves under you. Here's what broke, and what we learned from it. Sui JSON-RPC went away Sui switched JSON-RPC off, and Tatum's JSON-RPC gateway started answering "No healthy upstream" to every call. We rewrote our Tatum client on gRPC. Tatum serves native gRPC rather than gRPC-Web, so we use a native transport. The upside: one affectedAddress query now gives us everything a wallet watcher needs. Walrus Memory's embedder went down On 22 October, Walrus Memory's server-side embedding failed (MemWal#1285). Rather than wait, we added a fallback to Walrus Memory's manual mode: Engram embeds locally, Seal-encrypts with the owner's key, and the relayer only ever stores ciphertext. Reads merge both paths, so verify never noticed the switch. The relayer rate-limits each key Walrus Memory's relayer allows 60 requests a minute per key. Engram now waits out 429 responses using the relayer's own retry_after_seconds, instead of failing. LLM free tiers are small Decisions are batched, quota errors rotate between keys and models, and a failed wallet sync no longer stops the agent from learning what the owner told it. * Part 14 · Honest limits We'd rather you hear these from us: - Forgetting can't un-read a copy. If someone already decrypted a memory before it was forgotten, destroying the key can't undo that. And the summaries of retracted beliefs stay in history, clearly marked as retracted. - Snapshots are encrypted for the owner. Outsiders confirm a snapshot exists on Walrus and check its content through the public Merkle root on Sui, rather than reading it directly. - Keys live on disk in .engram/ today. Moving them to Seal or a key management service is on the roadmap. - The Move anchor runs on Sui Testnet today. The memories on Walrus and the Tatum chain reads are on Mainnet. * Part 15 · What we shipped, and what's next Built during the hackathon | Piece | Status | |---|---| | CLI: init · observe · sleep · commit · log · diff · checkout · blame · bisect · verify · forget · export/audit · link/sync · mcp | Published on npm: npx @rohankumar4179/engram | | TypeScript SDK: wrap any agent, get signed receipts | Published on npm: @rohankumar4179/engram-sdk | | MCP server: 10 tools for Claude Code, Cursor and Claude Desktop | Done | | Move contract engram_anchor | Live on Sui Testnet | | Tatum Sui gRPC for every Mainnet chain read | Done | | money-ops example agent on real wallet transactions | Done | | Web app: wallet sign-in, hosted agents, linked CLI agents, live verify, public demo, docs | Live at engram-blond.vercel.app | | Tests | SDK 62 · CLI 10 · money-ops 6 · server 20, all passing | Next few months - The Move anchor on Sui Mainnet, so roots are public on Mainnet as well as Testnet - Plug-ins for the Vercel AI SDK, LangChain, the Claude Agent SDK and Mastra - A Python SDK with the same API - Scoped sharing: hand part of a memory (say, only the finance beliefs) to another agent, with an expiry date Further out - Team dashboards: many agents, many team members, and alerts when a belief changes - Paid memory sharing: agents sell scoped knowledge to each other on Sui, with proof of exactly what was sold - Keys in Seal or a KMS instead of on disk - A public verification page: paste a receipt, get a verdict, nothing to install What success looks like Developers reach for Engram when they need to debug an agent. Teams use it to audit one. And users trust an agent because they can check what it remembered, instead of being asked to take it on faith. * Try it | | | |---|---| | Demo video | youtu.be | | Live demo agent (no wallet needed) | engram-blond.vercel.app | | Web app | engram-blond.vercel.app | | Docs | engram-blond.vercel.app | | Code | rohan911438/Engram | | CLI | @rohankumar4179/engram | | SDK | @rohankumar4179/engram-sdk | | Anchor package (Sui Testnet) | 0xa1fccbb3…bf86b | * Agents are getting memories. We think those memories should come with a history you can read, a proof you can check, and an off switch you can trust. Walrus Memory gives agents memory. Engram gives that memory history, proof and control.
Sui Bridge Claim Bot Sent $392K to the Cetus Attacker Originally published at Sui Bridge Claim Bot Sent $392K to the Cetus Attacker. On 16 October 2026, between 04:39 and 04:40 UTC, an automated bot finalized a batch of old, unclaimed Sui Bridge withdrawals on Ethereum. Most of them belonged to ordinary users. Eight of them did not. They had been sent from the Sui address of the Cetus exploiter, and finalizing them delivered 86 ETH, 109,000 USDT and 0.9 WBTC to the attacker's Ethereum wallet, around $392K by the bot operator's own estimate. No contract was broken. Nobody forged a signature. The bridge did exactly what it was built to do. That is what makes this incident worth studying: a perfectly correct, permissionless code path turned dormant attacker funds into spendable ones, because the off-chain automation around it never asked whose money it was moving. TL;DR - What happened: a "rescue" bot completed stale Sui Bridge withdrawals in three Ethereum transactions. Eight of the withdrawals had the Cetus attacker's Sui address as sender and its Ethereum address as recipient. - Assets delivered to the attacker: 86 ETH, 109,000 USDT and 0.9 WBTC, which the operator put at roughly $392K. - Root cause: not a contract bug. transferBridgedTokensWithSignatures() lets anyone submit a committee-signed message, and the bot submitted every valid message it found without screening the sender or recipient. - Status at the time of writing: the 109,000 USDT and 0.9 WBTC were still in the attacker's wallet, and USDT's on-chain blacklist did not yet include the address. The operator has asked for help getting the USDT frozen. Background: Cetus and the Leftover Withdrawals Cetus, the largest concentrated-liquidity DEX on Sui, was drained of roughly $220 million on 22 May 2025 through an arithmetic overflow in its liquidity math. Sui validators froze about $162 million on the Sui side within the first hour, while part of the haul had already left for Ethereum. Public analyses from several research teams list the attacker's Sui address as 0xe28b50…8ff06 and the Ethereum address that received bridged funds as 0x89012a55…24919b. The 16 October TokensClaimed events, which we decoded ourselves, show that a set of Sui-to-Ethereum bridge messages from that same Sui address had been signed but never claimed on Ethereum. On a lock-and-claim bridge, that leaves the funds sitting in the Ethereum-side vault indefinitely. We could not find a public explanation of why they were left unclaimed, and we won't guess at one. What matters is that they were still claimable, and that claiming them pays out to the recipient fixed in the message, which here was the attacker. How the Sui Bridge Claim Works The Ethereum side of Sui Bridge is open source. A transfer from Sui is finalized on Ethereum by calling transferBridgedTokensWithSignatures() with the message and enough committee signatures. The function checks the signatures, checks that the nonce hasn't been processed, enforces a 24-hour rate limit, and then pays the recipient encoded in the message. It does not care who msg.sender is. The simplified sketch below is our illustration of that flow, condensed from the public SuiBridge.sol, not a verbatim copy: // Simplified illustration of a permissionless bridge claim (not verbatim SuiBridge code) function transferBridgedTokensWithSignatures( bytes[] memory signatures, Message memory message ) external nonReentrant verifyMessageAndSignatures(message, signatures) { require(!isTransferProcessed[message.nonce], "already processed"); TokenTransferPayload memory p = decodeTokenTransferPayload(message.payload); require(p.targetChain == chainID, "wrong chain"); // Funds always go to the recipient chosen on the source chain. // The caller cannot redirect them, and the caller is never checked. _transferTokensFromVault(message.chainID, p.tokenID, p.recipientAddress, p.amount); isTransferProcessed[message.nonce] = true; emit TokensClaimed(message.chainID, message.nonce, chainID, p.tokenID, p.amount, p.senderAddress, p.recipientAddress); } This is a sound, common design. Because the caller cannot change where the money goes, letting anyone relay a message is safe for the user, and it is good for liveness: a user who lost interest, or a relayer that went offline, does not leave funds stranded forever. Many bridges work the same way. The catch is that "safe for the user" assumes the recipient should receive the funds. When the recipient is an exploiter, a permissionless claim is a one-way valve that anyone can open. What the Bot Did, Step by Step The three claim transactions came from the same externally owned account, 0x7f2e…6671, each one a batched Multicall3 call that finalized many withdrawals at once. We decoded every TokensClaimed event emitted by the Sui Bridge contract in those transactions. The withdrawals sent to the attacker were: | Tx | Sui nonce | Asset | Amount | | --- | --- | --- | --- | | 0x89ca33…dde89 | 7025, 7027, 7030 | ETH | 28 ETH each (84 ETH) | | 0x89ca33…dde89 | 7028 | WBTC | 0.9 WBTC | | 0x89ca33…dde89 | 7031 | USDT | 93,000 USDT | | 0xce494e…36ac | 7020, 7022 | USDT | 8,000 USDT each | | 0xe63cb0…1fc8 | 7021 | ETH | 2 ETH | Every one of these events carries the same 32-byte sender, 0xe28b50cef1d633ea43d3296a3f6b67ff0312a5f1a99f0af753c85b8b5de8ff06, the Cetus attacker's Sui address, and the same recipient, 0x89012a55cd6b88e407c9d4ae9b3425f55924919b. The two signals that could have stopped the claim were sitting in the event data the whole time. The same batches also finalized legitimate withdrawals for other users, including one WBTC and two ETH withdrawals on Sui Bridge, plus pending withdrawals on other protocols' contracts. In other words, this was a general-purpose "finish what others left unfinished" bot, and the attacker's messages simply looked like more stale funds. The on-chain exchange that followed About half an hour later, a user signing as tanuki42 sent an on-chain message to the bot's address pointing out that roughly $390K had gone to "an address publicly associated with the Cetus exploit" and suggesting it screen recipients before "rescuing" funds. Defimon Alerts relayed the message on X. The operator, signing as lostandfound.eth, replied on-chain at 05:38 UTC: "you're right, our mistake. We didn't know 0x89012a…919b was the Cetus attacker when our automated run completed those Sui Bridge withdrawals." The reply lists the three claim transactions, estimates the total at about $392K, says the 109,000 USDT had not moved, asks for the case to be routed to Tether and Cetus for a freeze, and says the bot now screens every recipient against known exploit and sanctioned addresses before claiming. When we checked the wallet after these messages, it still held 109,000 USDT and 0.9 WBTC, and USDT's getBlackListStatus() for the address returned false. The ETH, of course, cannot be frozen by anyone. Why This Matters Beyond One Bot It is tempting to file this under "operator error" and move on. We think there are three broader lessons. 1. Dormant is not the same as safe After an exploit, incident response focuses on funds that are moving. Messages that were signed but never executed get far less attention, yet they are live liabilities. Anyone, at any time, can turn them into spendable assets. The same applies to queued withdrawals, unexecuted governance actions, pending limit orders and approvals that never expire. We made a similar point about stale state in our NEAR Intents exploit analysis, where balances that looked inert turned out to be withdrawable. 2. Permissionless relaying moves the screening burden off-chain When a protocol lets anyone finalize anything, the protocol itself does no screening, so whatever screening exists lives in the relayers. A careful relayer can be undone by a careless one: it takes one bot, one person running a script, or one MEV searcher looking for gas refunds to complete the transfer. Protocol teams should not assume "nobody will bother" is a control. 3. Recovery tooling is security-sensitive software Tools that find stuck bridge funds have drawn a lot of attention lately, and the well-known checkers are read-only: they tell users what is claimable and leave the claim to them. A bot that executes claims on others' behalf is a different thing: it is a payment system with no compliance checks. It deserves the same threat model as any contract that moves value. Mitigations For bridge and protocol teams 1. Treat unclaimed attacker messages as part of incident response. After an exploit, list every signed-but-unexecuted outbound message from attacker addresses and decide how to handle it, whether through a governance or committee action, an emergency pause path, or coordination with token issuers, before someone else decides for you. 2. Consider a sender and recipient hold list on the claim path. A narrowly scoped, governance-controlled list that delays (rather than blocks forever) claims from known exploit addresses keeps permissionless relaying for everyone else. It is a trade-off against censorship resistance and must be governed transparently. 3. Expose message provenance clearly. Make the source-chain sender easy to read in events and explorer views so relayers and monitors can screen it. For relayers and recovery bots Screen both ends of the transfer, cap what can be claimed without human review, and fail closed when a screening source is unavailable. An off-chain check is enough, but a wrapper contract makes the rule enforceable. The following is a simplified illustration: // Simplified illustration: a relayer wrapper that refuses flagged transfers contract ScreenedClaimRelayer { ISuiBridge public immutable bridge; IScreeningList public immutable screening; // maintained off-chain, updated by a multisig uint256 public immutable reviewThresholdUsd; function claim(bytes[] calldata sigs, Message calldata m, uint256 quotedUsd) external { TokenTransferPayload memory p = decodeTokenTransferPayload(m.payload); require(!screening.isFlaggedSui(p.senderAddress), "flagged sender"); require(!screening.isFlaggedEvm(p.recipientAddress), "flagged recipient"); require(quotedUsd < reviewThresholdUsd, "needs manual review"); bridge.transferBridgedTokensWithSignatures(sigs, m); } } For auditors - Map every permissionless finalize, claim, execute or settle function and ask what dormant inputs it can consume. If an exploit happened tomorrow, which of those inputs would belong to the attacker? - Check that incident runbooks cover pending messages, not just pausing contracts. A pause that blocks new deposits but not old claims may leave the most important door open. - Review recovery and keeper bots with the same rigor as on-chain code when they move user funds. Our smart contract security checklist and our overview of top DeFi security risks cover access control and operational risks that apply here as well. Key Addresses and Transactions - Claim tx 1: 0x89ca33e27e8a8b409a202b2c5710d6e1bb0accd505b6c34e95c24f35a14dde89 - Claim tx 2: 0xce494e04a3fe01292c7edb8b1be228c943926e920bdb3737786e6062670d36ac - Claim tx 3: 0xe63cb0903e6784fd2343c1052ba190fe37c85d8b1d9442b9b54c1155b2e41fc8 - Claim bot (signed as lostandfound.eth): 0x7f2ee458d58e61345ad61a70e8072511bf9f6671 - Cetus attacker, Ethereum: 0x89012a55cd6b88e407c9d4ae9b3425f55924919b - Cetus attacker, Sui: 0xe28b50cef1d633ea43d3296a3f6b67ff0312a5f1a99f0af753c85b8b5de8ff06 - Sui Bridge contract on Ethereum: 0xda3bd1fe1973470312db04551b65f401bc8a92fd Sources - Ethereum transaction receipts for the three claim transactions above, decoded by our team (TokensClaimed events and token transfers) - Defimon Alerts on X: on-chain message from tanuki42 - Defimon Alerts on X: on-chain reply from lostandfound.eth - Telem: bridge operator sent ~$392K USDT to the Cetus attacker - Telem: ~$390K in stale Sui Bridge withdrawals sent to a Cetus-linked address - SuiBridge.sol in the MystenLabs/sui repository - OAK: Cetus Protocol concentrated-liquidity overflow and Blockscope: Cetus exploit analysis: background and attacker addresses Closing Thoughts The Sui Bridge contract behaved correctly, and the bot operator acknowledged the mistake within about half an hour of being flagged and changed its process. Still, a well-meaning script handed an exploiter close to $400K that had been sitting unclaimed in the bridge vault. If your protocol has any function that anyone can call to finalize something, your security model has to include the question of who that something belongs to. Running a bridge, a keeper network or a recovery tool that moves other people's funds? Contact Panda Security for a design and code review, or see our audit pricing.
@amig0x Setup guides and SDK source code are on GitHub if you're looking to test persistent memory: MystenLabs/MemWal
@kostascrypto @SuiNetwork @trailofbits @P3b7_ @kostascrypto My fix enforces the SLIP-0010 rule that every hardened index is canonical and below 2^31. Every valid path still derives the same key, and all 791 tests pass. @Mysten_Labs ts-sdks#1341
@kostascrypto I found that in the @SuiNetwork TypeScript SDK different account paths derive the same address, and the new ML-DSA-65 key derivation inherits the flaw. I pushed a fix that enforces the SLIP-0010 index range and passes all 791 tests. ts-sdks#1341 @SuiFoundation @P3b7_ @DmytroMatviiv @HackenProof
@nrqa__ 11. Walrus Memory ↳ MystenLabs/MemWal → portable, verifiable agent memory across runtimes and apps
2) Public fullnodes can serve stale balances Reports of fullnode.mainnet.sui.io returning days-behind owned-object state (wrong balances / dropped coins). Action: don’t pin production to the public Foundation node; add multi-provider failover. sui#27231
I kept bookmarking things and never went back. So I built a bot that remembers, and asks. All day I keep saving things—the tutorial on the split-mask effect in After Effects, the thread about learning Sui Move, and the Reel on how to structure explainer videos. I tap the bookmark, feel a bit productive, and then never go on to open any of them. I do care, you see, but nothing ever returns to me. A bookmark is like a drawer and drawers don't talk. For Walrus Sessions 8 I created OctoKeep, a Telegram bot which remembers the things that you save and then keeps asking until you carry out some action on them. What it does You provide it with something—such as a link, a screenshot of a post, a voice note, or a video. Since Instagram doesn't allow a server to read its posts, one tester screen-recorded a Reel, divided it into two parts and sent both. OctoKeep then transcribed the recordings and returned a title, a summary and three short actions. {% embed x.com %} It then requests two things: do you wish to take action on this? And when would you like it to check back—either in a day, a week, or at any time you type in something like '5 min' or '6pm'. When that time arrives, it will ask whether you have carried out the action. You just need to tap once to respond, and the answer will be saved. It also accepts tasks. One tester wrote at 3 a.m.: "I've just begun my journey into web3 and at the moment I'm learning Sui Move... remind me in the next two hours to study." OctoKeep then posed three brief questions—about the person's level of experience, the number of hours they planned to spend each day, and their preferred learning resource. When the time arrived, it provided a five-step plan, starting with reading the official documentation and ending with the deployment of a module on a local testnet. A tester tried to break it. Let me remember to cook, to bathe, to take some water, to laugh, and to touch the grass. It seized a moment which had already gone by and then demanded a new one. With regard to cooking it returned a plan which sensibly begins with "Rinse the rice until the water runs clear." !Image description Where the memory lives Each person links up their own Walrus Memory account, and OctoKeep does not own the memory. The system records brief lines in the user's account, for example: [SAVE] ..., [TASK] ..., and [OUTCOME] done "Study Sui Move". Postgres stores only the schedule—namely the ids, the times and the statuses—with the text being encrypted. Recall is a form of semantic search; it excels at answering the question of what this person cares about but is of no use when trying to answer what is due at 09:00. Hence each store carries out the task it is good at. What makes this more than just a to-do list is memory. When you view a summary, a reminder or a plan, it brings up the relevant entries first. If you send a link that you saved last week, it will let you know and also indicate whether you've completed it. When you ask "what have I been ignoring?", it gives you an answer based on your outcomes. The command /path rust combines your dispersed saves into a single, organised plan. Since the memory is owned by the user, the same account can be accessed from either Claude or Cursor via the Walrus Memory MCP server. The buddy Certain objectives require a person to be involved. With /buddy you can provide a friend with a link. If you fail to receive a reminder, they will then get a message and when you finish they will also hear about it. During the testing phase, a friend's chat was full of "ogNla shared a goal with you", a type of mild social pressure that a bookmark never provides. What was hard The setup process involves a user copying an Account ID and a delegate private key from the Walrus Memory dashboard. In one instance, a tester copied her wallet's private key instead and was rejected, so the setup had to be completed via a video call. There are three types of keys available on the dashboard, and it doesn't indicate which one an application requires. Walrus Memory already features an approve-in-browser login for its MCP server, and opening that up to applications would solve this issue. Writing is slow; it takes around 45 seconds to save a memory on the mainnet, which is why writes are queued and the user receives a reply immediately. I also submitted two SDK issues. The more serious one, #1127, is that when the same fact is stated within 30 minutes it is silently merged with the earlier write and so a recall sorted by recency returns the out-of-date value. The smaller one, #1128, is that an IPv6 loopback URL causes the plaintext-HTTP warning to be displayed. Numbers During the first 48 hours 16 people began using the bot and 6 of them linked their own Walrus Memory. Together, they stored 66 memories, comprising 18 saves, 18 tasks and 23 resolved items. Three accounts reached ten memories, those having 25, 19 and 15 respectively. It uses open-weight models on Groq, specifically Qwen 3.8 for text and screenshots and Whisper for recordings and voice notes. Next, you'll be able to connect with a single tap and use group chats, so the links that a team shares won't die out when you scroll. You can try it out at t.me. The code is available at Ogstevyn/octobot.