
做 AI 辅助开发这两年我体会最深的一句话是大模型天生是“无状态”的。它不记得上个会话里你定过的命名规则不记得项目为什么废弃了某个方案你只要新开一个对话它就立刻变回那个聪明但零记忆的实习生。于是很长一段时间我每天都在做一件毫无成就感的事——把项目背景、技术栈、工程约定、踩坑禁忌事无巨细地重新粘贴一遍。直到我把 Memory 工程认真捡起来用一份AGENTS.md声明式配置把项目的长期记忆外置才真正感觉 AI 编程的范式从“每次重新解释”切换到了“一进项目就懂你”。这篇文章就聊这个转变无状态模型到底卡在哪、Memory 工程怎么补位、AGENTS.md为什么能成为最轻量的记忆载体以及我自己从踩坑到落地的完整过程。适合被“每次开工先写大段提示词”折磨过的开发者也适合想给团队 AI 辅助开发定一套规矩的技术负责人。1. 先看清问题无状态模型是怎么“逼”出 Memory 工程的1.1 无状态模型的本质一次调用一次失忆很多人以为 AI 编程助手“有记忆”其实这是个错觉。大模型本身是一个纯粹的映射函数你给它一段文本它预测下一段最合理的文本。它没有内部状态没有日记本没有“上次对话结束后我记住了什么”。我们平时用聊天工具感觉它有记忆是因为外层应用把所有历史消息重新拼接、每次请求都塞给模型看。一旦超出长度限制最早的消息就无声无息地消失了。放在 AI 编程场景里这个问题会被放大好几倍。代码项目的信息密度极高——技术栈选型、目录职责、接口返回结构、命名风格、构建工具版本、已知坑位……这些知识散落在代码里、PR 评论里、README 里还有开发者的脑子里。模型看不到就只能靠你张口告诉它。你告诉它一次它能基于这一次会话干活但明天新开一个窗口它又是一张白纸。用生活类比就是你天天带同一个实习生他每天早上都会把你昨天讲过的东西忘得一干二净。你讲得多了会烦讲漏了他就犯低级错误。无状态模型就是这个完美符合“金鱼记忆”设定的实习生。1.2 上下文窗口不是记忆只是临时草稿纸既然模型没有记忆那我把所有有效信息都塞进上下文窗口不就行了这是很多人一开始的本能反应也是我走过的弯路。上下文窗口有两个硬伤。第一是长度上限工程规模稍微大一点光package.json、requirements.txt、后端路由文件就能吃掉几千个 token要把整个项目塞进去既不现实也浪费钱。第二是注意力稀释窗口越大模型在回答具体问题时反而越容易忽略远处的关键约束。你在开头写的“接口字段统一用下划线命名”到第 3000 行对话时已经被大量无关内容稀释成噪声了。你可以把上下文窗口理解成一张临时草稿纸它能记下当前对话里发生的事但一翻页就没了而且写得太满时真正重要的信息反而看不清。它本质上是一个工作台而不是仓库。跨会话的知识必须放到工作台之外的地方去。1.3 Memory 工程把知识从人脑和对话里搬进项目当“手动粘贴背景”和“塞满上下文窗口”两条路都走到瓶颈时就会自然转向第三个方向主动为模型构建外置记忆。这就是标题里“Memory 工程”的含义——不是给模型加脑机接口而是用工程手段管理 AI 能读取的持久知识保证它在恰当的时间、以恰当的形式拿到恰当的信息。Memory 工程要回答三个问题存什么哪些项目知识值得固化、怎么存用什么格式和载体、怎么读模型如何自动加载、加载后如何不产生噪声。围绕这三个问题业界分化出了很多方案向量数据库、语义检索、基于 RAG 的文档问答、对话历史摘要等等。但对绝大多数普通项目而言这些方案太重了维护成本远高于收益。真正被广泛接受的答案反而是一份最朴素的声明式配置文件——AGENTS.md。2. 认识主角AGENTS.md 和声明式配置的设计哲学2.1 一份写在项目根目录的“入职手册”AGENTS.md本质上是一份 Markdown 文件放在项目仓库的根目录有时也放在子目录里。主流 AI 编程工具在启动会话、读取仓库时会自动发现并加载这类文件把它作为模型的“项目背景板”。你可以把它理解成一份给 AI 的入职手册。新人入职第一天会拿到一本手册上面写着“我们公司是干什么的、技术栈是什么、代码怎么组织、提交信息怎么写、上线的红线是什么”。AGENTS.md就是同一件事只不过读者从人换成了模型。它不需要像 README 那样面向用户做漂亮的产品介绍它更像工程团队的内部 Wiki只写给 AI 和未来的维护者看。我第一次意识到这东西的分量是在一次调试里我新开一个会话让 AI 给我查一个用户列表分页接口的 bug它居然建议我去改一个根本不负责这块逻辑的服务层文件。因为它是从零认识这个项目的只能凭文件名猜用途。那一刻我意识到不是 AI 能力不够而是我没给它“入职培训”。2.2 为什么“声明式”比“命令式”更适合大模型AGENTS.md这类配置被称为“声明式配置”这个定语很关键。声明式和命令式的差别我这样理解命令式告诉 AI“你要怎么做”先读src/目录再打开user_service.py然后按第 3 步修改……声明式告诉 AI“项目是什么”src/services/user_service.py负责用户领域逻辑依赖postgres接口返回字段采用下划线命名……大模型是从海量无语义文本里训练出来的它们非常擅长从“事实陈述”里自己推导出该做什么。反过来冗长、琐碎、层层嵌套的命令式指令反而会让模型在执行时顾此失彼——它记不住第 1 步和第 7 步之间的关系遇到指令含糊的地方就开始自己编。声明式配置制造的阅读负担也小得多。模型读“该项目是 FastAPI 后端返回 JSON错误统一走{ code: 1, msg: ... }结构”比读“后端必须返回统一错误格式禁止直接抛异常如果抛异常必须先 catch 再转成响应”更稳。前者是在描述一个事实后者是在提一串要求而模型理解事实的能力远强于零散指令的逐条执行能力。2.3 从特设规则到跨工具共识早期各个 AI 编程工具有各自的配置约定有的是全局规则文件有的是项目内.rules格式五花八门。慢慢地社区开始形成一种偏向通用化的约定AGENTS.md正在成为越来越多工具默认识别的文件名同时很多工具也保留了各自的别名兼容策略。这对使用者来说是个好消息。一份AGENTS.md写好了就随仓库存在不管是个人项目还是团队协作不管是哪个 AI 编码助手都能读到。你不用为了换工具而重写提示词也不用担心配置锁死在某个私有生态里。从“为工具写规则”到“为项目写记忆”这正是范式转换里很关键的一步。3. 实操落地写好一份能让 AI “少吵三次架”的 AGENTS.md3.1 六个必写板块每个板块背后都是一个真实痛点结合我自己的经验一份高质量AGENTS.md至少需要有六个板块不一定要很长但每一块都要对应一类实际会踩的问题。项目一句话定位。写清楚这个项目是给谁用的、做什么的。模型如果连项目身份都不知道很容易给出“通用但无用”的建议比如给内部管理后台推荐 SEO 方案给纯后端服务推荐加前端模板。一句话就够但要准确。技术栈与版本约束。这一块解决的是“AI 用错技术”的问题。比如项目是 Vue 3 TypeScriptAI 建议你写 Vue 2 的Options API后端是 FastAPIAI 给你生成 Flask 的app.route。明确写出技术栈和版本可以直接砍掉这类低级错误。目录结构与职责边界。告诉模型哪些目录负责什么、能改哪些、不能碰哪些。比如 “src/components只放展示组件业务逻辑进src/composables”、“数据库迁移文件不要手动改”。没有这条AI 经常乱改文件或者把视图层逻辑塞进工具函数里。代码风格与命名约定。模型默认的生成风格是“最流行的写法”但不一定是你们项目的写法。字段命名是 camelCase 还是 snake_case组件是 .vue 单文件还是模板字符串异常处理是断言还是返回码——这些偏好在几十行代码后就会产生明显的违和感必须在开头固化成声明。常用命令与流程。测试命令、启动命令、构建命令、数据库迁移命令、代码格式化命令。AI 不知道这些就会瞎猜。我就见过它建议用户手动改数据库表结构的场面只因为配置里没写 “迁移必须执行alembic upgrade head”。已知陷阱与禁忌。这一块是“用血泪换来的经验”包含项目里最容易出错的地方。比如“prod环境禁止直接改数据库”“不要在BaseModel里加公用字段”“config.json是生成文件手动修改会被覆盖”。模型没有踩过坑你踩过的坑写进去它就不会再踩第二次。3.2 一份可以直接改用的基础模板下面是我在实际项目里用的一个模板项目背景是虚构的某后台管理系统后端 Python FastAPI前端 TypeScript Vue 3数据库 MySQL带 Celery 定时任务和数据导入导出功能。# AGENTS.md ## 项目定位 企业内部后台管理系统用于运营人员管理用户、配置活动策略、查看统计报表。 系统仅供内部使用不做面向公网的 SEO 优化不做 C 端登录注册。 ## 技术栈与版本约束 - 后端Python 3.11 FastAPIORM 使用 SQLAlchemy 2.x - 前端Vue 3 TypeScript Vite组件库使用 Element Plus - 数据库MySQL 8.0读写分离 - 异步任务Celery Redis - 禁止引入 Django、Flask 作为 Web 框架禁止新增重型前端状态库当前足够 ## 目录结构 - backend/app/api路由与接口层只做参数校验和响应组装 - backend/app/services业务逻辑层禁止在 api 层写复杂业务代码 - backend/app/modelsSQLAlchemy 模型字段变更必须配合迁移 - frontend/src/views页面入口只负责页面组装 - frontend/src/composables可复用的业务逻辑 - backend/migrations数据库迁移脚本禁止手改历史迁移 ## 代码风格与命名 - 接口返回统一结构{ code: 0, data: ..., msg: ok } - 字段名一律 snake_case包括 JSON 返回字段 - 前端组件文件名用 PascalCase目录名用 kebab-case - 后端路由用复数名词如 /users、/orders禁止出现动词开头 ## 常用命令 - 本地运行后端uvicorn app.main:app --reload --port 8000 - 前端 devpnpm dev - 运行测试pytest backend/tests - 生成迁移alembic revision --autogenerate - 应用迁移alembic upgrade head - 启动 Celerycelery -A app.worker.celery_app worker --loglevelinfo ## 已知陷阱与禁忌 - 用户导出接口为异步任务不要直接同步读取全部用户 - config.yaml 是运行时生成文件手动修改会丢失 - 订单金额单位统一为“分”传给前端前必须转成“元” - 不要直接在 prod 环境执行 alembic downgrade详情见 docs/rollback.md这个模板一共不到 30 行信息密度很高。写完之后AI 新开会话基本不需要你再讲“项目是干嘛的、技术栈是什么、返回格式是什么”它自己就能从文件里读出来。3.3 放置位置与加载优先级根目录、子目录与全局规则AGENTS.md的加载逻辑我总结成一个简单的优先级模型子目录配置 根目录配置 用户全局配置。根目录放全项目通用的事实和约定比如技术栈、全局命名、公共命令。子目录放模块级特化规则比如backend/app/payment/AGENTS.md里专门写支付流程的特殊约束。AI 在处理该目录下文件时会同时看到根规则和子规则但子规则视为更贴近任务的补充。用户全局配置放在工具的用户级设置里只放个人偏好比如“代码里不要用 TODO 注释”“所有 Git 提交信息用英文”。全局配置尽量不要写和项目强相关的内容否则换项目时会污染记忆。实际使用中我见过很多团队把项目里的小知识全塞进根目录一个文件越写越长最后上下文被吃掉了大半。正确思路是分层全局管偏好根目录管项目子目录管模块。这样加载时才不会把所有内容不分青红皂白地一股脑塞给模型。4. 从配置到工程记忆分层的完整拼图4.1 项目记忆、会话记忆、全局记忆各司其职写完AGENTS.md只解决了记忆工程里“项目记忆”这一层。完整的记忆体系还要考虑会话记忆和全局记忆。会话记忆是当前对话上下文里流动的临时信息。比如“这次我们正在修 login 接口的 500 错误”“刚才已经改了auth_service.py下一步看schemas.py”。这些信息不应该写进配置文件它只在当下有用会随着会话结束消失。你要做的是在对话开始时给一个清晰的“本轮目标”模型自然会在上下文里形成短期记忆。全局记忆是沉淀在个人层面的长期偏好比如“代码注释用中文”“普适性缓存策略”“不要用any类型”。它适合放在用户级全局配置里让每个新会话都默认遵循。项目记忆就是AGENTS.md的核心领域。它承载的是“换任何开发者、换任何工具都必须知道的项目事实”。三层记忆叠加起来模型才不是一个只会梗概的通用助手而是“认清项目、认清任务、认清个人偏好”的协作伙伴。4.2 把 AGENTS.md 纳入版本管理与评审流程很多团队把AGENTS.md当成一次性文件写完就丢。这是记忆工程里最容易犯的错——项目是活的配置却死了。我在实践中形成的习惯是把AGENTS.md当作一等公民跟随代码一起进版本管理。每当项目发生重大变更新增服务、调整目录、更换依赖、推翻旧约定我都会在 Pull Request 里顺手更新对应板块。团队评审时也默认要求改动包含新增模块的目录职责说明。更进一步我会定期做“记忆校准”。方法是让 AI 基于最近的真实改动反推项目现状生成一份“我认为现在的项目是这样”的描述然后和我手上的AGENTS.md做 diff。差异就是记忆过期的地方。这个技巧能让配置跟上项目演进而不是变成一座越来越大的记忆废墟。4.3 不是所有知识都该写进 AGENTS.md越写越多之后我反而开始做减法。AGENTS.md 适合承载的是稳定的项目事实——技术栈、目录结构、约定、禁忌这些至少在一个发布周期内不会变。不适合放进去的一是易变细节比如某次线上事故的具体时间线那是事故报告该管的事二是临时决策比如“这版本先不做分页下版本再补”这应该留在会话记忆或 Issue 里三是大面积操作步骤比如“上线回滚六步法”这种放在docs/runbook.md里需要时让 AI 去查即可。用一个比喻收束AGENTS.md 是项目的宪法不是操作手册。宪法写价值观和边界操作手册写具体动作。二者缺一不可但混在一起就会让模型分不清“必须遵守的约束”和“偶尔参考的流程”。5. 真实实践复盘我们团队是怎么把记忆工程跑起来的5.1 初始状态提示词堆砌出来的混乱我之前呆过的某开发团队维护一个中后台 SaaS 项目当时 AI 辅助开发的入门方式非常原始每个人维护自己的一版“祖传提示词”。有人把整个业务背景压缩在 800 字的开头提示词里有人专门写了一份“AI 规则十诫”还有人每次开工从旧会话里复制历史消息当作背景。问题在协作时集中爆发。新成员接手时不知道要带哪份提示词同一个问题两个人用两套提示词AI 给的建议经常互相矛盾更麻烦的是项目演进后提示词里的“规则”大多来自半年前的架构认知早就过时了。本质上大家是在用私有的人脑记忆去对抗模型的无限失忆这注定不可持续。5.2 转向落地三步把项目知识沉淀成配置我们做了一次为期两周的收敛过程可以拆成三步。第一步盘点高频背景。把过去一个季度的 AI 问答记录和真实报错捞出来标记哪些信息被反复提及。结果很集中项目技术栈新来的 AI 每次都不认识、接口返回结构几乎每次都要重申、数据库迁移方式被 AI 误导过三次、业务金额单位被搞错过一次线上事故。这四点成了第一版AGENTS.md的核心。第二步写 v0.1 并评审。先由一个人起草然后发给全组评审。评审规则是只保留“所有人公认的事实”删除任何“个人偏好”和“操作命令式指令”。这个环节很重要因为个人偏好会污染项目级配置影响其他成员的协作体验。第三步新会话盲测。每个人新开一个会话不粘贴任何背景直接抛一个真实开发任务看 AI 给出的建议是否匹配项目约定。第一次盲测就发现了一个大问题AI 不知道登录鉴权的中间件实现建议改成直接在接口里写token校验。于是我们把鉴权方式补充进AGENTS.md。5.3 效果三个可以量化的变化整个流程跑了两周后团队里有几个比较明显的改变。第一新会话引导时间从 15 到 20 分钟降到了 1 分钟以内。以前每次都要重讲项目背景现在新开会话后直接说任务即可。第二AI 输出与项目约定的贴合度大幅提升。尤其是接口返回结构、字段命名、目录归属这些硬约定基本不用再手动纠正代码审查里因为“风格不符合项目规范”而打回的次数少了很多。第三团队的知识交接也顺了。以前换人维护模块需要老成员口头讲半天现在一份配置能让 AI 和人都站在同一起跑线上。新成员看AGENTS.md比翻聊天记录高效得多。6. 避坑指南Memory 工程最常见的 5 个坑6.1 把 AGENTS.md 写成命令式大段指令最大、最容易犯的坑就是“用写程序的心态写配置”。一看标题是“声明式配置”落笔却全是“你必须先做……永远不要……如果遇到……就先……”这种命令式指令。模型执行冗长命令容易遗漏和自相矛盾而且这种指令一旦多了配置文件会越长越难维护。守住一个原则多数内容写成“是什么”少写“怎么做”。真要写流程放到文档里让 AI 按需读取。6.2 文件越来越长上下文被吃掉模板只有 30 行时是纯收益写到 500 行时就开始变成负债。模型每次启动都要读它文件越长留给真正任务代码的上下文就越少。我的经验是控制在 200 行以内超出部分拆到docs/下并在 AGENTS.md 里写一句“涉及部署细节时先阅读 docs/deploy.md 再回答”。这样既不丢信息也不占日常上下文。6.3 多配置文件打架优先级不清项目大了根目录一份、components 一份、某业务目录又一份内容还互相矛盾。模型处理冲突时不是报错而是凭感觉任选其一结果不可控。解决思路很简单分层写清楚子目录配置只能补充、不能推翻根目录的核心事实全局配置只放个人偏好。坚持“同一主题只在一个地方描述”比依赖加载优先级靠谱得多。6.4 只写不更新配置变成记忆废墟AGENTS.md 最大的隐性成本是“过期”。半年不更新里面写的目录结构、命令、约定可能已经和代码不一致AI 反而被错误信息误导。最好的办法是让它跟着 PR 走任何结构性变更都顺手改配置。每个迭代末用前面提到的“AI 反推 diff”方法对账一次把废条目清掉。6.5 忽略会话记忆把一切压力都推给项目配置项目配置不是万能药。有些本应该写在当前对话里的临时背景比如“这次只改导出模块其他模块不动”“API 联调时用测试环境的 key”硬塞进项目配置反而会污染长期记忆。我自己的规则是时间跨度超过一个迭代的知识进文件只在这一个会话里有效的知识留在对话里。该会话记忆管的事就别让项目文件越俎代庖。最后再说几点个人体会写到这里我对“AI 编程范式转换”有个很深的感受真正的分水岭不是模型变聪明了多少而是我们把多少项目知识从“人脑临时记忆”和“会话提示词”里搬出来变成结构化的、可加载的、随项目演进的“工程资产”。AGENTS.md是这条路上性价比最高的基础设施它几乎零成本却直接改变了 AI 认识项目的方式。最后分享一个小技巧。每次项目迭代结束我会让 AI 做一次“记忆同步”先让它总结“基于最近代码变更项目现在存在哪些先前未记录的约束”我再人工确认后追加进AGENTS.md。这个动作本质上是在利用 AI 自己维护自己的记忆库踩过几次坑之后你会发现配置不仅不会过期还会比大多数团队文档活得更久。