Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
77a006b
Feat: WALM-55 — extract.v6 timestamp injection (server)
hungtranphamminh May 28, 2026
8b2bf4c
Feat: WALM-55 — bench harness passes per-turn timestamps to /api/analyze
hungtranphamminh May 28, 2026
65bbcfc
chore: strip ticket-id prefixes from code comments
hungtranphamminh May 29, 2026
9d15a83
feat(sdk-ts): plumb occurredAt through analyze() / analyzeAndWait()
hungtranphamminh May 29, 2026
03500a0
feat(sdk-py): plumb occurred_at through analyze() / analyze_and_wait()
hungtranphamminh May 29, 2026
a17e44e
feat(openclaw): timestamp auto-captured turns with new Date()
hungtranphamminh May 29, 2026
c61e054
feat(openclaw): accept optional occurredAt on memory_store tool
hungtranphamminh May 29, 2026
0b6d86f
docs: rename MemWal to Walrus Memory in prose text
jessiemongeon1 May 29, 2026
aad7b3c
docs: revert changelog files from MemWal rename
jessiemongeon1 May 29, 2026
49493a2
docs: align messaging with portable agent memory positioning
jessiemongeon1 May 29, 2026
6fc2d6a
chore(release): patch-bump SDK + openclaw + python-sdk for occurred_at
hungtranphamminh Jun 1, 2026
da3014f
fix(server): classify Sui object-lock/equivocation distinctly, stop b…
jasong-03 Jun 1, 2026
467a3f5
fix(sidecar): mirror object-lock/equivocation detection in metrics cl…
jasong-03 Jun 1, 2026
a06230e
fix(server): map remaining transient upstream failures to 503
hungtranphamminh Jun 1, 2026
5f4a1da
fix(docs): correct occurredAt semantics + Python docstring
hungtranphamminh Jun 1, 2026
b07d646
docs(server): correct extractor transient comment
Jun 1, 2026
a273e50
Merge pull request #202 from MystenLabs/feat/WALM-55-timestamp-injection
ducnmm Jun 1, 2026
ef72c59
fix(server): require lock-specific anchor for object-lock classification
jasong-03 Jun 1, 2026
f1a70d9
Merge pull request #212 from MystenLabs/feature/walm-walrus-object-lo…
ducnmm Jun 1, 2026
dd43f15
Merge pull request #208 from jessiemongeon1/docs/rename-memwal-to-wal…
daniellam258 Jun 1, 2026
df2fd69
Add docs.memwal.ai root redirect
Jun 2, 2026
f4ce351
Fix Walrus upload concurrency
Jun 2, 2026
c7ac5dd
Revert docs root redirect
Jun 2, 2026
04514b6
Improve Walrus upload recovery
Jun 2, 2026
ca9fad7
Merge pull request #215 from MystenLabs/codex/docs-memwal-root-redirect
ducnmm Jun 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .changeset/walm-55-occurred-at-openclaw.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
"@mysten-incubation/oc-memwal": patch
---

Wire temporal anchoring through the agent-side memory tools.

### Added

- `memory_store` tool now accepts an optional `occurredAt` argument (RFC-3339 / ISO-8601 string) so agents can anchor recounted past events to the date they actually occurred. Description tells the LLM to omit it when unknown rather than guess.

### Changed

- Auto-capture hook (`agent_end`) now passes `new Date()` as `occurredAt` to `analyze()`. Every captured conversation now gets temporal anchoring automatically — the server extractor resolves in-turn relative references ("yesterday", "last Friday") into absolute dates inside the stored fact text. Facts captured by this version now carry resolved dates.
- SDK dependency bumped from published `^0.0.2` to `workspace:*` to consume the new `AnalyzeOptions` signature.
11 changes: 11 additions & 0 deletions .changeset/walm-55-occurred-at-sdk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@mysten-incubation/memwal": patch
---

Add optional `occurredAt` to `analyze()` and `analyzeAndWait()` for temporal anchoring of extracted facts.

- New `AnalyzeOptions` overload: `analyze(text, { namespace, occurredAt })` accepts `Date` or RFC-3339 string. The legacy `analyze(text, namespace?)` signature still works unchanged.
- When `occurredAt` is supplied, the server resolves in-turn relative references ("last Friday", "yesterday") into absolute dates inside the extracted fact text before embedding and encryption.
- Wire format is RFC-3339 UTC with millisecond precision (e.g. `"2023-05-25T17:50:00.000Z"`).
- Invalid `Date` instances (constructed from malformed input) now throw a diagnostic `TypeError` from the SDK rather than an opaque `RangeError` from `toISOString()`.
- Field is omitted from the request body when not supplied — existing callers see byte-identical wire payloads.
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# Walrus Memory

Privacy-first AI memory layer for storing encrypted memories on Walrus and
retrieving them with semantic search.
Portable agent memory — take your agent's memory anywhere.

Walrus Memory enables AI agents to operate reliably across apps and sessions,
without losing context. Portable, verifiable, and fully controlled by you, it's
the memory layer that lets agents handle complex workflows and coordinate using
data they can trust.

> Walrus Memory is currently in beta and actively evolving. While fully usable today, we continue to refine the developer experience and operational guidance. We welcome feedback from early builders as we continue to improve the product.

Expand Down Expand Up @@ -96,7 +100,7 @@ For the full step-by-step setup guide, see:

## OpenClaw / NemoClaw Plugin

[`@mysten-incubation/oc-memwal`](packages/openclaw-memory-memwal) — a memory plugin for [OpenClaw](https://openclaw.ai) agents. It gives OpenClaw persistent, encrypted memory via Walrus Memory with automatic recall and capture hooks.
[`@mysten-incubation/oc-memwal`](packages/openclaw-memory-memwal) — a memory plugin for [OpenClaw](https://openclaw.ai) agents. It gives OpenClaw agents portable, verifiable memory through Walrus Memory with automatic recall and capture hooks.

```bash
openclaw plugins install @mysten-incubation/oc-memwal
Expand Down
24 changes: 12 additions & 12 deletions SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
name: memwal
version: 0.0.1
description: |
Walrus Memory SDK for privacy-first AI memory on Sui blockchain with Walrus.
Walrus Memory SDK — portable agent memory that works across apps, sessions, and workflows.

Use when users say:
- "add memory to my app"
- "store encrypted memories"
- "portable agent memory"
- "integrate Walrus Memory"
- "AI agent memory"
- "persistent memory SDK"
- "memory across agents"
- "Walrus memory storage"
- "setup Walrus Memory"
- "recall memories"
Expand All @@ -19,30 +19,30 @@ keywords:
- walrus memory
- memory sdk
- ai memory
- encrypted memory
- portable memory
- walrus storage
- sui blockchain
- delegate key
- semantic search
- vercel ai sdk
---

# Walrus Memory — Privacy-First AI Memory SDK
# Walrus Memory — Portable Agent Memory

Walrus Memory is a TypeScript SDK for persistent, encrypted AI memory. It stores memories on Walrus (decentralized storage), encrypts them with SEAL, enforces ownership onchain via Sui smart contracts, and retrieves them with semantic (vector) search. Memories are scoped by `owner + namespace` — each namespace is an isolated memory space.
Walrus Memory enables AI agents to operate reliably across apps and sessions, without losing context. It stores memories on Walrus (decentralized storage), encrypts them with SEAL, enforces ownership onchain via Sui smart contracts, and retrieves them with semantic (vector) search. Memory is portable by design — not tied to a single runtime or provider — and scoped by `owner + namespace` for isolation and coordination.

---

## When to Use

Use Walrus Memory when your app or agent needs:

- **Persistent memory** across sessions, devices, or restarts
- **Encrypted storage** — end-to-end encryption, only the owner and authorized delegates can decrypt
- **Portable memory** — persists outside prompts and context windows, moves across agents, apps, and workflows
- **Full owner control** — programmable permissions and explicit ownership define how memory is shared and accessed
- **Agent coordination** — shared memory spaces help agents coordinate across long-running and multi-step workflows
- **Semantic recall** — retrieve memories by meaning, not just keywords
- **Decentralized storage** — no single point of failure, stored on Walrus
- **Onchain ownership** — cryptographically enforced access control on Sui
- **Cross-app memory** — share memory between apps via delegate keys
- **Verifiable integrity** — memory integrity can be independently verified without centralized trust
- **Cross-app memory** — not tied to a single runtime or provider, share memory between apps via delegate keys

---

Expand Down Expand Up @@ -146,7 +146,7 @@ const stored = await memwal.waitForRememberJob(accepted.job_id, {

## API Surface

### MemWal Methods
### Walrus Memory Methods

| Method | Description | Returns |
|---|---|---|
Expand Down
2 changes: 2 additions & 0 deletions apps/app/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ VITE_MEMWAL_SERVER_URL=https://relayer.dev.memwal.ai

# Docs URL (separate deployment)
VITE_DOCS_URL=http://localhost:5174
VITE_TERMS_OF_SERVICE_URL=https://docs.wal.app/docs/legal/walrus_general_tos
VITE_PRIVACY_POLICY_URL=https://docs.wal.app/docs/legal/privacy

# Demo app links (comma-separated, format: Label|URL)
# Example: VITE_DEMO_URLS=Chat Demo|https://chat.example.com,Agent Demo|https://agent.example.com
Expand Down
4 changes: 4 additions & 0 deletions apps/app/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ export const config = {
.split(',').map(s => s.trim()).filter(Boolean) as string[],
sidecarUrl: import.meta.env.VITE_SIDECAR_URL as string || 'http://localhost:9000',
docsUrl: import.meta.env.VITE_DOCS_URL as string || '',
termsOfServiceUrl: import.meta.env.VITE_TERMS_OF_SERVICE_URL as string ||
'https://docs.wal.app/docs/legal/walrus_general_tos',
privacyPolicyUrl: import.meta.env.VITE_PRIVACY_POLICY_URL as string ||
'https://docs.wal.app/docs/legal/privacy',
gtmContainerId: import.meta.env.VITE_GTM_CONTAINER_ID as string || '',
gaMeasurementId: import.meta.env.VITE_GA_MEASUREMENT_ID as string || '',
posthogProjectApiKey: (
Expand Down
28 changes: 16 additions & 12 deletions apps/app/src/pages/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,19 @@ type RemoveKeysConfirmState = {
source: 'single' | 'selection'
}

// sanitize a key label — strip HTML special chars and control characters
function sanitizeLabelInput(raw: string): string {
return raw
// Strip HTML special characters
.replace(/[<>&"'/]/g, '')
// Strip Unicode control characters.
.replace(/\p{Cc}/gu, '')
}

function normalizeLabelForSubmit(raw: string): string {
return sanitizeLabelInput(raw).trim()
}

function bytesToHex(bytes: Uint8Array | number[]): string {
return Array.from(bytes).map((b) => b.toString(16).padStart(2, '0')).join('')
}
Expand Down Expand Up @@ -448,15 +461,6 @@ export default function Dashboard({
// Generate + add a new delegate key (via SDK)
// ============================================================

// sanitize a key label — strip HTML special chars and control characters
const sanitizeLabel = (raw: string): string =>
raw
// Strip HTML special characters
.replace(/[<>&"'/]/g, '')
// Strip Unicode control characters.
.replace(/\p{Cc}/gu, '')
.trim()

const handleAddKey = useCallback(async () => {
if (!walletSigner) return

Expand All @@ -473,7 +477,7 @@ export default function Dashboard({
}

// validate label before submitting on-chain
const trimmedLabel = sanitizeLabel(newKeyLabel)
const trimmedLabel = normalizeLabelForSubmit(newKeyLabel)
if (!trimmedLabel) {
setKeyError('key label cannot be empty')
trackEvent('delegate_key_add_failed', { error_type: 'invalid_input' })
Expand Down Expand Up @@ -1120,8 +1124,8 @@ const result = await generateText({
value={newKeyLabel}
maxLength={64}
onChange={(e) =>
// strip HTML special chars and control characters on every keystroke
setNewKeyLabel(sanitizeLabel(e.target.value))
// strip unsafe characters while preserving whitespace during typing
setNewKeyLabel(sanitizeLabelInput(e.target.value))
}
placeholder="New key"
/>
Expand Down
2 changes: 1 addition & 1 deletion apps/app/src/pages/LandingPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ export default function LandingPage() {
<ConnectButton connectText="Connect wallet" />
</div>
<p className="wm-signin-tos">
By continuing, you agree to our <a href={config.docsUrl || '#'} target="_blank" rel="noopener noreferrer">Terms of Service</a> and <a href={config.docsUrl || '#'} target="_blank" rel="noopener noreferrer">Privacy Policy</a>
By continuing, you agree to our <a href={config.termsOfServiceUrl} target="_blank" rel="noopener noreferrer">Terms of Service</a> and <a href={config.privacyPolicyUrl} target="_blank" rel="noopener noreferrer">Privacy Policy</a>
</p>
</div>
<div className="wm-signin-trusted" aria-hidden="true">
Expand Down
6 changes: 3 additions & 3 deletions docs/architecture/permanent-registry-design.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
# Permanent Registry Design Intent

## Overview
The `AccountRegistry` shared object in MemWal is designed as a *permanent* append-only mapping of `owner_address -> account_id`. Even if a user decides to deactivate or "delete" their account, their address remains in the registry.
The `AccountRegistry` shared object in Walrus Memory is designed as a *permanent* append-only mapping of `owner_address -> account_id`. Even if a user decides to deactivate or "delete" their account, their address remains in the registry.

## Security & Architecture Rationale
1. **Preventing Duplicate Sybil Accounts:**
By maintaining a permanent record, we ensure that an address can only ever create exactly *one* MemWalAccount. This simplifies off-chain indexing and prevents abuses related to account recreation.

2. **Deterministic Indexing:**
Indexers rely on a strict 1:1 mapping between a user's wallet address and their MemWal storage container. If accounts could be deleted and recreated with a different ID, historical data queries and relational integrity off-chain would be compromised.
Indexers rely on a strict 1:1 mapping between a user's wallet address and their Walrus Memory storage container. If accounts could be deleted and recreated with a different ID, historical data queries and relational integrity off-chain would be compromised.

3. **Data Immutability Context:**
In Web3, identity is persistent. The "deletion" of an account in MemWal is treated as a *deactivation* (freezing) rather than true erasure, which aligns with blockchain state patterns. The account remains frozen, preserving the historical linkage.
In Web3, identity is persistent. The "deletion" of an account in Walrus Memory is treated as a *deactivation* (freezing) rather than true erasure, which aligns with blockchain state patterns. The account remains frozen, preserving the historical linkage.

4. **SEAL Access Integrity:**
If an address could recreate its account, old data encrypted under the same SEAL Key ID (`bcs(address)`) could become unpredictably accessible or orphaned depending on the new configuration. A permanent registry guarantees that the encryption identity mathematically maps to a single, stable on-chain policy object forever.
6 changes: 3 additions & 3 deletions docs/contract/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
title: "Smart Contract Overview"
---

The smart contract (`memwal::account`) defines the onchain account model for MemWal. It is a Move module deployed on Sui.
The smart contract (`memwal::account`) defines the onchain account model for Walrus Memory. It is a Move module deployed on Sui.

## Network IDs

These are the onchain IDs for the current public MemWal deployments:
These are the onchain IDs for the current public Walrus Memory deployments:

### Staging (Testnet)

Expand All @@ -28,7 +28,7 @@ For relayer setup and environment variable usage, see [Self-Hosting](/relayer/se

## What It Manages

- **Ownership** — who owns a MemWal account
- **Ownership** — who owns a Walrus Memory account
- **Delegate keys** — which Ed25519 keys are authorized to act through the relayer
- **SEAL access control** — who can decrypt encrypted memories via `seal_approve`
- **Account lifecycle** — activation and deactivation (freeze/unfreeze)
Expand Down
2 changes: 1 addition & 1 deletion docs/contributing/docs-workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "Docs Workflow"
---

MemWal is still in beta, so documentation is an active part of product hardening.
Walrus Memory is still in beta, so documentation is an active part of product hardening.
If you see unclear guidance, outdated flows, or missing examples, contributions are welcome.

## Source of Truth
Expand Down
2 changes: 1 addition & 1 deletion docs/contributing/run-repo-locally.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: "Run the Repo Locally"
description: "Step-by-step guide to set up the MemWal monorepo for local development."
description: "Step-by-step guide to set up the Walrus Memory monorepo for local development."
---

## Prerequisites
Expand Down
3 changes: 2 additions & 1 deletion docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@
"pages": [
"getting-started/what-is-memwal",
"getting-started/quick-start",
"getting-started/choose-your-path"
"getting-started/choose-your-path",
"examples/example-apps"
]
}
]
Expand Down
14 changes: 7 additions & 7 deletions docs/examples/example-apps.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
---
title: "Example Apps"
description: "Short examples showing how each demo app uses MemWal."
description: "Short examples showing how each demo app uses Walrus Memory."
---

The repo includes ready-to-run apps in `apps/` that show different MemWal integration patterns.
This page focuses on app-level patterns,the basic SDK flow covered in [Quick Start](/sdk/quick-start) and [MemWal Usage](/sdk/usage/memwal).
The repo includes ready-to-run apps in `apps/` that show different Walrus Memory integration patterns.
This page focuses on app-level patterns,the basic SDK flow covered in [Quick Start](/sdk/quick-start) and [Walrus Memory Usage](/sdk/usage/memwal).

## Run Locally

Expand All @@ -17,7 +17,7 @@ pnpm dev:researcher

## [Playground](https://github.com/MystenLabs/MemWal/tree/main/apps/app)

Dashboard, playground, and interactive demo for MemWal.
Dashboard, playground, and interactive demo for Walrus Memory.

```ts
const memwal = MemWal.create({
Expand Down Expand Up @@ -51,7 +51,7 @@ const model = withMemWal(baseModel, {
});
```

This app shows AI middleware integration in a production-style chat app. The UI can enable MemWal, collect a delegate key and account ID, and pass them to the chat API. The server wraps the selected model with `withMemWal`, so recall happens before generation and new context can be auto-saved after each turn.
This app shows AI middleware integration in a production-style chat app. The UI can enable Walrus Memory, collect a delegate key and account ID, and pass them to the chat API. The server wraps the selected model with `withMemWal`, so recall happens before generation and new context can be auto-saved after each turn.

## [Noter](https://github.com/MystenLabs/MemWal/tree/main/apps/noter)

Expand All @@ -65,7 +65,7 @@ export const extractMemories = async (text: string): Promise<string[]> => {
};
```

This app shows note-to-memory extraction. Noter keeps a shared server-side MemWal client, lets the user configure the key and account at runtime, and uses `analyze()` to turn note content into structured facts while the relayer stores them asynchronously.
This app shows note-to-memory extraction. Noter keeps a shared server-side Walrus Memory client, lets the user configure the key and account at runtime, and uses `analyze()` to turn note content into structured facts while the relayer stores them asynchronously.

## [Researcher](https://github.com/MystenLabs/MemWal/tree/main/apps/researcher)

Expand All @@ -83,4 +83,4 @@ await memwal.waitForRememberJob(job.job_id);
const { results } = await memwal.recall({ query, limit: 5 });
```

This app shows long-form research memory and session rehydration. Researcher saves each sprint as a structured report in MemWal, then generates recall queries from sprint metadata, pulls back the most relevant findings, and rebuilds context for a fresh session.
This app shows long-form research memory and session rehydration. Researcher saves each sprint as a structured report in Walrus Memory, then generates recall queries from sprint metadata, pulls back the most relevant findings, and rebuilds context for a fresh session.
Loading
Loading