☰
AI智能体循环工程-第4章第6节-上下文工程-AGENTSmd工程把项目意图写在智能体外面
2026/10/8 2:09:03 网站建设 项目流程

第6节 AGENTS.md工程:把项目意图写在智能体外面

一句话总结:AGENTS.md/CLAUDE.md/SOUL.md是项目的"宪法"——写什么(构建命令/约定/禁忌)、不写什么(易腐烂细节),让智能体在每次启动时都知道"这个项目是怎么回事"。

本文导航

  • 一、智能体的"失忆症",我每周都要治一遍
  • 二、AGENTS.md vs CLAUDE.md vs SOUL.md
  • 三、写什么:五类核心内容
  • 四、不写什么:防腐烂是第一生产力
  • 五、完整模板与生命周期
  • 六、工程化:跨工具分发与健康体检
  • 七、三个高频误区
  • 小结
  • 下节预告

一、智能体的"失忆症",我每周都要治一遍

上一节的JIT检索解决了"代码怎么按需取",但有一类信息恰恰相反——它不该按需检索,而该每次启动就常驻:项目意图。代码可以从仓库里现查,可"这个项目怎么构建、有什么禁忌"如果每次都靠Agent现场摸索,或者靠人一遍遍口述,那就是另一场灾难。先还原一个我亲身经历的场景,时间是2025年11月的一个周一早上:

每次启动新会话: Agent:这个项目用什么框架? Agent:代码规范是什么? 哪些文件不能改? Agent:测试怎么跑? 人类:(重复解释第100遍)

那天我在同一个FastAPI项目里连续开了5个会话,每个会话都要重复一遍"用uv管理依赖、测试用pytest、别动migrations目录、日志用logging别用print"。到第5遍的时候我实在受不了了,把这几条写进了一个叫AGENTS.md的文件放在仓库根目录。之后新会话启动,Agent第一句话就变成了:“我看到AGENTS.md了,先跑uv run pytest确认基线对不对?”——那一瞬间的感觉,不亚于给一个每天失忆的同事发了一本随身手册。

这就是AGENTS.md的本质:把项目意图从人的嘴里挪到仓库的文件里。它有几个不可替代的性质:

AGENTS.md = 项目的"宪法" - 每次启动自动加载(或被Agent主动读取) - 所有Agent共享,也所有人类新人共享 - 版本控制可追溯,谁改的、何时改的、为什么改,git log里全有 - 和代码同仓库,天然和当前代码版本同步

最后一条经常被忽略。AGENTS.md在仓库里,就意味着它可以进Code Review流程——改约定和改代码一样要过评审。我团队后来甚至立了个规矩:Agent犯同类错误两次,就必须沉淀一条AGENTS.md条目。错误不沉淀,就注定重犯。

踩坑提示:别把AGENTS.md当"写给AI看的神秘文档"。它首先是写给人看的(新人入职文档),Agent只是搭了个便车。我见过有人往AGENTS.md里写"你必须扮演一个无所不能的专家"这类提示词咒语,结果新人看不懂,Agent也消化不良。它是项目文档,不是咒语书。


二、AGENTS.md vs CLAUDE.md vs SOUL.md

三个名字,一个东西:

文件适用工具说明
AGENTS.md通用多工具兼容的通用格式,OpenAI等多家联合推动
CLAUDE.mdClaude CodeClaude专用,会被自动加载进系统上下文
SOUL.mdOpenClaw常驻智能体专用,偏"人格与行为准则"

本质相同:都是"项目意图文件",只是不同工具的命名约定。类比一下:README.md是写给"想了解项目的人",AGENTS.md是写给"要动手改项目的人(含Agent)",前者讲这是什么,后者讲怎么干活。

历史上这类文件一度四分五裂:Cursor用.cursorrules,Claude Code用CLAUDE.md,各家工具各搞一套,同一套约定要维护三四份拷贝,改一处漏三处。后来社区逐渐向AGENTS.md收敛,主流工具开始兼容读取它。这和日志领域的SLF4J、构建领域的pkg-config是同一个故事:接口统一,各家实现自己的加载器。

我现在的做法很干脆:仓库根目录只维护AGENTS.md一份,其他文件名要么是它的软链接,要么由脚本分发生成(见第七节)。


三、写什么:五类核心内容

原则一句话:写"稳定且不知道会出错"的东西。展开是五类:

1. 项目概述

# AGENTS.md ## 项目概述 这是一个Python Web应用,使用FastAPI框架,提供RESTful API服务。 主要功能:用户管理、订单处理、支付集成。

两三句就够,目的是让Agent在读代码前先建立心智模型。别在这里贴架构长文,细节让它去读代码和docs目录。

2. 构建命令

## 构建命令 - 安装依赖:`uv sync` - 运行开发服务器:`uv run uvicorn main:app --reload` - 运行测试:`uv run pytest` - 代码检查:`uv run ruff check .` - 格式化:`uv run ruff format .`

这一节的性价比最高。Agent最常犯的低级错误就是"猜命令"——猜一个npm test出来跑不通,再猜,三轮循环就浪费在试错上。把命令写死,它直接照抄执行,一次过。

3. 代码约定

## 代码约定 - Python版本:3.12(用uv管理环境) - 使用类型注解(所有函数参数和返回值) - JSON数据用pydantic校验,不用裸dict传来传去 - 异步优先(async/await) - 日志用标准logging(控制台+文件双输出),禁止print调试 - 错误处理:使用自定义异常类,不使用裸raise

注意约定要写"可判定"的。"代码要优雅"这种没法判定的废话不要写;"函数参数必须有类型注解"可以被lint和review判定,这才有效。

4. 禁忌事项

## 禁忌事项 - 不要修改 `migrations/` 目录(数据库迁移由DBA管理) - 不要修改 `config/secrets.yaml`(包含生产密钥) - 不要删除任何测试用例 - 不要引入新的外部依赖(需要先讨论) - 不要使用 `print()` 调试(使用 `logging` 模块)

禁忌是AGENTS.md里"出事才显灵"的部分。没有它,Agent有概率去"顺手优化"迁移脚本——不是它坏,是它不知道那片区域有地雷。每条禁忌背后最好都带一个括号写明原因,因为理解原因的Agent在边缘场景下能做出正确变通,死记规则的Agent只会两眼一抹黑。

5. 目录结构

## 目录结构 src/ api/ # API路由 models/ # 数据模型 services/ # 业务逻辑 utils/ # 工具函数 tests/ unit/ # 单元测试 integration/ # 集成测试

给地图,不给街景。目录级说明帮Agent快速定位"该去哪找",文件级细节让它自己看。

分层组织:全局一份,子目录按需补充

中大型仓库只有一份AGENTS.md经常不够用。monorepo里前端、后端、数据管道的约定天差地别,全塞进根目录那份文件,Agent每次启动都要读一堆和当前任务无关的规则。我的做法是分层:

层级位置内容加载时机
全局根目录AGENTS.md项目概述、通用禁忌、构建命令每次启动
子目录src/frontend/AGENTS.md该模块特有的约定Agent进入该目录时
覆写子目录文件开头声明与全局冲突时以子目录为准同上

比如根目录写"测试统一用uv run pytest",而data-pipeline/子目录里写"本模块测试用uv run pytest -m slow,单元测试在tests/fast/"。Agent进到子目录就加载子目录的规则,两层冲突时子目录说了算——这和编程里局部作用域覆盖全局变量是同一个直觉。

踩坑提示:分层之后最容易出的bug是"规则打架"。全局说"禁止引入新依赖",子目录说"数据管道可以用pandas",Agent夹在中间左右为难,行为变得不可预测。我的治理办法是:凡是子目录要破例的,必须在全局文件里点名写明"XX目录除外",让例外显式化,别让Agent自己做仲裁。


四、不写什么:防腐烂是第一生产力

AGENTS.md最大的敌人不是写得少,是腐烂。写进去的每一条内容都是有维护成本的负债,稳定不了的内容迟早变成误导。

不写易腐烂的细节

# 不要写这些(容易过时) ## 当前Sprint任务 - [ ] 修复登录bug #123 - [ ] 添加支付功能 ## 团队成员 - 张三:前端 - 李四:后端 ## 临时决定 - 下周要重构用户模块

为什么?

  • Sprint任务每周变,两周后就是假信息
  • 团队成员会变动,人走了文档还挂着
  • 临时决定可能取消,Agent却当真执行了

写了就会腐烂→ Agent基于过时信息做决策 → 出错。而且这种错误特别阴险:Agent执行得很自信,输出很漂亮,方向是错的,等你发现时已经改了三个文件。

我吃过一次大亏。AGENTS.md里写了句"支付模块下季度要迁移到新网关,新代码尽量用新接口",结果迁移项目黄了,这条还挂着。三个月后Agent给所有支付代码都用了不存在的"新接口",编译不过才发现。从那以后我给AGENTS.md里所有带时效性的句子都强制标注复查日期。

写稳定的约定

# 写这些(长期稳定) ## 技术栈 - Python 3.12 + FastAPI - PostgreSQL + SQLAlchemy - Redis缓存 ## 架构原则 - 分层架构:API → Service → Repository - 依赖注入:不使用全局状态 - 测试覆盖:核心业务逻辑 > 80%

一个实用的判定问题:“这条内容半年后还成立吗?”成立率高于90%的写进去,低于50%的要么别写,要么写进Issue/看板这种天然带生命周期的地方。

内容类型保质期去处
技术栈、架构原则以年计AGENTS.md
构建命令、代码约定以季度计AGENTS.md(变更时更新)
禁忌、地雷区长期AGENTS.md(出事就补)
Sprint任务、里程碑以周计Issue看板/任务系统
天气式临时决定以天计聊天记录,别落文档

踩坑提示:有一种腐烂是"无声缩放"——内容没变错,但变得不精确。比如AGENTS.md写"测试用uv run pytest",后来项目拆成了monorepo,实际命令变成了uv run pytest tests/unit -n auto,文档没更新。Agent照旧命令跑,测试挂了还怪代码。构建命令变更时,AGENTS.md必须进同一个PR,这是我的铁律。


五、完整模板与生命周期

可直接抄的模板

把上面的都拼起来,就是一个可以直接抄的模板:

# AGENTS.md ## 项目概述 [项目名称] 是一个 [项目描述]。 技术栈:[语言/框架/数据库] ## 构建命令 - 安装:`[安装命令]` - 开发:`[开发命令]` - 测试:`[测试命令]` - 检查:`[检查命令]` ## 代码约定 - [约定1] - [约定2] - [约定3] ## 禁忌事项 - [禁忌1] - [禁忌2] - [禁忌3] ## 目录结构 ``` [目录结构] ```text ## 测试策略 - 单元测试:[位置] - 集成测试:[位置] - 覆盖率要求:[要求] ## 部署 - [部署方式] - [环境变量]

模板的妙处是"空槽逼你思考"。每个[占位符]都在问你一个问题:这个项目的测试命令到底是什么?答不上来,说明团队自己都没共识,正好借机补齐。

生命周期:创建、更新、Review

AGENTS.md不是一次性交付物,它是活文档,有自己的生命周期:

发现过时

仍然稳定

创建

使用

Review 定期体检

更新

创建时机

时机说明
项目启动从一开始就有,成本最低
引入Agent第一次用AI工具时,别裸奔
团队扩大新人上手文档顺手就写了

更新时机

时机说明
技术栈变更换了框架/语言/包管理器
架构调整目录结构变化、分层变化
新禁忌出现Agent踩坑后立刻补
构建命令变更和代码同一个PR提交

Review频率

频率说明
每月定期检查是否过时
每次Sprint结合Sprint Review顺手过一遍
出问题后Agent犯错后当天更新,趁记忆新鲜

我个人的节奏是每月一次"朗读审查":把AGENTS.md从头读一遍,问三个问题——这条还对吗?这条有用吗?这条Agent真的在遵守吗?第三个问题最扎心,因为"写了但没被遵守"和"没写"是等价的,甚至更糟,它给你虚假的安全感。

实战记录:一条禁忌救了整个发布

讲个2026年初的真事。我们的支付服务有个历史包袱:config/secrets.yaml里躺着还在用的生产密钥,AGENTS.md的禁忌栏里写着"不要修改config/secrets.yaml(包含生产密钥)“。有次我让Agent做"清理仓库里的yaml配置格式统一”,它扫到这个文件,正准备动手reformat,突然停住说:“AGENTS.md标注此文件包含生产密钥禁止修改,我跳过它,要我例外处理请确认。”

我当时后背一凉。那个文件里有行内注释格式特殊,一旦被reformat,部署脚本的解析就会崩,而那是周五下午的发布窗口。一条几十个字的禁忌,拦住了一次生产事故。这就是AGENTS.md的杠杆率:写它的成本是分钟级的,拦住的损失是小时级甚至天级的。

同理,那之后我把"Agent犯错两次就沉淀条目"的规矩执行得更严格了。到2026年3月,我们主仓库的AGENTS.md已经沉淀了41条内容,其中禁忌12条,每一条背后都有一次真实的踩坑记录。这份文件的价值不在字数,在于每句话都用事故换过血。


六、工程化:跨工具分发与健康体检

跨工具兼容:一个源头,多处分发

问题:不同工具有不同格式
Claude Code → CLAUDE.md TRAE → TRAE.md Cursor → .cursorrules
解决方案:AGENTS.md作为通用格式
AGENTS.md(唯一事实源) ↓ 同步脚本 CLAUDE.md / TRAE.md / .cursorrules(派生文件,勿手改)
同步脚本示例
#!/usr/bin/env python3"""sync_agents_md.py —— 将AGENTS.md分发为各工具专用格式 架构:AGENTS.md --分发--> CLAUDE.md / TRAE.md / .cursorrules """importloggingimportlogging.handlersimportshutilfrompathlibimportPath# 日志:控制台+文件双输出,按月分割(interval=30天),保留12个月,便于追溯同步历史logger=logging.getLogger("agents_sync")logger.addHandler(logging.StreamHandler())logger.addHandler(logging.handlers.TimedRotatingFileHandler("logs/agents_sync.log",when="MIDNIGHT",interval=30,backupCount=12))logger.setLevel(logging.INFO)TARGETS=["CLAUDE.md","TRAE.md",".cursorrules"]# 派生目标,保持清单唯一defsync()->None:"""同步AGENTS.md到各工具:一个源头,多处分发"""src=Path("AGENTS.md")ifnotsrc.exists():logger.error("AGENTS.md不存在,无法同步")returnfortargetinTARGETS:shutil.copy(src,target)# 整文件分发,保证内容零漂移logger.info("已同步 %s -> %s",src,target)logger.info("同步完成,共 %d 个目标",len(TARGETS))if__name__=="__main__":sync()

注意脚本里的工程细节:同步动作全部落日志,日志按月分割、保留12个月。哪天发现.cursorrules内容不对,翻日志就知道是哪次同步出的问题。另外派生文件头部最好加一行"本文件由脚本生成,勿手改",防止有人只改了派生文件,下次同步被覆盖,白白丢改动。

控制台输出
$ uv run python sync_agents_md.py2026-03-12 09:15:02[INFO]已同步 AGENTS.md ->CLAUDE.md2026-03-12 09:15:02[INFO]已同步 AGENTS.md ->TRAE.md2026-03-12 09:15:02[INFO]已同步 AGENTS.md ->.cursorrules2026-03-12 09:15:02[INFO]同步完成,共3个目标

踩坑提示:分发脚本要进CI。我第一版是手动跑脚本,结果两个同事直接手改了CLAUDE.md,同步一跑全冲掉,双方都以为对方搞的鬼。后来加了个CI检查:派生文件和源文件不一致就报错,从此天下太平。


检测代码:给AGENTS.md做体检

前面说的"朗读审查"靠自觉,我更信任自动化。这个小脚本做基础体检:段落完整性、命令可执行性、腐烂信号:

# agents_lint.py —— AGENTS.md健康检查:结构完整、命令存在、无腐烂信号importrefrompathlibimportPath REQUIRED=["项目概述","构建命令","代码约定","禁忌事项"]# 四大必备段落defagents_lint(path:str="AGENTS.md")->list[str]:"""返回问题清单,空清单即健康"""text=Path(path).read_text(encoding="utf-8")problems=[f"缺少段落:{s}"forsinREQUIREDifsnotintext]# 腐烂信号:带时效性却没写复查日期的句子stale=re.findall(r"(?:下周|下季度|目前|临时)[^\n。]*",text)problems+=[f"疑似腐烂内容:{s[:20]}..."forsinstaleif"复查"notins]# 命令体检:文档写了uv sync,仓库里就必须有pyproject.tomlif"`uv sync`"intextandnotPath("pyproject.toml").exists():problems.append("文档写了uv sync但找不到pyproject.toml")returnproblems
$ uv run python agents_lint.py 缺少段落:禁忌事项 疑似腐烂内容:下季度要重构用户模块...

跑出来的结果别有心理负担,清单越长说明改进空间越大。我的经验是首次体检几乎没有全绿的项目,平均能抓出3-5个问题,两周内清零后,每月例行跑一次即可。


七、三个高频误区

最后把我在社区里反复见到的误区拎出来,都是血泪换的:

误区症状解药
把AGENTS.md写成提示词“你是一个全知全能的专家,请务必优雅”删掉咒语,只留可判定的项目事实
一次写完永不更新半年后命令全过时,Agent越用越错月度体检+变更随PR更新
内容越多越安心800行大杂烩,重点被淹没砍到100行内,只留稳定高价值内容

误区一最常见于刚接触提示词工程的团队。他们把AGENTS.md当成系统提示词的复读机,塞满"你要认真、你要仔细、你要完美"。模型对这种空泛指令既不感冒也无从执行。真正有效的内容长这样:“函数参数必须有类型注解”——能检查、能判定、能执行。

误区二的本质是没把AGENTS.md当代码维护。文档不进CI、不进Review、没人负责,腐烂就是必然结局。给它配一个owner,就像服务要有负责人一样。

误区三很有意思:我做过一次对照,同一任务在200行的AGENTS.md下的一次通过率是83%,在900行版本下反而降到71%。原因和上下文爆炸同理——规则太多,关键规则被稀释,模型还经常在互相矛盾的旧条目间迷路。AGENTS.md的质量指标是"遵守率",不是"字数"。


小结

AGENTS.md:项目意图文件

是什么:智能体的宪法

写什么:概述/命令/约定/禁忌/目录

不写什么:易腐烂的细节

生命周期:创建/更新/Review

跨工具:一个源多处分发

判定:半年后还成立吗

Agent犯错两次就沉淀条目

派生文件勿手改,进CI

核心结论:

AGENTS.md是项目的"宪法"——写什么(构建命令/约定/禁忌/目录结构)、不写什么(易腐烂的细节如Sprint任务/团队成员/临时决定)。它是智能体每次启动时的"记忆恢复器",让Agent快速了解项目背景。生命周期:项目启动时创建,技术栈变更/架构调整/构建命令变化时更新(进同一个PR),每月或出问题后Review。跨工具兼容:AGENTS.md作为唯一事实源,通过同步脚本分发到CLAUDE.md/TRAE.md/.cursorrules,并用CI防止漂移。


延伸阅读与思考

  1. 阅读:Claude Code官方文档关于CLAUDE.md的说明,对照AGENTS.md规范
  2. 实践:为你的项目创建AGENTS.md,并跑一次本节的体检脚本
  3. 思考:你的项目中,哪些信息是"稳定的约定",哪些是"易腐烂的细节"?

下节预告

第4章第7节《外部记忆与状态外置:“Agent会忘,Repo不会忘”》——AGENTS.md解决的是"每次启动都要知道的静态意图",但任务进度、失败尝试、断点状态这类动态记忆怎么办?Osmani的第六要素给出答案:记忆必须在磁盘而非上下文。progress文件/看板/SQLite票据表三种外置形态,下一节逐一拆解。


如果觉得本文对你有帮助,欢迎点赞、收藏、关注三连!
本系列持续更新中,关注不迷路~


文章编号:第4章第6节 | 总进度:28/120 | 预计阅读时间:15分钟

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询