1. 从每次重新解释一遍说起无状态模型到底卡在哪如果你最近半年深度用过任何一款AI编程助手大概率经历过这种循环新开一个会话窗口把项目结构、技术栈、代码规范、命名习惯、测试框架、目录约定重新讲一遍AI才勉强给出能用的代码。换个窗口一切归零。这不是模型不够聪明而是它的工作方式决定的——大语言模型本质上是无状态的每一次推理都是一次独立的函数调用上一次对话里你费尽口舌建立的上下文在会话结束的那一刻就蒸发了。这个特性在聊天场景里无所谓但在编程场景里是致命的。写代码从来不是孤立行为它高度依赖项目上下文这个模块为什么用这个设计模式、那个工具函数为什么不能随便改、接口返回值的字段命名为什么和数据库列名不一致。这些隐性知识散落在老代码、注释、提交记录和团队成员的脑子里AI看不到就只能靠猜。猜对了是运气猜错了你还得花时间纠正它。于是很多人开始想办法喂上下文把关键文件贴进对话、写一段长长的系统提示词、用注释在代码里埋提示。这些做法短期有效但都有同一个毛病——不可复用、不可维护、不可协作。你写的提示词只有你自己看得懂换个人接手就得重新理解项目一升级提示词里的信息就过期了但没人记得去改。Memory工程要解决的就是这个问题。它的核心思路很朴素既然模型无状态那就把状态外置成一份结构化、可版本管理、可被工具读取的文件。这份文件不依赖某一次对话而是跟着代码仓库走谁打开项目谁就能拿到同一份上下文。而AGENTS.md这类声明式配置正是这种思路目前最接地气的落地形态——用一份人类可读、机器可解析的Markdown文件把这个项目是什么、怎么跑、有哪些规矩一次性说清楚。这篇文章不打算停留在概念层面。我会把无状态模型带来的具体痛点拆开讲清楚Memory工程为什么必须走声明式这条路然后给出一份可以直接抄的AGENTS.md结构再聊聊实际落地时那些文档里不会写的坑。无论你是刚接触AI编程的新手还是已经在团队里推AI协作的老手应该都能从中找到能直接用的东西。2. 无状态模型的三个真实痛点以及为什么多轮对话救不了2.1 上下文窗口不是记忆只是临时工作台很多人有个误解既然模型支持几十万token的上下文窗口那把整个项目塞进去不就行了理论上可以实践上很蠢。原因有三层。第一层是成本。上下文窗口里的每一个token都要参与计算你每次提问都带着几万token的项目代码费用和延迟都会成倍上涨。第二层是注意力稀释。上下文越长模型对其中关键信息的抓取能力越弱这在业界被称为lost in the middle现象——开头和结尾的信息记得牢中间的大段内容容易被忽略。第三层是时效性。代码是活的今天贴进去的版本明天就变了而上下文窗口里的内容是静态快照不会自动更新。所以上下文窗口解决的是单次任务的信息量问题不是跨会话的记忆问题。把这两者混为一谈是很多AI编程实践走偏的起点。2.2 提示词工程的天花板个人技巧无法变成团队资产早期大家靠提示词工程来弥补无状态写一堆你是一个资深工程师请遵循以下规范之类的话术。这套东西在个人使用时有奇效但一旦进入团队协作就崩了。问题在于提示词是隐性的、口头的、易失的。A同学调好了一段提示词效果很好但他没法把它安装到B同学的编辑器里就算复制粘贴过去B同学的项目结构不一样提示词里的具体路径和约定全对不上。更麻烦的是提示词没有版本概念改了就是改了没人知道上一版长什么样也没法回滚。这本质上是一个知识管理问题而不是提示词技巧问题。团队需要的不是某个人手里的咒语而是一份所有人都能读、能改、能追溯的共享文档。2.3 模型换代带来的记忆断层还有一个容易被忽略的痛点模型是会换的。今天你用A模型明天可能换成B模型或者同一个模型升级了大版本。不同模型对提示词的敏感度、对格式的偏好、对指令的遵循程度都不一样。你为A模型精心调教的提示词换到B模型上可能完全失效。如果上下文信息是硬编码在提示词里的那每次换模型都是一次重写。但如果上下文是声明式地存在一份标准文件里换模型时只需要调整读取和注入的方式内容本身不用动。这就是声明式配置相对于命令式提示词的核心优势——内容和载体解耦。把这三个痛点摆在一起看结论就很清楚了无状态模型需要的不是更长的上下文也不是更花哨的提示词而是一份外置的、结构化的、可版本管理的项目记忆。这份记忆的载体就是接下来要讲的AGENTS.md。3. 声明式配置为什么比命令式提示词更适合做Memory载体3.1 声明式与命令式的本质区别先把这个概念说清楚不然后面全是空中楼阁。命令式是告诉系统怎么做声明式是告诉系统要什么。放到AI编程场景里命令式提示词你写一段话指导AI先读package.json再检查src目录然后按照ESLint规则生成代码……——你在描述流程。声明式配置你写一份文件说明本项目使用TypeScript严格模式测试用Vitest组件放src/components——你在描述事实。区别在哪命令式的流程是死的换个任务就得重写声明式的事实是活的任何任务都能基于同一份事实去推理。AI拿到本项目用Vitest这个事实后你让它写测试它就知道用Vitest你让它改测试它也知道用Vitest不需要你每次都交代一遍。3.2 声明式配置天然适配版本管理和协作AGENTS.md本质上就是一个Markdown文件放在代码仓库根目录。这意味着它自动获得了Git带来的一切好处有历史、能diff、能review、能回滚、能分支。项目规范变了改这个文件提交记录里清清楚楚新人入职读一遍这个文件就知道项目全貌多个AI工具接入读的是同一份文件行为一致。这一点是命令式提示词永远做不到的。提示词存在某个工具的配置里是私有的、黑盒的、不可协作的。而声明式文件是公开的、透明的、属于项目本身的。3.3 一份文件多个消费者声明式配置的另一个好处是消费者多样。同一份AGENTS.md可以被不同的角色读取消费者读取方式用途AI编程助手工具自动注入或手动引用生成符合项目规范的代码新加入的开发者人工阅读快速理解项目结构和约定CI/CD流程脚本解析特定字段校验代码是否符合声明规范代码审查工具解析规则段落自动检查PR是否违规一份文件服务多个场景这是命令式提示词想都不敢想的。你写一次收益是复利的。3.4 从教AI做事到给AI事实的思维转变我观察到一个很有意思的现象新手用AI编程总想着怎么把AI教明白老手用AI编程想的是怎么把项目讲清楚。前者是命令式思维后者是声明式思维。教AI做事你永远教不完因为任务无穷无尽。给AI事实你只需要把项目的基本盘交代清楚剩下的让模型自己去推理组合。这就像带新人你不会手把手教他每一个操作而是给他一份项目文档让他自己查、自己判断。AGENTS.md就是这份文档。4. 一份能直接用的AGENTS.md该长什么样4.1 结构设计分区块每块只讲一件事AGENTS.md不是越长越好而是要结构清晰、信息密度高。我实践下来一份好用的文件应该包含以下几个区块每个区块职责单一# 项目名称 ## 项目概述 一句话说明这个项目是做什么的面向什么用户。 ## 技术栈 - 语言TypeScript 5.x严格模式 - 框架React 18 Vite - 状态管理Zustand - 测试Vitest Testing Library - 包管理pnpm ## 目录结构 - src/components通用UI组件每个组件一个目录 - src/features按业务功能划分的模块 - src/lib与业务无关的工具函数 - src/types全局类型定义 ## 编码规范 - 组件一律使用函数式写法禁止class组件 - 所有导出必须有显式类型标注 - 禁止使用any必要时用unknown加类型守卫 - 命名组件用PascalCase函数和变量用camelCase常量用UPPER_SNAKE_CASE ## 常用命令 - 开发pnpm dev - 构建pnpm build - 测试pnpm test - 类型检查pnpm typecheck ## 注意事项 - 修改src/lib下的工具函数前先搜索所有引用点 - 新增依赖前先确认是否已有同类库 - 提交前必须通过类型检查和测试这个结构的好处是AI读一遍就知道项目全貌人读一遍也能快速上手。每个区块都是事实陈述不是流程指导所以不会随任务变化而失效。4.2 技术栈区块写版本别写最新版技术栈这块有个坑很多人写React最新版Node LTS这种模糊描述对AI毫无帮助甚至有害。AI可能按它训练数据里的版本来生成代码和你项目实际用的版本对不上。正确做法是写明确版本号。React 18和React 19的API有差异TypeScript 4和5的类型系统行为不同这些差异会直接影响AI生成的代码能不能跑。写清楚版本AI才能生成匹配的代码。另外包管理器一定要写。pnpm、npm、yarn的lock文件格式不同命令也有细微差别。AI如果不知道你用pnpm可能给你生成npm install的命令虽然能跑但和项目约定不一致。4.3 目录结构区块讲清楚什么代码放哪里目录结构这块光列目录名没用要说明每个目录的职责边界。比如src/components放通用组件和src/components放组件是两回事前者告诉AI什么该放进去后者什么都没说。我习惯在每个目录后面加一句职责说明必要时加一句什么不该放这里。比如src/lib与业务无关的纯函数工具不依赖任何业务类型src/features按业务域划分每个feature内部可以有自己的components、hooks、utils这种边界说明能极大减少AI把代码放错地方的概率。4.4 编码规范区块只写反直觉的规则编码规范最容易写成一堆废话。代码要清晰命名要有意义这种话AI本来就知道写了等于没写。真正有价值的是反直觉的、项目特有的规则。比如禁止使用any就是反直觉的因为AI默认可能用any图省事组件一律函数式也是因为AI可能生成class组件。这些才是需要明确声明的。而变量命名要有意义这种通用规范写进去只是占地方。判断标准很简单如果一条规则是AI默认就会遵守的就别写如果AI默认会违反的必须写。4.5 注意事项区块把踩过的坑写进去这个区块是AGENTS.md最有价值的部分因为它承载的是项目特有的隐性知识。比如修改某个工具函数前先搜索引用点这条规则背后可能是某次线上事故新增依赖前先确认是否已有同类库背后可能是依赖膨胀的教训。这些知识在传统项目里靠口口相传新人要踩一遍坑才知道。写进AGENTS.md后AI和人都能直接获得省下大量试错成本。5. 落地实操让AI真正读到并遵守这份配置5.1 不同工具的读取方式不一样写好了AGENTS.md下一步是让AI工具真正读到它。这里有个现实问题不同工具的读取机制不同。有些工具会自动扫描项目根目录的约定文件并注入上下文你什么都不用做有些工具需要你在配置里显式指定文件路径还有些工具只认特定文件名你得把内容放到它认的那个文件里。我的建议是以AGENTS.md为主文件其他工具需要的格式用软链接或构建脚本生成。这样内容只有一份维护成本最低。如果工具支持自定义路径直接指向AGENTS.md即可。5.2 手动引用作为兜底方案如果工具不支持自动读取那就手动引用。在对话开头说一句请先阅读项目根目录的AGENTS.md大多数工具都能理解并去读。虽然多了一步但比每次重新交代上下文强太多。更稳妥的做法是把关键信息做成一个可复制的片段存在编辑器snippet里新开会话时一键插入。这样既保证了信息一致又不用依赖工具的自动读取能力。5.3 验证AI是否真的读懂了写完配置不代表AI就遵守了。你需要主动验证。方法很简单问AI几个只有读了配置才能答对的问题。比如这个项目用什么测试框架组件应该放在哪个目录。如果AI答对了说明配置生效如果答错或含糊说明没读到或者读到了没理解。这个验证步骤很多人跳过结果配置写了等于白写。花两分钟验证一下能省下后面无数次纠正。5.4 把配置纳入代码审查流程AGENTS.md既然是项目文件就应该和代码一样接受审查。每次修改都应该有明确的理由改动应该被review。我见过太多团队把这份文件当成一次性文档写完就扔在那项目变了文件不变最后AI读到的是过期信息反而帮倒忙。把AGENTS.md的更新纳入PR流程改代码规范的同时改配置加新依赖的同时更新技术栈区块。让它成为活文档而不是死档案。6. 踩坑实录那些文档里不会写的经验6.1 配置写太满反而干扰AI判断刚开始用AGENTS.md时我犯过一个典型错误把能想到的所有规则都写进去文件写了上千行。结果AI反而变笨了——因为信息太多重点被淹没模型抓不住关键约束。后来我做了减法只保留真正影响代码生成质量的规则文件压缩到一百多行效果反而更好。这印证了前面说的注意力稀释原理不是信息越多越好而是信噪比越高越好。判断哪些该留问自己如果AI不知道这条会不会生成错误的代码。会就留不会就删。6.2 规则之间打架AI会随机选一个另一个坑是规则冲突。比如你在编码规范里写优先使用函数式编程又在某个feature的说明里写这个模块用class组织AI遇到具体任务时就懵了可能随机选一个执行。解决办法是明确优先级。在文件开头加一句当通用规范与模块特定说明冲突时以模块特定说明为准。这样AI就有了判断依据不会瞎猜。6.3 更新不及时AI拿着旧地图找新路最隐蔽的坑是配置过期。项目重构了目录结构但AGENTS.md没改AI还按旧结构生成代码你看着一堆路径错误的import还以为是AI变笨了。我的做法是把配置更新和代码改动绑定每次重构目录、换依赖、改规范都在同一个PR里更新AGENTS.md。这样两者永远同步不会出现地图和地形对不上的情况。6.4 别指望一份配置适配所有任务最后说个心态问题AGENTS.md不是银弹。它能解决项目上下文缺失的问题但解决不了任务描述不清的问题。如果用户的需求本身模糊AI读再多配置也生成不出对的代码。配置解决的是背景知识需求描述解决的是当前目标两者缺一不可。别把配置当成万能药它只是把AI从完全瞎猜提升到有依据地推理。7. 从Memory工程看AI编程的下一步把AGENTS.md这类声明式配置放到更大的视角里看它其实是AI编程范式转换的一个缩影。早期的AI编程是对话式的人和模型你一句我一句上下文靠对话维持现在正在转向配置式的项目上下文外置成文件模型按需读取再往前看很可能是代理式的AI代理自主读取项目记忆、规划任务、执行并验证。这个演进路径背后有一条清晰的主线把隐性的、易失的、私有的知识变成显性的、持久的、共享的资产。AGENTS.md只是这条路上的一个站点但它已经足够实用足够让今天的开发者受益。我自己的体会是自从把项目上下文沉淀成声明式配置后用AI写代码的体验发生了质变。以前是每次都要重新教现在是打开就能用以前是只有我会用现在是团队都能用。这种从个人技巧到团队资产的转变才是Memory工程真正的价值所在。如果你还没开始做这件事建议从最小的AGENTS.md开始——哪怕只写技术栈和目录结构两个区块也比什么都不写强。用起来之后你会自然发现还需要补充什么然后逐步迭代。这份文件不需要一次写完美它需要的是持续维护、和项目一起生长。
阅读完成 · 觉得有帮助?