Walrus Memory
The recommended default client. The relayer handles embeddings, Seal encryption, Walrus upload, and vector indexing. The SDK only signs requests and sends text.
How does the client work?
- The SDK signs each request with your delegate key (Ed25519 through PyNaCl)
- The relayer verifies delegate access
rememberreturns an accepted job while the relayer encrypts, uploads, and indexes in the backgroundrecallsearches by namespace and returns decrypted matches
from memwal import MemWal, RecallParams
memwal = MemWal.create(
key="<your-ed25519-private-key>",
account_id="<your-memwal-account-id>",
env="prod", # or server_url="https://your-relayer-url.com"
namespace="chatbot-prod",
)
MemWalSync.create(...) takes the same arguments for synchronous code.
How to store, recall, and query memories
Source: python-sdk/usage/memwal.md# Store a memory (async-accept; poll to completion)
done = await memwal.remember_and_wait("User prefers dark mode and works in Python.")
print(done.blob_id)
# Recall relevant memories
result = await memwal.recall(RecallParams(query="What do we know about this user?", limit=5))
for memory in result.results:
print(memory.text, memory.distance)
# Extract and store facts from longer text
analyzed = await memwal.analyze(
"I live in Hanoi, prefer dark mode, and usually work late at night."
)
print(analyzed.job_ids)
# Ask a question answered using your memories
answer = await memwal.ask("Where does this user live?")
print(answer.answer, answer.memories_used)
# Check relayer health (no auth)
await memwal.health()
Every memory method accepts an optional namespace= override that wins over the client default for that call.
How to restore missing indexed entries
Rebuild missing indexed entries for one namespace from Walrus. Incremental and namespace-scoped, meant to repair PostgreSQL vector state from Walrus-backed memory.
Source: python-sdk/usage/memwal.mdresult = await memwal.restore("chatbot-prod", limit=10)
print(result.restored, result.skipped, result.total)
Lower-level methods
Use these when you already have a vector or Seal-encrypted bytes. See Manual methods:
remember_manual(RememberManualOptions(encrypted_data=..., vector=..., namespace=...))recall_manual(RecallManualOptions(vector=..., limit=..., namespace=...))embed(text), embedding vector only, no storageget_public_key_hex(), the delegate public key
What errors does the SDK raise?
| Exception | Raised when |
|---|---|
MemWalError | Base class for all SDK errors (also raised on a failed health()) |
MemWalRememberJobNotFound | A polled job_id is unknown or not owned by the caller |
MemWalRememberJobFailed | An async remember job reached terminal status=failed |
MemWalRememberJobTimeout | A polling loop exceeded its timeout_ms budget |
MemWalRateLimited | A bulk wait could not read any job status because every read, including one confirming read at the end, was rate-limited (.job_ids, .retry_after). The writes might or might not have landed |
Transient statuses (connection drop, 429, 5xx) are retried inside the polling loops rather than surfaced. The one exception: if no bulk status read gets through before the deadline, wait_for_remember_jobs makes one confirming read and raises MemWalRateLimited when that is rate-limited too. Status reads count against the same delegate-key budget as writes.
What does remember return?
remember returns a RememberAcceptedResult with 2 fields, job_id and status, as soon as the relayer accepts the request. A background worker then runs the Walrus upload and onchain commit, so the accepted result has no blob_id.
To check a job once without polling, call get_remember_status with the job_id. It returns the job state: pending, running, uploaded, done, failed, or not_found.
Remember with or without waiting
remember returns a RememberAcceptedResult (job_id, status) as soon as the relayer accepts the request. The Walrus upload and onchain commit continue in a background worker, so the memory is not searchable yet. To finish the write, choose one of these options:
- Call
remember_and_waitto submit and poll to completion in one call. The result includes theblob_id. - Pass the
job_idfromremembertowait_for_remember_joblater. It polls until the memory is searchable. - Call
get_remember_status(job_id)to read the job state once without polling.
Polling starts immediately, then grows 1.5× toward a 5s cap with ±25% jitter.