犀牛鸟 2026 研究笔记 estelledc.github.io

Profile 与 User Memory 边界

Profile/MCP/Memory Bank 基础:MCP 记忆集成层 Claude Code 记忆机制:精读: Claude Code 记忆系统 Codex 记忆机制:精读: Codex 记忆系统 Coding Agent 横评:Coding Agent 记忆横评

调研元信息

项目
调研日期 2026-06-22
涉及研究轴 C(Profile 层)为主
前置阅读 deep-dive-mcp-memory-bridge.md Profile 对比章节
证据等级 [源码] [文档] [社区] 混合

一句话定位

Profile(CLAUDE.md / AGENTS.md / .cursor/rules)是开发者写给 Agent 的行为规范,User Memory 是Agent 自己从对话中学到的知识——两者在概念上清晰,在实践中经常混淆,而 Memory Bank 社区模式更是刻意模糊了这条边界 [社区]

记忆类型标注

类型 涉及 说明
Working 不涉及 session 上下文
Profile 核心 CLAUDE.md / AGENTS.md / Rules
User 核心 memdir / Codex memories / Cursor Memories
External 间接 Memory Bank 用 Profile 模拟 External

日常类比

Profile 就像一个公司的员工手册——写着”代码用 4 空格缩进”“所有 API 必须有错误处理”“先写测试再写实现”。这是规范,不会因为你做了某件事就自动更新。

User Memory 则像你的个人工作笔记——”张三偏好 TypeScript”“这个项目的数据库用 PostgreSQL”“上次那个 bug 的根因是连接池泄漏”。这是从工作经验中提炼的知识,会随着交互自动积累。

混淆场景:如果你把”上次那个 bug 的根因”写进员工手册(Profile),下次换了新人也能看到——但员工手册会越来越厚,而且”上次那个 bug”的上下文可能已经过时。这就是 Memory Bank 模式的根本问题。


概念模型:Profile ≠ User Memory

flowchart TB
    subgraph profile["Profile(行为规范)"]
        direction TB
        P1["写入者:人工<br/>更新频率:低<br/>内容:'应该怎么做'"]
        P2["CLAUDE.md<br/>AGENTS.md<br/>.cursor/rules<br/>CONVENTIONS.md"]
    end

    subgraph user_mem["User Memory(学到的知识)"]
        direction TB
        U1["写入者:Agent/系统<br/>更新频率:高<br/>内容:'学到了什么'"]
        U2["memdir<br/>~/.codex/memories/<br/>Cursor Memories"]
    end

    subgraph confusion["混淆地带"]
        direction TB
        C1["Memory Bank<br/>用 Profile 文件模拟 User Memory"]
        C2["在 CLAUDE.md 写 'remember to...'<br/>期望被 extractMemories 提取"]
    end

    profile --> AGENT[Agent]
    user_mem --> AGENT
    confusion -.->|"不推荐"| AGENT

三个经典误区

误区 1:把动态知识写进 Profile

错误做法:在 CLAUDE.md 里写 “当前正在重构 auth 模块,注意 JWT 过期时间改为 1 小时”。

问题:Profile 文件通常受版本控制,所有团队成员共享。”当前正在重构 auth 模块”是临时状态,重构完成后这句话就过时了——但如果没人记得删掉它,Agent 会一直以为 auth 模块在重构中 [社区]

正确做法:这类信息应该在 User Memory(如 Claude Code 的 memdir)中自然存在,并通过 staleness 机制在过期后自动降权。Claude Code 的 memoryAge 模块就是为此设计的——超过 1 天的记忆会被自动加上 <system-reminder> 提示模型注意时效 [源码]

误区 2:期望 Profile 内容被 extractMemories 提取

错误做法:在 CLAUDE.md 写 “remember that this project uses pnpm not npm”,然后期望 extractMemories 把它存到 memdir。

问题:Claude Code 的 extractMemories 明确将 “CLAUDE.md 已有的内容”列为不应保存的信息——因为 Profile 已经在 system prompt 中了,重复存到 memdir 是浪费 [源码]

正确做法:CLAUDE.md 负责规范(”用 pnpm”),memdir 负责上下文(”上次用户试过 npm 遇到了 peer dependency 冲突”)。

误区 3:Memory Bank 就是 User Memory

错误做法:认为用 Memory Bank 文件(activeContext.md、progress.md 等)就等于有了 User Memory。

问题:Memory Bank 的三个根本缺陷——无嵌入/无语义检索(全量注入)、无冲突合并(多 session 竞态)、人工触发(遗忘=丢失)——使它在本质上仍然是 Profile 的变种,只是内容更动态而已 [社区]

对照:Claude Code 的 memdir 有 Sonnet 语义检索、hasMemoryWritesSince 竞态保护、自动触发的 extractMemories hook——这些都是 Memory Bank 缺失的基础设施。


AGENTS.md 发现链深度分析

Codex 的 AGENTS.md 发现链在 agents_md.rs 中实现,是 Profile 系统中设计最精巧的链式机制 [源码]

发现流程

  1. 从 cwd 向上逐级查找 .git(或其他项目根标记),确定项目根
  2. 从项目根到 cwd 路径上的每一级目录,按优先级查找:AGENTS.override.mdAGENTS.md → fallback(如 CLAUDE.md
  3. 用户级 instructions 排最前,各级内容用 --- project-doc --- 分隔符拼接

设计亮点AGENTS.override.md 类似 .env.local——可以 gitignore,不影响团队配置。这解决了 Profile 系统的一个痛点:个人偏好(如”我用 vim keybinding”)不应该提交到团队 repo,但又需要 Agent 知道。

与 CLAUDE.md 的差异:CLAUDE.md 虽然也支持链式发现和 CLAUDE.local.md 本地覆盖,但其路径布局更复杂(全局 / 项目根 / .claude/ / 子目录 / local),而 AGENTS.md 的设计更简洁——只有三层优先级,且作为 30+ 工具的联合标准有更广的兼容性 [源码]


Cursor Rules 四种 Apply 模式

详细对比见 bridge 篇

Cursor 的 .cursor/rules/*.mdc 提供了最灵活的条件注入策略,四种模式形成了从”始终注入”到”按需注入”的完整光谱 [文档]

flowchart LR
    ALWAYS["Always Apply<br/>始终注入<br/>= CLAUDE.md"] --> GLOBS["Globs<br/>文件匹配注入<br/>= 无对应"]
    GLOBS --> DESC["Description<br/>Agent 自判注入<br/>≈ findRelevantMemories"]
    DESC --> MANUAL["Manual<br/>@引用<br/>= 无对应"]

关键观察:Description 模式让 Agent 读规则描述后自行判断是否拉入上下文——这在概念上接近 Claude Code 的 findRelevantMemories(用 LLM 判断相关性),只是作用对象不同(Cursor 判断的是规则,Claude Code 判断的是记忆文件) [文档]


边界判断决策树

面对一条新信息,应该放在 Profile 还是 User Memory?

flowchart TB
    START[新信息] --> Q1{是否跨 session 有用?}
    Q1 -->|否| DAILY[放 daily/<br/>(会话内用完即弃)]
    Q1 -->|是| Q2{是否所有团队成员<br/>都应遵守?}
    Q2 -->|是| Q3{是否变化频率低?<br/>(月级别以上)}
    Q3 -->|是| PROFILE["Profile<br/>CLAUDE.md / AGENTS.md / Rules"]
    Q3 -->|否| ISSUE["考虑拆分:<br/>稳定部分 → Profile<br/>动态部分 → User Memory"]
    Q2 -->|否| Q4{是否可从代码/环境推导?}
    Q4 -->|是| SKIP["不保存<br/>(extractMemories 也会跳过)"]
    Q4 -->|否| USER_MEM["User Memory<br/>memdir / Codex memories"]

各 Agent 的 Profile-Memory 边界实践

Agent Profile 和 User Memory 的代码级边界 是否有防重复机制
Claude Code extractMemories 明确排除 CLAUDE.md 已有内容 [源码] 是——主代理写过记忆时提取代理跳过
Codex Phase1 过滤 AGENTS.md 指令和 developer 消息 [源码] 是——Phase2 consolidation 做去重合并
OpenClaw flush prompt 标注 MEMORY.md/SOUL.md 为只读 [源码] 部分——dreaming 晋升时有评分
Cursor Memories 记录编程偏好,Rules 记录项目规范 [文档] 不确定
Cline/Aider 无 User Memory,不存在边界问题 不适用

Memory Bank:权宜之计的教训

Memory Bank 模式的存在和演变为整个 Profile-Memory 边界讨论提供了一个真实案例 [社区]

起因:Cursor 1.0 之前没有 User Memory,Cline 至今没有。开发者需要跨 session 持久化项目上下文,于是用 Profile 文件来模拟。

结果:6 个 markdown 文件(projectBrief → progress)形成了一个类似 Wiki 的结构,但继承了 Profile 的所有缺陷——无检索、无冲突合并、人工触发。

教训

  1. 需求是真实的——跨 session 持久化是刚需,Coding Agent 不能忽视
  2. Profile 不是正确的容器——静态文件 + 全量注入无法扩展
  3. MCP 是正确方向——让 Cline 接入 supermemory 或 DB-Agent-Memory 的 MCP Server,可以获得 Memory Bank 缺失的所有能力(检索、自动提取、冲突处理)

局限性

  1. AGENTS.md 源码分析基于 Codex 仓库:其他采用 AGENTS.md 标准的 30+ 工具可能有不同实现 [源码]
  2. Cursor Memories Beta 内部机制不透明:云端实现细节无法验证 [文档]
  3. Memory Bank 分析基于社区文档和 Cline 源码:不同社区变体可能有差异 [社区]

证据等级汇总

论点 证据等级
extractMemories 排除 CLAUDE.md 内容 [源码] deep-dive-claude-code-memory.md
AGENTS.md 发现链实现 [源码] agents_md.rs
Cursor Rules 四种 apply 模式 [文档] cursor.com/docs
Memory Bank 社区模式分析 [社区] + [源码] Cline
Codex Phase1 过滤 AGENTS.md [源码] deep-dive-codex-memory.md
三个经典误区 [源码][社区] 推导