以前,基因每次运行都从零开始。它对用户、对任务、对反复出现的输入学到的东西,运行一结束就没了。
v0.9.4 给每个 Agent 一份记忆。Agent 里的基因可以在多次运行之间读写它:一共四个调用,规则由协议定好——这是哪一类条目、谁能读、空间有多大、留多久。
v0.9.4 是协议版本号(规范 §38,Agent 记忆),2026-11-01 随 npm 包 @rotifer/playground 0.33.0 发布。
名词速查:Agent 是由一组基因组成、替你完成一件事的智能体;基因(Gene) 是 Agent 里可以单独替换、单独打分的能力单元;领域(domain) 是基因声明的功能类别,比如「格式化」「搜索」。
记忆属于 Agent,不属于某个基因
一个 Agent 由一组基因组成,而基因是会被换掉的:来了一个更好的格式化基因,或者某个基因出了新版本。如果记忆存在基因里面,每换一次,Agent 学到的东西就清空一次。
所以记忆归 Agent 所有。替换或升级基因时,Agent 的记忆原样留着,下一个基因接着用。
下面这个格式化基因会记住用户上次要的缩进宽度:
import type { GeneMemoryAccess } from "@rotifer/playground/memory";
// reindent() 是这个基因自己的格式化逻辑,此处省略。
const KEY = "formatter/indent";
export function express(
input: { code: string; indent?: number },
ctx: { memory: GeneMemoryAccess },
): { formatted: string; indent: number } {
let indent = input.indent;
if (indent === undefined) {
const saved = ctx.memory.readMemory(KEY, "PREFERENCE");
indent = saved ? Number(new TextDecoder().decode(saved.value)) : 2;
} else {
ctx.memory.writeMemory(
KEY,
new TextEncoder().encode(String(indent)),
"PREFERENCE",
);
}
return { formatted: reindent(input.code, indent), indent };
}这个条目用的是默认访问策略,同一领域的其他格式化基因也能读到。把它换成同领域里更好的格式化基因,新基因会在老基因留下的地方找到这个缩进设置。
四类条目,满了先清哪类
每个条目属于四类之一:
| 类别 | 存什么 | 记忆满了会被清理吗? |
|---|---|---|
PREFERENCE |
Agent 对用户习惯与偏好的了解 | 永不 |
PATTERN |
多次运行中发现的规律 | 会,排在 CACHE 之后 |
CONTEXT |
对某个任务或领域积累的知识 | 会,排在 PATTERN 之后 |
CACHE |
可以重新算出来的中间结果 | 会,最先清 |
每个 Agent 有一个记忆配额,默认 10 MB。创建 Agent 时可以另设:
rotifer agent create my-agent --genes my-gene --memory-quota=50MB写入会超出配额时,Agent 依次删掉最旧的 CACHE、PATTERN、CONTEXT 条目来腾地方,PREFERENCE 条目永远不会这样被删。腾完还放不下,这次写入以 MEMORY_QUOTA_EXCEEDED 失败,什么也不写。
谁能读什么
每个条目写明哪些基因能读、哪些基因能改或删。可选的范围是:只有创建它的基因、与创建者同一领域的基因、Agent 里所有基因。默认是同一领域(SAME_DOMAIN)。
每次读、写、删之前都会检查。不允许的基因拿到 MEMORY_ACCESS_DENIED,这次拒绝会写进 Agent 的审计日志。
条目留多久
条目可以带 maxRetentionDays。从它最后一次被写入算起,过了这么多天,它就没了:读不到、查询里没有、不再占配额。每删一条都会记日志。
查看和清理 Agent 的记忆
你作为部署这个 Agent 的人,可以查看并清理它的记忆:
rotifer agent memory list <agent> [--category <category>]
rotifer agent memory delete <agent> (--key <key> | --category <category>)list 列出每个条目的键、类别、大小、创建它的基因和最后更新时间,从不显示值。delete 按键删一条,或删掉一整类,不受条目访问策略的限制,每次删除都记日志。
全部留在你的机器上
记忆存在项目的 .rotifer/playground.db 里。每一次改动、每一次被拒绝的访问,都会在 .rotifer/audit.jsonl 里加一行。这两个文件都留在你的机器上,CLI 不会把它们发到任何地方。
哪些基因能用记忆
- 在 Node.js 上运行的 TypeScript 基因通过
ctx.memory拿到这四个调用,就像上面的例子。 - 自带 WASM 的基因(Rust、AssemblyScript、WAT)调用宿主函数
rotifer.readMemory、writeMemory、queryMemory、deleteMemory。 - 编译成 WASM 的 TypeScript 基因暂时用不了记忆。需要记忆的 TypeScript 基因,请在 Node.js 上运行。
记忆只在 Agent 里可用(rotifer agent run)。想试一个用到记忆的基因,就跑 rotifer test:它在测试期间给基因一份空的临时记忆,测完即删,不碰你的 Agent 的记忆。
四个调用、错误码、宿主函数接口和大小限制,见 Memory API 参考。
云端:已实现、已核对,尚未部署
同一套记忆模型也为 Rotifer Cloud 实现了:数据库结构和一个 agent-memory 边缘函数,代码在 rotifer-playground 仓库里。我们把同一组操作分别在 CLI 和云端实现(连本地 Supabase)上各跑一遍,逐条比对结果:主场景 39 条全部一致,过期场景 32 条全部一致。
它还没有部署。目前 Rotifer Cloud 不保存 Agent 的记忆,也没有命令能把 Agent 的记忆搬到云端。它会在 rotifer.ai 的云端 Agent 接入时部署;这一版不包含,也没有排期。
这一版还有
rotifer run会检查 schema。运行前按基因的inputSchema检查输入,运行后按outputSchema检查输出。不合规的输入现在以退出码 1 结束;--no-validate可关掉两项检查。rotifer compile显示Gene ID (v2),也就是记忆里记作条目创建者的那个 ID,并注明内容哈希不是身份标识。- 修复:包装基因又能编译了;写成
Par、Cond或Try却没法按原样运行的 Agent,会停下并说明原因,不再悄悄按Seq运行;因超时被停下的基因报告为超时;rotifer run在 Windows 上可用了。 - CLI 里的 τ 也暂停了;wasmtime 升到 48.0.8,修复 2026-10-29 的 RustSec 安全公告。
完整列表见更新日志。
走到了哪一步
我们要的是:Agent 跑得越久越会做事,而它里面的基因不断被更好的基因换掉。这需要一份比任何单个基因都活得久的记忆,以及谁能碰它的规则。这一版把它在你的机器上建好了。
这一版没有的:
- 云端记忆没有上线。云端实现已经有了,结果也和 CLI 一致,但还没部署。
- 编译成 WASM 的 TypeScript 基因暂时用不了记忆。
autoDeleteOnTermination会保存,但暂时不起作用。- 没有命令能把 Agent 或它的记忆搬到另一个 Binding。
安装 / 升级
npm install -g @rotifer/playground@0.33.0