Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions apps/chatbot/app/(chat)/api/chat/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { getLanguageModel, getMemWalModel } from "@/lib/ai/providers";
import { createDocument } from "@/lib/ai/tools/create-document";
import { getWeather } from "@/lib/ai/tools/get-weather";
import { requestSuggestions } from "@/lib/ai/tools/request-suggestions";
import { saveMemory } from "@/lib/ai/tools/save-memory";
import { updateDocument } from "@/lib/ai/tools/update-document";
import { isProductionEnvironment } from "@/lib/constants";
import {
Expand Down Expand Up @@ -170,6 +171,7 @@ export async function POST(request: Request) {
"createDocument",
"updateDocument",
"requestSuggestions",
"saveMemory",
],
providerOptions: isReasoningModel
? {
Expand All @@ -183,6 +185,7 @@ export async function POST(request: Request) {
createDocument: createDocument({ session, dataStream }),
updateDocument: updateDocument({ session, dataStream }),
requestSuggestions: requestSuggestions({ session, dataStream }),
saveMemory: saveMemory({ memwalKey, memwalAccountId }),
},
experimental_telemetry: {
isEnabled: isProductionEnvironment,
Expand Down
22 changes: 21 additions & 1 deletion apps/chatbot/components/message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ const PurePreviewMessage = ({
>
{message.role === "assistant" && (
<div className="-mt-1 flex size-8 shrink-0 items-center justify-center rounded-full bg-background ring-1 ring-border">
<SparklesIcon size={14} />
<div className={isLoading && !message.parts?.some((p) => (p.type === "text" && p.text?.trim()) || ["tool-getWeather", "tool-createDocument", "tool-updateDocument", "tool-requestSuggestions"].includes(p.type)) ? "animate-pulse" : ""}>
<SparklesIcon size={14} />
</div>
</div>
)}

Expand Down Expand Up @@ -104,6 +106,24 @@ const PurePreviewMessage = ({
</div>
)}

{/* Show "Thinking..." when assistant message is loading with no content */}
{message.role === "assistant" &&
isLoading &&
!message.parts?.some(
(p) =>
(p.type === "text" && p.text?.trim()) ||
["tool-getWeather", "tool-createDocument", "tool-updateDocument", "tool-requestSuggestions"].includes(p.type)
) && (
<div className="flex items-center gap-1 p-0 text-muted-foreground text-sm">
<span className="animate-pulse">Thinking</span>
<span className="inline-flex">
<span className="animate-bounce [animation-delay:0ms]">.</span>
<span className="animate-bounce [animation-delay:150ms]">.</span>
<span className="animate-bounce [animation-delay:300ms]">.</span>
</span>
</div>
)}

{message.parts?.map((part, index) => {
const { type } = part;
const key = `message-${message.id}-part-${index}`;
Expand Down
15 changes: 9 additions & 6 deletions apps/chatbot/components/messages.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,15 @@ function PureMessages({
/>
))}

{status === "submitted" &&
!messages.some((msg) =>
msg.parts?.some(
(part) => "state" in part && part.state === "approval-responded"
)
) && <ThinkingMessage />}
{(status === "submitted" || status === "streaming") &&
(() => {
const lastMsg = messages[messages.length - 1];
// Show ThinkingMessage when:
// 1. Status is "submitted" (request sent, no response yet) AND last message is from user
// 2. Status is "streaming" but no assistant message exists yet
const lastIsUser = !lastMsg || lastMsg.role === "user";
return lastIsUser;
})() && <ThinkingMessage />}

<div
className="min-h-[24px] min-w-[24px] shrink-0"
Expand Down
4 changes: 2 additions & 2 deletions apps/chatbot/lib/ai/entitlements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ export const entitlementsByUserType: Record<UserType, Entitlements> = {
* For users without an account
*/
guest: {
maxMessagesPerHour: 10,
maxMessagesPerHour: 30,
},

/*
* For users with an account
*/
regular: {
maxMessagesPerHour: 10,
maxMessagesPerHour: 30,
},

/*
Expand Down
7 changes: 6 additions & 1 deletion apps/chatbot/lib/ai/prompts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@ Do not update document right after creating it. Wait for user feedback or reques

export const regularPrompt = `You are a friendly assistant! Keep your responses concise and helpful.

When asked to write, create, or help with something, just do it directly. Don't ask clarifying questions unless absolutely necessary - make reasonable assumptions and proceed with the task.`;
When asked to write, create, or help with something, just do it directly. Don't ask clarifying questions unless absolutely necessary - make reasonable assumptions and proceed with the task.

You have access to the user's personal memory system powered by MemWal. Memories are automatically recalled and injected as context during conversations.

Memory Tool:
- saveMemory({text}) - Save information to the user's personal memory on the blockchain. ONLY call this when the user EXPLICITLY asks to save or remember something. Do NOT call it proactively.`;

export type RequestHints = {
latitude: Geo["latitude"];
Expand Down
48 changes: 48 additions & 0 deletions apps/chatbot/lib/ai/tools/save-memory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { tool } from "ai";
import { z } from "zod";
import { MemWal } from "@mysten-incubation/memwal";

export const saveMemory = ({
memwalKey,
memwalAccountId,
}: {
memwalKey?: string;
memwalAccountId?: string;
}) =>
tool({
description:
"Save information to the user's personal memory on the blockchain. ONLY use this tool when the user EXPLICITLY asks you to save or remember something (e.g., 'remember this', 'save this', 'lưu lại', 'nhớ giùm'). Do NOT use this tool proactively. Save the FULL, DETAILED content — do not summarize or shorten it.",
inputSchema: z.object({
text: z
.string()
.describe(
"The full, detailed text to save to memory. Include all relevant details — do not summarize."
),
}),
execute: async ({ text }) => {
const key = memwalKey || process.env.MEMWAL_KEY;
const accountId = memwalAccountId || process.env.MEMWAL_ACCOUNT_ID;
const serverUrl = process.env.MEMWAL_SERVER_URL || "http://localhost:8000";

if (!key || !accountId) {
return {
saved: false,
text,
error: "MemWal not configured — MEMWAL_KEY or MEMWAL_ACCOUNT_ID missing",
};
}

try {
const memwal = MemWal.create({ key, accountId, serverUrl });
await memwal.remember(text);
return { saved: true, text };
} catch (error) {
console.error("[Tool] saveMemory error:", error);
return {
saved: false,
text,
error: error instanceof Error ? error.message : "Failed to save memory",
};
}
},
});
4 changes: 2 additions & 2 deletions docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@
"links": [
{
"label": "GitHub",
"href": "https://github.com/CommandOSSLabs/memwal"
"href": "https://github.com/MystenLabs/MemWal"
}
]
},
"footer": {
"socials": {
"github": "https://github.com/CommandOSSLabs/memwal"
"github": "https://github.com/MystenLabs/MemWal"
}
},
"navigation": {
Expand Down
2 changes: 1 addition & 1 deletion docs/fundamentals/architecture/core-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ This means Web2 developers can integrate MemWal without touching wallets, signin
Because the relayer handles encryption and plaintext data, you are placing trust in the relayer operator. This is a deliberate trade-off for developer experience. If you need full control over that trust boundary, you can [self-host](/relayer/self-hosting) your own relayer, or use the [manual client flow](/sdk/usage) to handle encryption and embedding entirely on the client side (recommended for Web3-native users). See [Trust & Security Model](/fundamentals/architecture/data-flow-security-model) for details.
</Note>

You can use the [public relayer](/relayer/public-relayer) to get started, [self-host](/relayer/self-hosting) your own, or use the manual client flow for full client-side control.
You can use the [managed relayer](/relayer/public-relayer) to get started, [self-host](/relayer/self-hosting) your own, or use the manual client flow for full client-side control.

## MemWal Smart Contract

Expand Down
4 changes: 2 additions & 2 deletions docs/fundamentals/architecture/data-flow-security-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ You have options depending on your trust requirements:

| Option | Trust level | What the relayer sees |
|--------|------------|----------------------|
| **Public relayer** | You trust the MemWal team | Plaintext content, embeddings, decrypted results |
| **Managed relayer** | You trust Walrus Foundation | Plaintext content, embeddings, decrypted results |
| **Self-hosted relayer** | You trust your own infra | Same as above, but under your control |
| **Manual client flow** | Minimal trust | Only encrypted payloads and pre-computed vectors — never plaintext |

- **Use the public relayer** — convenient for getting started and prototyping. You trust the MemWal team to operate it responsibly.
- **Use the managed relayer** — convenient for getting started and prototyping. You trust Walrus Foundation to operate it responsibly.
- **Self-host your own relayer** — you control the infrastructure, so the trust boundary is entirely yours. No third party sees your data.
- **Manual client flow** — use `MemWalManual` to handle encryption and embedding entirely on the client side. The relayer only sees encrypted payloads and vectors, never plaintext. This is recommended for Web3-native users who want full control over their data and are comfortable managing keys, signing, and SEAL operations directly.

Expand Down
22 changes: 13 additions & 9 deletions docs/getting-started/choose-your-path.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: "Choose Your Path"
MemWal supports several integration modes depending on how much control you need. Pick the one that fits your use case.

<Tip>
These paths aren't mutually exclusive. You can combine them for example, use the **Default SDK** with the **AI Middleware**, or start with the **Public Relayer** and move to **Self-Hosting** later. They all share the same backend and data layer.
These paths aren't mutually exclusive. You can combine them - for example, use the **Default SDK** with the **AI Middleware**, or start with the **Managed Relayer** and move to **Self-Hosting** later. They all share the same backend and data layer.
</Tip>

## 1. Default SDK
Expand All @@ -17,20 +17,24 @@ Use `@mysten-incubation/memwal` when you want the fastest working integration.

Go to: [SDK Overview](/sdk/overview)

## 2. Public Relayer
## 2. Managed Relayer

Use this when you want to evaluate MemWal without running the backend yourself.
Use a hosted relayer, or deploy your own [self-hosted relayer](/relayer/self-hosting) with access to a wallet funded with WAL and SUI.

<Note>
Following endpoints are provided as public good by Walrus Foundation.
</Note>

| Network | Relayer URL |
|---|---|
| **Testnet** (staging) | `https://relayer.staging.memwal.ai` |
| **Mainnet** (production) | `https://relayer.memwal.ai` |
| --- | --- |
| **Production** (mainnet) | `https://relayer.memwal.ai` |
| **Staging** (testnet) | `https://relayer.staging.memwal.ai` |

Go to: [Public Relayer](/relayer/public-relayer)
Go to: [Managed Relayer](/relayer/public-relayer)

## 3. Manual Client Flow

Use `@mysten-incubation/memwal/manual` when you want full client-side control over encryption and embeddings. Recommended for Web3-native users who want to minimize trust in the relayer it never sees your plaintext data.
Use `@mysten-incubation/memwal/manual` when you want full client-side control over encryption and embeddings. Recommended for Web3-native users who want to minimize trust in the relayer - it never sees your plaintext data.

- client handles embeddings and SEAL encryption locally
- relayer only sees encrypted payloads and vectors
Expand All @@ -45,6 +49,6 @@ Go to: [AI Integration](/sdk/usage/with-memwal)

## 5. Self-Host the Relayer

Use this when you need full control over the trust boundary your infrastructure, your credentials, no third party sees your data.
Use this when you need full control over the trust boundary - your infrastructure, your credentials, no third party sees your data.

Go to: [Self-Hosting](/relayer/self-hosting)
39 changes: 19 additions & 20 deletions docs/getting-started/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ The fastest way to get MemWal running is through the TypeScript SDK.
## Prerequisites

- [Node.js](https://nodejs.org/) v18+ or [Bun](https://bun.sh/) v1+
- A delegate key (Ed25519 private key in hex)
- A MemWalAccount object ID on Sui
- A relayer URL

## Quick Start

Expand Down Expand Up @@ -96,23 +93,33 @@ The fastest way to get MemWal running is through the TypeScript SDK.
<Step>
### Generate your account ID and delegate key

Create a MemWal account ID and delegate private key for your SDK client using the hosted endpoint:
Create a MemWal account ID and delegate private key for your SDK client using one of the hosted endpoints below.

<Tip>
These hosted endpoints are provided by Walrus Foundation.
</Tip>
<Note>
The following endpoints are provided as a public good by Walrus Foundation.
</Note>

| App | URL |
| --- | --- |
| **MemWal Playground** | [memwal.ai](https://memwal.ai) |
| **Walrus-hosted Playground** | [memwal.wal.app](https://memwal.wal.app) |

- Production (mainnet): `https://memwal.ai` or `https://memwal.wal.app`
- Staging (testnet): `https://staging.memwal.ai`
For the contract-based setup flow, see [Delegate Key Management](/contract/delegate-key-management) and [MemWal smart contract](/contract/overview).
</Step>

<Step>
### Choose a relayer

Use the hosted relayer, or deploy your own if it has access to a wallet funded with WAL and SUI:
Use a hosted relayer, or deploy your own [self-hosted relayer](/relayer/self-hosting) with access to a wallet funded with WAL and SUI:

<Note>
Following endpoints are provided as public good by Walrus Foundation.
</Note>

- Production (mainnet): `https://relayer.memwal.ai`
- Staging (testnet): `https://relayer.staging.memwal.ai`
| Network | Relayer URL |
| --- | --- |
| **Production** (mainnet) | `https://relayer.memwal.ai` |
| **Staging** (testnet) | `https://relayer.staging.memwal.ai` |
</Step>

<Step>
Expand All @@ -130,14 +137,6 @@ The fastest way to get MemWal running is through the TypeScript SDK.
namespace: "my-app",
});
```

<Tip>
Use `https://relayer.memwal.ai` for production (mainnet) or `https://relayer.staging.memwal.ai` for staging (testnet). See [Public Relayer](/relayer/public-relayer) for details.
</Tip>

<Note>
If you are self-hosting and do not have `MEMWAL_ACCOUNT_ID` yet, see [Self-Hosting](/relayer/self-hosting) for the account-creation and delegate-key setup flow.
</Note>
</Step>

<Step>
Expand Down
8 changes: 6 additions & 2 deletions docs/getting-started/what-is-memwal.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ title: "What is MemWal?"
description: "Persistent, verifiable memory for AI agents"
---

<Note>
MemWal 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.
</Note>

MemWal introduces a long-term, verifiable memory layer on Walrus, allowing agents to remember, share, and reuse information reliably.

<CardGroup cols={2}>
Expand Down Expand Up @@ -98,7 +102,7 @@ And many more — check out the example apps below to see MemWal in action.

## Example Apps

The repo ships with ready-to-run apps in the [`/apps`](https://github.com/CommandOSSLabs/memwal/tree/main/apps) directory:
The repo ships with ready-to-run apps in the [`/apps`](https://github.com/MystenLabs/MemWal/tree/main/apps) directory:

- **Playground** — dashboard demo for MemWal
- **Chatbot** — AI chat app with persistent memory across sessions
Expand All @@ -120,7 +124,7 @@ See [Example Apps](/examples/example-apps) for short code examples from each app
Quickstart, usage patterns, AI integration, and examples
</Card>
<Card title="Relayer" icon="tower-broadcast" href="/relayer/overview">
Public relayer, installation and setup, self-hosting
Managed relayer, installation and setup, self-hosting
</Card>
<Card title="Smart Contract" icon="scroll" href="/contract/overview">
Onchain ownership model, delegate key management, permissions
Expand Down
12 changes: 6 additions & 6 deletions docs/relayer/public-relayer.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
---
title: "Public Relayer"
title: "Managed Relayer"
---

The public relayer is a managed MemWal deployment for teams that want to get started without running infrastructure. If a public relayer endpoint is available for your environment, it gives you the fastest path to integration.
A managed relayer is a simpler experience for teams that want to get started without running infrastructure. If a managed relayer endpoint is available for your environment, it gives you the fastest path to integration.

## Endpoints
## Walrus Foundation hosted endpoints

| Network | Relayer URL |
|---|---|
Expand All @@ -26,9 +26,9 @@ const memwal = MemWal.create({

## What to Know

- **Shared App ID** - all users of the public relayer share the same MemWal package ID. Your data is isolated by your own `owner + namespace` (Memory Space), but the underlying deployment is shared.
- **Trust assumption** - the relayer sees plaintext during encryption and embedding. By using the public relayer, you're trusting the Mysten-hosted instance with that data. See [Trust & Security Model](/fundamentals/architecture/data-flow-security-model) for details.
- **Availability** - the public relayer is a managed beta service. There are no SLA guarantees.
- **Shared App ID** - all users of the managed relayer share the same MemWal package ID. Your data is isolated by your own `owner + namespace` (Memory Space), but the underlying deployment is shared.
- **Trust assumption** - the relayer sees plaintext during encryption and embedding. By using the managed relayer, you're trusting the Walrus Foundation-hosted instance with that data. See [Trust & Security Model](/fundamentals/architecture/data-flow-security-model) for details.
- **Availability** - the managed relayer is a managed beta service. There are no SLA guarantees.
- **Storage costs** - the server wallet covers Walrus storage fees. Usage limits may apply during beta.

If you need full control over the trust boundary or your own dedicated instance, see [Self-Hosting](/relayer/self-hosting).
4 changes: 2 additions & 2 deletions docs/relayer/self-hosting.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ title: "Self-Hosting"

Self-hosting means running your own relayer — either pointing at an existing MemWal package ID or deploying an entirely new MemWal instance with your own contract, database, and server wallet.

The public relayer provided by Mysten is a reference implementation. You can also build your own implementation that fits the same API surface with custom logic. This guide covers how to run the reference implementation as your own self-hosted relayer.
The managed relayer provided by Walrus Foundation is a reference implementation. You can also build your own implementation that fits the same API surface with custom logic. This guide covers how to run the reference implementation as your own self-hosted relayer.

## When to Self-Host

Expand All @@ -13,7 +13,7 @@ The most common reasons are removing the trust assumption on a third-party relay
- **Control the trust boundary** — a self-hosted relayer keeps plaintext, encryption, and embedding under your own control
- **Run your own MemWal instance** — deploy your own contract with a separate package ID, SEAL encryption keys, and data isolation
- **Choose your own embedding provider** — use your own OpenAI-compatible API and credentials
- **Guarantee availability** — the public relayer is a beta service with no SLA
- **Guarantee availability** — the managed relayer is a beta service with no SLA

## What Runs

Expand Down
Loading
Loading