← 返回博客

Rotifer v0.9.4:Agent 有了自己的记忆(npm 0.33.0)

Agent 现在有一份记忆,基因可以在多次运行之间读写。记忆属于 Agent,换掉基因也不会丢。四类条目、按固定顺序清理的配额、访问范围和保留期限,全部存在你自己的机器上。

Rotifer v0.9.4:Agent 有了自己的记忆(npm 0.33.0)

以前,基因每次运行都从零开始。它对用户、对任务、对反复出现的输入学到的东西,运行一结束就没了。

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 不会把它们发到任何地方。


哪些基因能用记忆

记忆只在 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 接入时部署;这一版不包含,也没有排期。


这一版还有

完整列表见更新日志。


走到了哪一步

我们要的是:Agent 跑得越久越会做事,而它里面的基因不断被更好的基因换掉。这需要一份比任何单个基因都活得久的记忆,以及谁能碰它的规则。这一版把它在你的机器上建好了。

这一版没有的:

安装 / 升级

npm install -g @rotifer/playground@0.33.0