Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

第 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.0ai@6.0.175zod@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 安全要求。