OpenClaw Agent、工作区与记忆:它到底记住什么

Posted on Sat 10 October 2026 in AI 编程 • Sucre Liu

一个 agent = 一个工作区

OpenClaw 内置一套 agent 运行时:agent 循环、工具接线、提示组装都在这里。每个 agent 有自己的工作区,而工作区是它唯一的工作目录(cwd)与上下文来源。

这带来一个必须早点知道的事实:工作区是"默认 cwd",不是硬沙箱。 除非你启用 sandboxing,否则工具用绝对路径照样能越过工作区。想真正限制,靠的是沙箱 + 工具策略,而不是"把文件放在 workspace 里"。相关工作区布局与备份见官方 Agent workspace 页。

想新建一份工作区及其初始文件,用:

openclaw setup

Bootstrap 文件:每次新会话注入什么

工作区里这几个 Markdown 是"人可编辑"的核心:

文件 作用
AGENTS.md 操作指令 + "记忆"
SOUL.md 人格、边界、语气
IDENTITY.md 名字/风格/emoji
USER.md 用户画像与称呼偏好
BOOTSTRAP.md 一次性首跑仪式(完成后删除)
MEMORY.md 长期记忆根文件(存在才注入)

在新会话的第一轮,这些文件的内容会被注入系统提示的 Project Context。行为细节:

  • 空文件会被跳过;大文件会被裁剪/截断并留标记(要看全文就自己读文件)。
  • 除 MEMORY.md 外,缺失的文件会注入一行"缺文件"标记;openclaw setup 会生成安全模板。
  • BOOTSTRAP.md 只在全新工作区(其它 bootstrap 文件都不存在)时创建;完成仪式删掉后不会在重启时重建。

如果工作区是预置好的、不想让它生成 bootstrap 文件:

{ agents: { defaults: { skipBootstrap: true } } }

一个值得养成的习惯:把 AGENTS.md 当成"操作手册",别当垃圾桶。 它每轮都进上下文,越长越贵,也越容易被忽略。

会话存在哪

会话行与转录存放在每个 agent 各自的 SQLite:

~/.openclaw/agents/<agentId>/agent/openclaw-agent.sqlite

要点:

  • 会话 ID 由 OpenClaw 稳定分配;
  • 老的 JSONL 转录是迁移输入,正常启动不会导入;发现旧存储时会拒绝就绪并打印 doctor 命令,要在停机后 openclaw doctor --fix;
  • 它不读其它工具的会话目录——别指望把别处的会话文件夹丢进来就能用。

还有一个运行时行为值得知道:流式进行中的消息默认会被"steer"进当前运行,而不是排队等下一轮。/queue steer 是默认值;/queue followup、/queue collect 让它等下一轮,/queue interrupt 直接中止当前运行。块级流式(block streaming)默认关闭。

记忆:没有隐藏状态

这是 OpenClaw 做得比多数工具清楚的地方——记忆就是工作区里的纯 Markdown,模型只记住被写进磁盘的东西,没有隐藏状态。四个文件分工:

<workspace>/
├── USER.md                  # 稳定偏好、画像(指令式,带观察日期)
├── MEMORY.md                # 长期记忆:耐久事实与决定
├── memory/
│   └── 2026-10-10.md        # 每日笔记:运行上下文、观察
└── DREAMS.md                # 做梦巩固的日记,供人复核
  • USER.md 是紧凑的"用户模型"层:稳定偏好写成指令,偏好变化时原地替换而不是追加矛盾条目。
  • MEMORY.md 是策展层:耐久事实、长期决定、短摘要。它不是转录,也不是每日日志。
  • memory/YYYY-MM-DD.md 是工作层:细节、观察、会话摘要。它们被索引供搜索,但不会每轮注入。
  • 裸 /new 或 /reset 时,今天和昨天的日期笔记会自动加载。

如果 MEMORY.md 超过 bootstrap 预算,OpenClaw 保留磁盘原文,但截断注入副本。这是一个信号:把细节挪进 memory/*.md,MEMORY.md 只留摘要。用 /context list、/context detail 或 openclaw doctor 看实际注入大小与截断状态。

想让助手记东西,直接说就行:"记住我偏好 TypeScript。"它会写进合适的文件。

三个记忆工具

agent 手上有三个工具:

  • memory_search:语义搜索,措辞不同也能找到;
  • memory_get:读某个记忆文件或行区间;
  • intent:创建、列出、取消"事件条件型"的常驻意图。

配置了 embedding provider 时,memory_search 用混合检索:向量相似度 + 关键词(对 ID、代码符号这类精确项尤其有用)。默认用 OpenAI embeddings,可用 memory.search.provider 换成 Gemini、Voyage、Mistral、Bedrock、本地 GGUF、Ollama、LM Studio 等。

引擎默认是内置的 SQLite(关键词 + 向量 + 混合),也可换 Honcho(AI 原生的跨会话记忆)或 LanceDB 插件。

巩固:记忆冲写与"做梦"

两块自动机制,默认都开:

记忆冲写(memory flush):在上下文压缩(compaction)总结之前,OpenClaw 会跑一个静默回合,提醒 agent 把重要上下文写进记忆文件。它用对话的私有副本,这些"家务"消息不会出现在后续用户回合里。想让它跑在本地小模型上,可以单独指定:

{
  "agents": {
    "defaults": {
      "compaction": {
        "memoryFlush": { "model": "ollama/qwen3:8b" }
      }
    }
  }
}

注意:冲写需要可写工作区;沙箱要求只读或不访问工作区的会话会跳过它。

做梦(dreaming):后台巩固通道,收集短期召回信号、评分候选,只把合格的项提升进 MEMORY.md。它默认开启,启用时会自动管理一个周期性的 cron 任务。通过的候选会经过"合并/替换"的选择,结果写进 DREAMS.md 供人复核。短期的召回状态是机器排序面,MEMORY.md 只由深阶段写入——三者边界清楚。想关:

{ plugins: { entries: { "memory-core": { config: { dreaming: { enabled: false } } } } } }

从别处导入记忆

Control UI 的 Settings → Import Memory 能从 Codex、Claude Code、Hermes 导入本地记忆。它只搬 Markdown 记忆,不搬配置、凭据或技能:

  • Claude Code:~/.claude/projects/*/memory 下的 Markdown;
  • Codex:~/.codex/memories 下的 MEMORY.md、memory_summary.md;
  • Hermes:探测到的 MEMORY.md、USER.md。

导入的文件单独存放在 memory/imports/<来源>/,会被索引、可通过 memory_get 读取,但不会合并进 bootstrap 的 MEMORY.md。源文件保持不变。

多 agent:隔离的正确姿势

多 agent 用 agents.entries 定义,bindings 把通道/账号/peer 路由到 agent。两条硬经验:

  1. 绝不复用同一个 agentDir。 那会导致 auth 与会话冲突。
  2. 多人可发消息时,务必设 session.dmScope。 否则不同人的私聊会并进同一段主会话上下文。

另外,工作区里能用绝对路径越界,除非你开了沙箱——隔离靠沙箱,不靠目录约定。

关于记忆的一条边界

记忆能保存"审批上下文",但不执行策略。想实现硬性的操作控制,用 OpenClaw 的审批设置、沙箱与定时任务,而不是在记忆里写一句"不要做 X"。这一点和 Claude Code 里"CLAUDE.md 是请求不是保证"是同一个道理。

小结

  • 一个 agent = 一个工作区;工作区是默认 cwd,不是硬沙箱。
  • bootstrap 文件在新会话首轮注入;AGENTS.md 是操作手册,别当垃圾桶。
  • 会话在 per-agent SQLite;旧 JSONL 要 doctor --fix 导入。
  • 记忆是纯 Markdown(USER.md/MEMORY.md/memory/*.md/DREAMS.md),加 SQLite 索引,没有隐藏状态。
  • 冲写与做梦是自动巩固;MEMORY.md 要保持策展级精简。
  • 多 agent 绝不复用 agentDir;多人场景先定 dmScope。

下一篇讲工具、技能与插件:三者的边界、"工具在模型调用前就被裁掉"意味着什么,以及为什么第三方 skill 要当作不可信代码。