🛠️ 第6章 AGENTS.md:给 Agent 的项目说明书
📄 一句话概括

权限矩阵管「谁的地盘」,禁区管「谁都不许碰」,两套规则要同时存在。 交接四项:改了什么、为什么、怎么验的、下一步。缺一项就打回。 值班的边界不是时间,是「哪些动作不需要问人」。

📝 本章和前面几章的关系

前三篇讲的都是「一个 Agent 在干活」。这一篇讲「几个人加几个 Agent 一起干」。 一旦人多,AGENTS.md 里就得多两样东西:谁负责哪块、交接要留什么。 Demo 用一张权限矩阵跑六个请求,再用四项检查跑一次交接。 六个请求拒了三个,四项交接缺了一项。

一、谁能改哪一块

权限矩阵只写「能改哪儿」,不写「能做什么」。 粒度到目录就够——再细会写成一本没人看的制度。

角色 能改 不能改
前端 src/web/ src/api/
后端 src/api/、src/ src/web/
值班 config/ 源码全部

注意 Demo 里「后端改 data/」被拒了。 他在自己能改的范围里(src/ 下面),但 data/ 是禁区。 这说明两套规则要同时存在: 矩阵管「谁的地盘」,禁区管「谁都不许碰」。 「有权限」不等于「该做」。 这句话在人多的时候特别重要——因为 Agent 不会替你判断「该不该」,它只看「能不能」。

二、交接要留什么

四项:改了什么、为什么、怎么验的、下一步。

项 作用
改了什么 让他知道动过哪儿
为什么 让他判断这个改动还成不成立
怎么验的 让他能重跑一遍
下一步 让他能接着干

前三项是「交代」,第四项是「接力」。 Demo 里缺的正好是第四项——它最常被跳过,因为它看起来不属于「已完成」。 但交接的对象不是「过去」,是「接下来」。 没有第四项,接手的人第一件事就是来找你问——那这次交接等于没做。

三、值班时什么能自动做

值班的边界不是「几点到几点」,是「哪些动作不需要问人」。 写得出来,值班才睡得着。

动作 能不能自动 为什么
跑测试、看退出码 能 只读,可回滚
重启服务 能,但要留记录 影响面大,可回滚
改配置并提交 不能 改了就生效,且难回滚
删数据、改表结构 不能 没有撤销键

这张表的排序依据是「可回滚性」,不是「重要性」。 能回滚的可以自动,不能回滚的必须问人。 所以「重启服务」能自动,「改配置」不能——虽然改配置看起来更轻。 值班还有一个隐含要求:自动做的事要留痕。 「它半夜自己重启了三次」这种事,第二天必须有人知道—— 否则你会在三个月后排查一个从那时开始的问题。

四、动手 Demo:角色分工与交接:谁能改哪一块

这个 Demo 两段:先跑一张权限矩阵,再跑一次交接检查。 权限那段拿六个真请求去撞,看放行还是拒绝。 交接那段拿四项去查,缺一项就打回。 六个请求拒三个、交接缺一项——都是真算出来的。

ROLES = {
    u"前端": [u"src/web/"],
    u"后端": [u"src/api/", u"src/"],
    u"值班": [u"config/"],
}

for role, path in REQS:
    ok = any(path.startswith(p) for p in ROLES[role])
    P(u"  %s %s 改 %s" % (u"[放行]" if ok else u"[拒绝]",
                              pad(role, 6), path))

实跑输出:

--------------------------------------------------------------------
角色分工与交接:谁能改哪一块
--------------------------------------------------------------------


  ① 一张权限矩阵
  --------------------------------------------------------------------
  前端   -> src/web/
  后端   -> src/api/、src/
  值班   -> config/
  矩阵只写「能改哪儿」,不写「能做什么」。粒度到目录就够,再细会写成一本没人看的制度。

  ② 六个请求,逐条判
  --------------------------------------------------------------------
  [放行] 前端   改 src/web/Chat.jsx
  [拒绝] 前端   改 src/api/handler.py
  [放行] 后端   改 src/api/handler.py
  [拒绝] 后端   改 data/stopwords.txt
  [放行] 值班   改 config/app.yaml
  [拒绝] 值班   改 src/main.py
  六个里拒了 3 个。
  注意「后端」改 data/ 被拒——目录权限和禁区是两回事:他在自己能改的范围里,也不许碰禁区。
  ! 权限矩阵管「谁的地盘」,禁区管「谁都不许碰」。
  两套规则要同时存在,因为「有权限」不等于「该做」。

  ③ 交接:四项缺一项就打回
  --------------------------------------------------------------------
  [有] 改了什么  src/api/handler.py 加了一行判空
  [有] 为什么    空消息会让下游计数为负
  [有] 怎么验的  python tasks.py test,通过 3 / 失败 0
  [缺] 下一步    ——
  缺一项,交接打回。缺的是「下一步」——这一项最常被跳过,因为它看起来不属于「已完成」。
  ! 交接不是「告诉他我干了什么」,是「让他能接着干」。
  「改了什么、为什么、怎么验的」让他能判断,「下一步」让他能动手。四项少一项,他就得来找你。

  ④ 值班时什么能自动做
  --------------------------------------------------------------------
| 动作 | 能不能自动 | 为什么 |
|---|---|---|
| 跑测试、看退出码 | 能 | 只读,可回滚 |
| 重启服务 | 能,但要留记录 | 影响面大,可回滚 |
| 改配置并提交 | 不能 | 改了就生效,且难回滚 |
| 删数据、改表结构 | 不能 | 没有撤销键 |

  ! 值班的边界不是「几点到几点」,是「哪些动作不需要问人」。写得出来,值班才睡得着。

「后端改 data/」那条被拒,是这份 Demo 最想说的一句。 他在 src/ 的地盘里,但 data/ 是禁区。 两套规则叠起来,才拦得住这种「有权限但不该做」的请求。 六个请求里三个被拒,比例不低。 这说明矩阵不是摆设——没有它,这三个请求都会被执行,而其中两个会改到别人负责的目录。 交接那段缺的是「下一步」。 注意它是四项里唯一「指向未来」的,所以最容易被当成「不属于本次工作」。 最后那张值班表按「可回滚性」排,不按「重要性」排。 这个口径要记住——按重要性排,你会得出「重启服务最重要所以不能自动」这种反结论。

30 秒实验

  1. 画一张你自己的权限矩阵,三个角色就够。 画完拿最近五个改动对一遍,看有几个越界。
  2. 下一次交接,强迫自己写第四项。 写不出来,说明这次任务其实没完成。
  3. 列一下你值班时会自动做的三件事,和必须问人的三件事。 前者按可回滚性筛,后者按影响面筛。

常见误区

  1. 「人少,不用分角色。」 人少更要知道边界——因为一个人同时是前端和后端时,Agent 更不知道哪块不该动。
  2. 「交接写前三项就够了。」 前三项让他能判断,第四项让他能动手。 缺第四项,他第一件事就是来问你。
  3. 「值班能自动的越多越好。」 能自动的判据是「可回滚」,不是「省事」。 不可回滚的自动了,就是给自己埋雷。
自测三问(点开对答案) 1. 权限矩阵和禁区有什么区别?为什么要两套? —— **矩阵管「谁的地盘」,禁区管「谁都不许碰」。** **只看矩阵,「有权限」会被当成「该做」**——**而这两件事不一样。** 2. 交接四项里哪一项最常被漏?为什么? —— **「下一步」。** **它是唯一指向未来的,最容易被当成「不属于本次工作」。** 3. 值班时「能不能自动」按什么判? —— **按可回滚性,不按重要性。** **能回滚的可以自动,不能回滚的必须问人。**

下一篇 6.5 收这一章:三类项目各一份模板,拿同一个体检器过一遍。

相关笔记