Walrus Memory
The recommended default client. The relayer handles embeddings, Seal encryption, Walrus upload, and vector indexing.
How it works
- The SDK signs each request with your delegate key
- The relayer verifies delegate access
remember(text)takes the memory text and returns an accepted job whosejob_idyou pass towaitForRememberJob(), while the relayer encrypts, uploads, and indexes in the backgroundrecall({ query, limit })takes the searchqueryand an optionallimiton the number of matches, searches the client's memory space (owner address, namespace, and app ID), and returns decrypted matches
import { MemWal } from "@mysten-incubation/memwal";
const memwal = MemWal.create({
key: "<your-ed25519-private-key>",
accountId: "<your-memwal-account-id>",
serverUrl: "https://your-relayer-url.com",
namespace: "chatbot-prod",
});
Core methods
Source: sdk/usage/memwal.md// Store a memory
const job = await memwal.remember("User prefers dark mode and works in TypeScript.");
await memwal.waitForRememberJob(job.job_id);
// Recall relevant memories
const result = await memwal.recall({ query: "What do we know about this user?", limit: 5 });
// Extract and store facts from longer text
const analyzed = await memwal.analyze(
"I live in Hanoi, prefer dark mode, and usually work late at night."
);
console.log(analyzed.job_ids);
// Check relayer health
await memwal.health();
Restore
Rebuild missing indexed entries for one namespace. restore() takes the namespace as its first argument and an optional limit as its second, the maximum number of blobs to inspect in that call (default 10), as in restore("chatbot-prod", 10), and returns a result object. Incremental, namespace-scoped, and meant to
repair PostgreSQL vector state from Walrus-backed memory.
const result = await memwal.restore("chatbot-prod", 10);
Lower-level methods
Use these when you already have a vector or encrypted payload:
rememberManual({ encryptedData, vector, namespace? })recallManual({ vector, limit?, namespace? })embed(text)
What analyze() returns
The relayer extracts facts synchronously and returns one job_id per fact, then embeds, encrypts, uploads, and indexes each fact in the background. The analyze() result contains:
job_ids: one polling ID per extracted factfacts: each entry hastext(the extracted fact),id(same value asjob_id), andjob_idfact_count: the number of accepted factsstatus: usuallypendingowner: the owner address
To wait until every extracted fact is stored, use analyzeAndWait(text, namespace?, opts?).
Read recall results
The recall result holds its matches in result.results. Each match carries the decrypted text and a distance, where a smaller number means a closer match:
for (const memory of result.results) {
console.log(memory.distance.toFixed(3), memory.text);
}
recall returns up to limit results, defaulting to 10, and gives no signal when it drops extra matches. Treat a result count equal to limit as a sign that more matches might exist.
Restore limit and pagination
The limit argument must be a positive integer. Otherwise, restore() throws a TypeError. Restore inspects your onchain blobs newest-first and has no pagination cursor. If you repeat a call at the same limit, it re-inspects the same newest blobs and returns nothing new. To rebuild a large namespace, set limit high enough to cover every blob in the namespace in a single call. A restored count that stops increasing across reruns is not proof that every blob is covered. You can safely run restore more than once, because it skips blobs the relayer already indexed.