第 27 章 项目三:MemWal AI Agent 记忆库
MemWal 是 Mysten Labs 推出的 AI Agent 记忆层,目前仍处于 beta。它把记忆内容加密后存到 Walrus,用 Sui 上的账户和 delegate key 表达所有权与授权,并通过 relayer 处理 embedding、SEAL 加密、Walrus 上传下载和向量搜索。本章实现一个可运行的 TypeScript 记忆库:Agent 可以写入事实、按问题召回记忆,并把记忆能力暴露为 AI SDK tool。
项目目标
- 使用
@mysten-incubation/memwal连接 MemWal relayer。 - 固定最新依赖版本:
@mysten-incubation/memwal@0.0.2、@mysten/seal@1.1.1、@mysten/walrus@1.1.4、@mysten/sui@2.16.0、ai@6.0.175、zod@4.4.3。 - 通过环境变量管理 relayer、account id、delegate key 和 namespace。
- 说明 namespace 隔离、delegate key 轮换和 relayer 信任边界。
- 提供 CLI 与 AI SDK tool 两种接入方式。
架构
Agent runtime
| remember / recall
v
MemWal SDK
| signed request with delegate key
v
MemWal relayer
| embedding + SEAL + Walrus upload/search
v
Sui account + Walrus encrypted blobs + vector index
默认推荐路径是 MemWal 客户端:应用把请求交给 relayer,relayer 负责 embedding、SEAL、Walrus 与索引。只有当你要把 embedding 和 SEAL 全部放到客户端控制时,才使用 MemWalManual。
目录结构
examples/memwal/
package.json
tsconfig.json
.env.example
README.md
src/
config.ts
memory.ts
tools.ts
cli.ts
配置
MEMWAL_PRIVATE_KEY=your-64-char-hex-delegate-private-key
MEMWAL_ACCOUNT_ID=0x...
MEMWAL_SERVER_URL=https://relayer.staging.memwal.ai
MEMWAL_NAMESPACE=lets-walrus-agent-dev
字段含义:
MEMWAL_PRIVATE_KEY:delegate private key,不是用户主钱包私钥。Agent 用它签名请求并访问被授权的记忆空间。MEMWAL_ACCOUNT_ID:Sui 上的MemWalAccount对象 ID,表达记忆账户与所有权。MEMWAL_SERVER_URL:relayer 地址。测试可用 staging relayer,生产可用托管 mainnet relayer或自托管 relayer。MEMWAL_NAMESPACE:记忆命名空间。MemWal 按owner + namespace隔离搜索和存储,建议每个产品、租户或 Agent 使用独立 namespace。
关键代码
配置读取使用 Zod 做强校验:
import { z } from "zod";
const ConfigSchema = z.object({
MEMWAL_PRIVATE_KEY: z.string().regex(/^[0-9a-fA-F]{64}$/),
MEMWAL_ACCOUNT_ID: z.string().startsWith("0x"),
MEMWAL_SERVER_URL: z.string().url().default("https://relayer.staging.memwal.ai"),
MEMWAL_NAMESPACE: z.string().min(1).default("lets-walrus-agent-dev"),
});
export const config = ConfigSchema.parse(process.env);
封装 MemWal 客户端:
import { MemWal } from "@mysten-incubation/memwal";
import { config } from "./config.js";
export const memory = MemWal.create({
key: config.MEMWAL_PRIVATE_KEY,
accountId: config.MEMWAL_ACCOUNT_ID,
serverUrl: config.MEMWAL_SERVER_URL,
namespace: config.MEMWAL_NAMESPACE,
});
export async function rememberFact(content: string) {
await memory.health();
return memory.remember(content);
}
export async function recallFacts(query: string) {
await memory.health();
const result = await memory.recall(query);
return result.results ?? [];
}
把记忆能力暴露为 AI SDK tools:
import { tool } from "ai";
import { z } from "zod";
import { recallFacts, rememberFact } from "./memory.js";
export const memoryTools = {
memory_store: tool({
description: "Store a durable encrypted memory for future conversations.",
inputSchema: z.object({
content: z.string().min(1),
}),
execute: async ({ content }) => {
await rememberFact(content);
return { ok: true };
},
}),
memory_search: tool({
description: "Search durable encrypted memories by semantic query.",
inputSchema: z.object({
query: z.string().min(1),
}),
execute: async ({ query }) => {
return { results: await recallFacts(query) };
},
}),
};
CLI 用于验收记忆写入和召回:
import { recallFacts, rememberFact } from "./memory.js";
const [command, ...rest] = process.argv.slice(2);
const text = rest.join(" ").trim();
if (!command || !text) {
console.error("Usage: npm run mem -- remember <text>");
console.error(" npm run mem -- recall <query>");
process.exit(1);
}
if (command === "remember") {
await rememberFact(text);
console.log("stored");
} else if (command === "recall") {
const results = await recallFacts(text);
console.log(JSON.stringify(results, null, 2));
} else {
throw new Error(`Unknown command: ${command}`);
}
运行命令
cd examples/memwal
npm install
cp .env.example .env
示例目录包含 .npmrc:
legacy-peer-deps=true
原因是 MemWal 0.0.2 当前仍把 Zod 3 写在 optional peer 依赖声明中,而本书按最新版本事实固定 zod@4.4.3,AI SDK 6.0.175 也支持 Zod 4。这个设置只放在示例目录,避免影响整本书其它项目。
填入 .env 后运行:
npm run mem -- remember "用户偏好:回答要直接、中文、带可复制命令。"
npm run mem -- recall "这个用户喜欢什么回答风格?"
在 Agent 中接入:
import { generateText } from "ai";
import { memoryTools } from "./tools.js";
const result = await generateText({
model,
tools: memoryTools,
prompt: "记住:我正在学习 Walrus。以后回答要结合去中心化存储。",
});
上面的 model 由你的模型 provider 提供,例如 OpenAI-compatible、Anthropic 或本地模型适配器。MemWal 不绑定具体模型供应商。
Relayer、Namespace 与 Delegate Key
relayer 是 MemWal 的关键运行边界。托管 relayer 可以最快接入;自托管 relayer适合需要控制 embedding provider、SEAL 操作、可用性和日志边界的团队。自托管时通常需要 PostgreSQL + pgvector、Redis、Sui server key、MemWal package/registry id,以及 SEAL key server 配置。
namespace 是记忆隔离单元。推荐命名:
<app>:<environment>:<tenant-or-agent>
例如:
lets-walrus:dev:writer
lets-walrus:prod:support-agent
lets-walrus:prod:tenant-42
delegate key 是给 Agent 的授权钥匙,不应等同于用户主钱包私钥。生产系统至少要做到:
- 每个环境使用不同 delegate key。
- 每个高风险 Agent 使用独立 namespace 和独立 delegate key。
- 支持撤销和轮换 delegate key。
- 不在浏览器、本地日志、CI 输出或错误上报中泄露私钥。
安全边界
- MemWal 当前是 beta,托管 relayer 不应被视为有强 SLA 的生产基础设施。
- 使用托管 relayer 时,团队需要接受 relayer 参与 embedding、加密/解密编排、Walrus 上传下载和向量搜索的信任边界。
- 需要更强控制时,自托管 relayer,并把数据库、Redis、server wallet、OpenAI-compatible embedding key 纳入自己的运维边界。
- 记忆召回结果会进入 LLM 上下文,应把它当作外部输入处理,避免把召回内容直接当系统指令执行。
- namespace 不是权限系统的全部;它是隔离维度,仍然要配合 delegate key、账户所有权和应用层授权。
验收标准
npm install后依赖版本与本章指定版本一致。.env填入 staging 或生产凭证后,npm run mem -- remember ...返回stored。- 使用同一
MEMWAL_NAMESPACE可以召回刚写入的事实。 - 更换
MEMWAL_NAMESPACE后默认召回不到另一个 namespace 的记忆。 - 日志不输出完整 delegate key。
- README 明确标注 MemWal beta、relayer 信任边界和 delegate key 安全要求。