1. 为什么 Agent 的“记忆”问题值得单独拿出来聊做 AI Agent 开发的人绕不开一个坎记忆。你让 Agent 帮你改一个跨十几个文件的重构任务它干到一半忘了前面定的命名规范你昨天跟它聊过的项目架构今天开新会话它一脸茫然你反复强调“这个项目用 pnpm 不用 npm”下次它照样给你敲npm install。这些问题的本质都一样——Agent 没有持久化记忆每次会话都是失忆重启。行业里解决这个问题的主流方案是向量库检索把历史对话、代码片段、文档切块做 embedding存进向量数据库需要的时候做相似度检索召回。这条路成熟、通用但代价也明显——你得维护一套 embedding 流水线得选向量库Chroma、Qdrant、Milvus、pgvector……得处理切块策略、召回精度、embedding 模型版本漂移还得为每次读写付 token 和延迟成本。对于一个只是想“记住项目约定”的编码 Agent 来说这套东西重得有点离谱。Codex 和 Claude Code 这两个当下最火的编码 Agent走的是另一条路不用向量库用文件系统做持久化记忆。它们的思路出奇一致——把记忆写成人类可读的 Markdown 文件放在项目目录里靠 Agent 自己按需读取。听起来很“土”但实测下来极其有效而且可解释、可版本控制、可手工编辑。这篇就围绕这两条路线把它们的记忆机制拆开讲清楚顺带把我在实际项目里踩过的坑和总结的配置方法一并交代。适合谁看正在做 Agent 开发、想给自己的 Agent 加持久化记忆但不想上向量库的工程师已经在用 Codex 或 Claude Code、想把它们的记忆能力用透的开发者以及单纯好奇“不靠向量检索Agent 怎么记住东西”的技术爱好者。全文基于我自己的实操和常见工程实践补充涉及具体参数和文件结构的地方会给出可直接抄的模板。2. 两条路线的整体设计思路拆解2.1 向量库路线 vs 文件记忆路线到底差在哪先把两条路线的本质差异摆清楚后面才好理解 Codex 和 Claude Code 为什么这么设计。向量库路线的核心假设是记忆量可能非常大必须靠语义检索来压缩召回。所以它的流程是“写入时切块embedding读取时相似度检索”。优点是能处理海量非结构化记忆召回靠语义而非关键词。缺点是整条链路复杂embedding 质量、切块边界、召回阈值任何一个环节出问题Agent 就会“记错”或“记不起来”而且你很难调试——你没法直接打开一个向量看看它到底存了什么。文件记忆路线的核心假设是对编码 Agent 来说真正需要长期记住的东西其实不多而且高度结构化。项目用什么包管理器、代码风格约定、目录结构、常用命令、踩过的坑——这些东西加起来也就几百到几千字完全没必要上向量检索。直接写成 MarkdownAgent 每次启动读一遍或者按需读取就够了。优点是零基础设施、完全可解释、可 git 管理、可人工编辑。缺点是记忆容量受上下文窗口限制不能无限膨胀。提示文件记忆路线并不是“低配版向量库”它是针对特定场景的另一种工程取舍。编码 Agent 的记忆特点是“量小、结构强、变更频繁、需要人机共读”这恰好是文件系统的强项。2.2 Codex 的记忆设计AGENTS.md 作为项目级契约Codex 的记忆机制核心是一个叫AGENTS.md的文件。它的定位很明确放在项目根目录作为 Agent 的“项目说明书”。Codex 在启动会话、执行任务前会读取这个文件把它作为系统级上下文注入。这个设计的巧妙之处在于分层。Codex 支持多级 AGENTS.md项目根目录一个子目录可以各有一个用户主目录还可以有一个全局的。Agent 会根据当前操作的文件路径把沿途所有层级的 AGENTS.md 合并起来。这意味着你可以把“全局偏好”放在主目录“项目约定”放在根目录“某个子模块的特殊规则”放在子目录各管各的互不干扰。为什么用 Markdown 而不是 JSON/YAML因为这份文件是给人看的。新加入项目的工程师读一遍 AGENTS.md 就知道这个项目的约定Agent 读同一份文件就能遵守同样的约定。人机共读一份契约这是文件记忆路线最优雅的地方。2.3 Claude Code 的记忆设计CLAUDE.md 加自动记忆Claude Code 走的是类似但更“主动”的路线。它的核心记忆文件是CLAUDE.md同样放在项目根目录同样支持多级项目级、用户级、企业级。但 Claude Code 多了一层机制自动记忆写入。当你在会话里说“记住这个项目用 pnpm”Claude Code 可以主动把这条信息写进 CLAUDE.md而不需要你手动编辑。它还支持用#开头的快捷指令来触发记忆写入。这个“Agent 自己维护记忆文件”的能力是它和 Codex 最大的区别——Codex 更偏向“你写好契约我遵守”Claude Code 更偏向“我们一起维护这份契约”。另外 Claude Code 的记忆文件支持path/to/file的引用语法可以把其他文件的内容导入进来。这意味着你可以把记忆拆成多个文件比如CLAUDE.md引用docs/conventions.md和docs/commands.md保持主文件清爽。这个设计在大型项目里非常实用。2.4 为什么两者都放弃了向量库把两者的设计放一起看会发现它们放弃向量库的理由是共通的第一编码场景的记忆是“契约型”而非“检索型”。你不需要“从一万条历史对话里找出最相关的那条”你需要的是“每次都无条件遵守这几条规则”。契约型记忆用文件最合适检索型记忆才需要向量库。第二可解释性压倒一切。Agent 行为出问题时你打开 AGENTS.md 或 CLAUDE.md 一眼就能看出它被灌了什么上下文。向量库你做不到这一点。第三版本控制天然契合。记忆文件进 git谁改了什么、什么时候改的、为什么改全都有记录。团队协作时这份记忆是共享的、可 review 的。第四成本。没有 embedding 调用没有向量库运维没有额外延迟。对个人开发者和小团队来说这是实打实的省钱省心。3. 核心细节解析与实操要点3.1 AGENTS.md 的层级合并规则与写法Codex 读取 AGENTS.md 的规则我实测下来大致是这样的从当前工作目录向上逐级查找直到项目根或用户主目录把找到的所有 AGENTS.md 按“从通用到具体”的顺序拼接。也就是说越靠近当前目录的规则优先级越高越具体的规则覆盖越通用的规则。基于这个规则我建议的写法是用户主目录的 AGENTS.md放跨项目的个人偏好。比如“回答用中文”“代码注释用英文”“优先给可运行的完整代码而不是片段”。项目根目录的 AGENTS.md放项目级约定。比如技术栈、包管理器、目录结构、构建命令、测试命令、代码风格。子目录的 AGENTS.md放模块级特殊规则。比如“这个目录下的代码是自动生成的不要手改”“这个模块用旧版 API不要升级”。一个我常用的项目根 AGENTS.md 模板长这样# 项目约定 ## 技术栈 - 语言TypeScript 5.x - 运行时Node.js 20 - 包管理器pnpm禁止使用 npm 或 yarn - 框架Next.js 14 App Router ## 常用命令 - 安装依赖pnpm install - 开发pnpm dev - 构建pnpm build - 测试pnpm test - 类型检查pnpm typecheck ## 代码风格 - 使用 2 空格缩进 - 组件文件用 PascalCase工具函数用 camelCase - 禁止使用 any必要时用 unknown 加类型守卫 - 所有导出函数必须有 JSDoc 注释 ## 目录结构 - src/app页面路由 - src/components可复用组件 - src/lib工具函数 - src/types全局类型定义 ## 注意事项 - 修改数据库 schema 前必须先写 migration - 不要直接修改 node_modules - 提交前必须跑 pnpm typecheck 和 pnpm test这份文件不长但信息密度极高。Agent 读完它基本就不会犯“用错包管理器”“乱放文件”“不写注释”这类低级错误。注意AGENTS.md 不是越长越好。我见过有人往里塞了几千行的详细文档结果 Agent 每次启动都要吃掉大量上下文反而挤占了真正干活的空间。经验值是控制在 500 行以内超过就拆到子目录或引用文件里。3.2 CLAUDE.md 的自动记忆与引用语法Claude Code 的 CLAUDE.md 在写法上和 AGENTS.md 类似但多了两个实用特性。第一个是自动记忆写入。当你在会话里明确说“记住……”时Claude Code 会把这条信息追加到 CLAUDE.md。这个功能的好处是记忆的积累是“顺手”的——你不用专门停下来编辑文件。但坏处也明显如果不加控制CLAUDE.md 会被塞进一堆零碎的、临时的、甚至互相矛盾的信息。我的做法是定期 review 这个文件把临时信息清理掉只保留真正的长期约定。第二个是引用语法。你可以在 CLAUDE.md 里写docs/conventions.mdClaude Code 会把那个文件的内容也读进来。这让记忆可以模块化# 项目记忆 ## 核心约定 docs/conventions.md ## 常用命令 docs/commands.md ## 已知问题 docs/known-issues.md主文件保持精简具体内容分散到各个文档里。这样既方便维护也方便不同的人负责不同的文档。3.3 记忆文件的“写入时机”与“读取时机”这是很多人忽略的关键点。记忆文件不是写完就完事什么时候写、什么时候读决定了它到底有没有用。写入时机上我的经验是三类内容值得写进记忆文件稳定不变的约定技术栈、包管理器、代码风格。这类内容一次写好长期不动。反复纠正的错误如果 Agent 连续两次犯同一个错就该把纠正写进记忆避免第三次。项目特有的知识比如“这个 API 的返回格式和文档不一致实际是 xxx”“这个测试环境需要先跑一个初始化脚本”。读取时机上Codex 和 Claude Code 都是会话启动时自动读取。但这里有个细节如果你的记忆文件很大每次启动都全量读取会浪费上下文。所以更好的做法是把“必须每次遵守的”放主文件“按需查阅的”放引用文件让 Agent 在需要时再读。提示我习惯在记忆文件顶部放一个“快速索引”列出这个文件包含哪些主题方便 Agent 和人都能快速定位。比如“本文件包含技术栈、命令、风格、目录结构、注意事项”。3.4 记忆的“冲突处理”与“优先级”多级记忆文件必然会有冲突。比如用户级说“注释用中文”项目级说“注释用英文”Agent 听谁的实测下来两者的处理逻辑都是就近优先——越具体的规则覆盖越通用的规则。所以项目级覆盖用户级子目录级覆盖项目级。这个逻辑和 CSS 的层叠、Git 的配置层级是一个思路符合直觉。但这里有个坑如果冲突是“隐性的”Agent 可能不会主动告诉你它选了哪个。比如用户级说“用 npm”项目级说“用 pnpm”Agent 大概率会用 pnpm但它不会提醒你“我忽略了用户级的 npm 约定”。所以我的建议是记忆文件里的规则尽量别冲突如果确实需要覆盖在项目级文件里显式写一句“本项目覆盖全局约定使用 pnpm”。4. 实操过程与核心环节实现4.1 从零给一个项目配置 Codex 记忆假设你有一个已有的 TypeScript 项目想给它配上 Codex 记忆。完整流程如下。第一步在项目根目录创建 AGENTS.md。先别急着写内容先花十分钟梳理这个项目“新人入职需要知道什么”。把这些问题列出来用什么语言和框架怎么装依赖怎么跑起来怎么测试代码放哪有什么坑这份清单就是 AGENTS.md 的骨架。第二步按上一节的模板填充内容。注意用祈使句和明确指令不要用模糊描述。写“使用 pnpm”不要写“建议使用 pnpm”写“禁止使用 any”不要写“尽量避免 any”。Agent 对明确指令的遵守度远高于模糊建议。第三步在子目录按需添加 AGENTS.md。比如src/legacy/AGENTS.md写“此目录为遗留代码使用旧版 API不要重构只做最小改动”。第四步验证。开一个新会话问 Agent“这个项目用什么包管理器”看它答得对不对。再让它做一个简单任务观察它是否遵守了代码风格约定。如果发现它没遵守某条规则检查那条规则是不是写得不够明确。第五步迭代。记忆文件不是一次写完的。用一段时间后把 Agent 反复犯的错补进去把已经过时的规则删掉。4.2 给 Claude Code 配置带引用的记忆体系Claude Code 的配置流程类似但可以玩得更细。我的做法是建一个docs/目录专门放记忆文档docs/ conventions.md # 代码风格约定 commands.md # 常用命令 architecture.md # 架构说明 known-issues.md # 已知问题和坑然后 CLAUDE.md 只做引用和放最核心的几条# 项目记忆 本项目使用 TypeScript Next.js包管理器为 pnpm。 ## 详细文档 docs/conventions.md docs/commands.md docs/architecture.md docs/known-issues.md ## 最高优先级规则 - 禁止使用 npm 或 yarn - 提交前必须跑 pnpm typecheck - 不要修改 src/generated 下的任何文件这样主文件很短Agent 启动时先读这几条硬规则需要细节时再读引用文档。实测下来这种结构在大型项目里比单文件效果好很多因为主文件的“硬规则”不会被淹没在细节里。4.3 用记忆文件解决“跨会话一致性”问题记忆文件最直接的价值就是解决跨会话一致性。我举一个真实场景。之前做一个重构任务需要把项目里所有的moment.js换成dayjs。这个任务跨了三天每天开新会话。如果没有记忆文件我每天都要重新跟 Agent 解释“我们在做 moment 到 dayjs 的迁移已经改了哪些文件还剩哪些”。有了记忆文件我在 CLAUDE.md 里加一段## 进行中的任务 - moment.js 迁移到 dayjs进行中 - 已完成src/utils/date.ts, src/components/Calendar.tsx - 待处理src/components/DatePicker.tsx, src/lib/format.ts - 注意dayjs 需要手动引入插件参考 src/utils/date.ts 的写法第二天开新会话Agent 读完这段就知道上下文直接接着干。任务完成后把这段删掉即可。这个用法把记忆文件当成了“任务状态板”非常实用。4.4 记忆文件的版本控制与团队协作记忆文件进 git 之后团队协作的玩法就打开了。第一记忆变更可以 review。谁改了项目约定通过 PR 走一遍 review避免有人偷偷改了规则导致 Agent 行为突变。第二记忆是团队共享的。新人 clone 项目Agent 自动就懂项目约定不需要口口相传。第三可以追溯。Agent 某天行为异常git log AGENTS.md一看原来是昨天有人改了约定。我的团队实践是AGENTS.md 或 CLAUDE.md 的修改走和代码一样的 PR 流程重要变更在 PR 描述里说明原因。这样记忆文件就成了项目文档的一部分而不是某个人的私人配置。注意不要把敏感信息写进记忆文件。API key、内部地址、个人 token 这些东西绝对不能进 git。记忆文件里只放“约定”和“知识”不放“秘密”。5. 常见问题与排查技巧实录5.1 Agent 不遵守记忆文件怎么办这是最高频的问题。排查思路按顺序来先确认文件位置对不对。Codex 找 AGENTS.mdClaude Code 找 CLAUDE.md文件名写错就白搭。再确认文件在不在 Agent 的工作目录范围内——如果你在子目录启动 Agent它可能读不到根目录的文件。然后检查规则写得够不够明确。“尽量用 pnpm”这种模糊表述Agent 可能忽略“必须使用 pnpm禁止 npm 和 yarn”这种明确指令遵守率高得多。最后看是不是被更具体的规则覆盖了。子目录的 AGENTS.md 可能覆盖了根目录的规则检查一下沿途所有层级的文件。5.2 记忆文件太大导致上下文被挤占记忆文件吃上下文是文件记忆路线的固有代价。排查方法看 Agent 启动后还剩多少上下文可用。如果记忆文件占了超过 20%就该瘦身了。瘦身策略把“必须每次遵守的”留主文件“按需查阅的”移到引用文件删掉过时的、临时的内容把详细文档拆到子目录。我的经验是主记忆文件控制在 200 行以内引用文件可以长但只在需要时读。5.3 多级记忆冲突导致行为诡异前面提过多级记忆冲突时 Agent 就近优先但不会主动提示。排查方法把所有层级的记忆文件列出来逐条对比找出冲突项。解决方法是显式声明覆盖关系在具体层级的文件里写清楚“本层级覆盖上级的某某规则”。5.4 自动记忆写入把文件搞乱Claude Code 的自动记忆写入很方便但容易积累垃圾。排查方法定期 review CLAUDE.md看有没有重复的、矛盾的、临时的内容。解决方法是养成习惯每周清理一次把临时信息删掉把重复信息合并。5.5 常见问题速查表问题现象可能原因排查方向解决方法Agent 完全不读记忆文件名错/位置错确认文件名和启动目录改对文件名放到正确目录部分规则不生效规则表述模糊检查规则是否用明确指令改成祈使句加“必须/禁止”规则被忽略被下级文件覆盖检查沿途所有层级显式声明覆盖关系上下文不够用记忆文件过大看记忆占上下文比例瘦身拆分到引用文件行为前后矛盾记忆文件有冲突逐条对比各层级删除或合并冲突项自动记忆变乱临时信息堆积review 记忆文件定期清理只留长期约定5.6 几个我踩过的坑第一个坑在记忆文件里写“建议”而不是“规则”。我早期写“建议使用函数式组件”结果 Agent 时不时用 class 组件。改成“必须使用函数式组件禁止 class 组件”之后问题消失。第二个坑记忆文件放在错误的位置。我有次把 AGENTS.md 放在了src/下而不是项目根结果在根目录启动 Agent 时它读不到。记住项目级记忆放根目录。第三个坑忘了清理进行中的任务记录。任务完成后没删Agent 下次启动还以为任务在进行中继续按旧状态干活。养成任务完成后立即清理的习惯。第四个坑把秘密写进记忆文件。这个最危险一旦进 git 就泄露了。记忆文件只放约定和知识秘密用环境变量管理。6. 两条路线的选型建议与扩展玩法6.1 什么时候选 Codex什么时候选 Claude Code从记忆机制的角度看两者的差异其实不大都是文件记忆路线。选型更多看其他因素。如果你偏好“契约式”的记忆管理——自己写好规则Agent 严格遵守不喜欢 Agent 自作主张改文件——Codex 的 AGENTS.md 更符合这个心智模型。如果你偏好“协作式”的记忆管理——希望 Agent 能主动记录、能引用多个文档、记忆体系更灵活——Claude Code 的 CLAUDE.md 加自动记忆和引用语法更合适。实际项目里我两个都用过最后的选择往往取决于团队已经在用哪个、以及个人对自动记忆的接受度。记忆机制本身不构成决定性差异。6.2 把文件记忆和向量库结合起来的混合玩法文件记忆路线不是要取代向量库两者可以结合。我的做法是契约型记忆用文件检索型记忆用向量库。项目约定、代码风格、常用命令这些“每次都要遵守”的放 AGENTS.md 或 CLAUDE.md。历史对话、大量文档、代码库全量索引这些“需要时检索”的还是走向量库。Agent 启动时读文件记忆拿到硬规则干活过程中按需查向量库拿参考资料。这样既保留了文件记忆的可解释性和零成本又保留了向量库处理海量记忆的能力。对复杂项目来说这是更务实的方案。6.3 记忆文件的进阶玩法动态生成与自动同步记忆文件不一定手写。我试过几种自动化的玩法一是从代码生成。写个脚本扫描package.json、tsconfig.json、目录结构自动生成 AGENTS.md 的技术栈和命令部分。代码变了记忆自动更新。二是从 CI 同步。把 CI 里跑的检查命令自动写进记忆文件保证 Agent 知道的命令和 CI 实际跑的一致。三是从 issue 同步。把已知问题从 issue tracker 同步到known-issues.mdAgent 干活时就能避开这些坑。这些玩法需要一点脚本工作但对长期维护的项目来说收益很明显——记忆永远和项目实际状态同步不会过时。6.4 记忆文件写什么、不写什么最后分享一个我总结的“写与不写”清单这是用好文件记忆的关键。该写的技术栈和版本、包管理器、常用命令、代码风格、目录结构、架构说明、已知问题、进行中的任务、项目特有的坑。不该写的秘密和凭证、临时调试信息、个人偏好除非放用户级、大段复制的文档用引用代替、会频繁变动的细节放引用文件、和项目无关的闲聊。这个清单的核心逻辑是记忆文件是“契约”不是“日记”。它记录的是“这个项目怎么运作”不是“我们聊过什么”。守住这条线记忆文件就能长期保持有用而不是变成一堆没人看的垃圾。我个人在实际操作中的体会是文件记忆路线的最大价值不在于“省了向量库”而在于它把 Agent 的记忆变成了团队可见、可 review、可版本控制的工程资产。向量库里的记忆是黑盒文件里的记忆是白盒。对需要长期维护、多人协作的项目来说白盒的价值远超那点检索精度的差异。如果你正在给 Agent 加记忆不妨先从一份 AGENTS.md 或 CLAUDE.md 开始用起来之后再决定要不要上向量库——很多时候你会发现一份写好的 Markdown 就够了。
阅读完成 · 觉得有帮助?