为什么 runbook 引用 slug 而不是显示名

2026-08-09

打开 agency-agents 仓库 strategy/ 目录下的 runbooks.json,你会看到一个有点反直觉的细节:里面定义的四个场景团队,成员写的全是 engineering-frontend-developertesting-evidence-collector 这种一串小写加连字符的字符串,而不是这些 agent 在花名册里对外显示的 Frontend Developer、Evidence Collector。

第一眼看上去这只是「机器可读文件用机器格式」的老套路。但 runbooks.json 自己的 _note 字段把理由写出来了,而那个理由值得任何一个维护多文件配置的人抄走。

slug 到底指什么

在这个仓库里,slug 就是 agent markdown 文件的文件名主干_note 里管它叫 corpus id。两个例子:

  • engineering/engineering-frontend-developer.md → slug 是 engineering-frontend-developer
  • specialized/agents-orchestrator.md → slug 是 agents-orchestrator

注意第二个。specialized 目录下的这个文件,文件名主干里压根没有 specialized 前缀。_note 专门提醒了这一点:文件名主干并不总是带 division 前缀。所以你不能靠「目录名 + 短横线 + 职能名」去拼 slug,只能回目录里查文件真名。

这个仓库一共 255 个带 frontmatter 的 agent markdown,分布在 17 个 division(核对日 2026-08-09)。255 个文件里,slug 与显示名的对应关系并不是一条规则能算出来的。翻几个花名册里的实例就明白了:

显示名(frontmatter 的 nameslug(文件名主干)
Frontend Developerengineering-frontend-developer
Senior Project Managerproject-manager-senior
Infrastructure Maintainersupport-infrastructure-maintainer
Persona Walkthrough Specialistdesign-persona-walkthrough
Agents Orchestratoragents-orchestrator

第一行是最规矩的情况:加个 division 前缀,空格换短横线,全部小写。第二行词序就反了,Senior 从头跑到了尾。第三行的 division 前缀 support 在显示名里根本不出现。第四行显示名多了一个 Specialist,slug 里没有。第五行前面说过,没前缀。

没有任何一条机械规则能同时算对这五行。 光看第一行和第五行就够了:前者必须补上 division 前缀才对,后者补了就错。同一段代码不可能既加前缀又不加前缀,除非它先去查一遍目录——那它就已经不是「规则」而是「查表」了。如果 runbook 里写的是显示名,那么任何一个要把 runbook 变成实际安装动作的程序,都得先解决「Senior Project Manager 是哪个文件」这个查表问题——而这张表本身还是会变的。

显示名为什么当不了引用键

_note 给的理由很短:显示名带前缀、会漂移,所以 roster 一律引用 slug——slug 抗改名、可测试

拆开看是两件事。

第一件是漂移。 显示名是给人看的字段,它天然会被改。一个 agent 的定位调整了、语气改了、职能范围扩了,最先改的就是 namedescription。这类修改在评审里几乎不会有人反对,因为看上去只是文案。但只要有第二个文件按显示名去引用它,这次「只是改文案」的提交就会在另一个文件里留下一条断掉的引用,而且改动者完全不会意识到。文件名不一样:重命名一个文件是件显眼的事,它会体现在 diff 的路径上,评审时一眼能看见。

第二件是可测试。 仓库里有个 scripts/check-runbooks.sh,它守的就是这条边界——runbook 里引用的每个 slug 必须能解析到真实存在的 agent 文件。这条检查之所以写得出来,前提是引用的东西和磁盘上的东西之间存在一个确定的对应关系:slug 就是文件名,解析规则只有一条,脚本按图索骥即可。

换成显示名,这个脚本就难写了:得先把 255 个文件的 frontmatter 全解析出来,建一张 name → 文件的映射,还得处理大小写、多余空格、以及万一两个 agent 的 name 撞车怎么办。能写,但复杂度和出错面都上了一个台阶。引用键选得对,校验脚本就是十几行;选得不对,校验脚本本身就成了要维护的东西。

顺带说一句,这个仓库对「配置漂移」是有系统性防御的,check-runbooks.sh 只是其中一环,旁边还有 check-divisions.sh(目录、脚本里的数组、CI 路径过滤器三处必须一致)和 check-tools.shtools.jsoninstall.shconvert.sh 必须一致)。它们的共同点是:把「两份数据必须对得上」这件事从人的自觉变成构建失败。

这条设计怎么一路贯穿到安装

slug 不只活在 runbook 里。往下游走一步就会发现,整条安装链路的目标路径模板也是用 slug 拼的。tools.json 里 16 种工具的用户级落点模板,绝大多数都带 {slug} 占位:Claude Code 是 .claude/agents/{slug}.md,Codex 是 .codex/agents/{slug}.toml,Cursor 是 .cursor/rules/{slug}.mdc。也就是说,你在 runbook 里写下的那个字符串,最终会原样变成落到磁盘上的文件名。

例外只有两个,而且例外本身也说明问题:Aider 的落点是 CONVENTIONS.md、Windsurf 是 .windsurfrules,都没有 {slug}。原因是它们的 installKindroster——所有 agent 合并进一个文件,产物形态里根本没有「一 agent 一文件」这回事,自然也就没地方放 slug。换句话说,路径模板里有没有 {slug},恰好反映了这个工具是按 agent 装还是整包装。

runbooks.json_note 描述的用途正是这个:给上层应用把一个 runbook 变成「一键部署一个团队」——读 roster、把每个 slug 映射到目录里的 agent、然后整组安装。这条链上每多一次「显示名转文件名」的翻译,就多一个可能对不上的接缝;全程用 slug,接缝就只剩下最初那次「人选 agent」。

有意思的是命令行这一侧留了个口子。install.sh--agent <slug,slug> 收的是 slug,而 --agents-file <path> 的说明里写的是「每行一个 slug 或名字」,还支持 # 注释。这不是自相矛盾,而是分层:面向人手写的入口可以宽松一点,允许你按记得住的名字写;面向机器解析、要进 CI 检查的配置文件则一律收紧到 slug。

这个分层是可以照抄的判断方式:一个字段是给人填的还是给程序读的,决定了它该不该容忍别名。

判断依据:你自己项目里的引用该用什么

把这条经验抽出来,就是一句话:跨文件引用要引用稳定 id,不要引用展示名。 但真到自己项目里,什么算「跨文件引用」、什么时候值得为它专门造一个 id,还是得有判断标准。下面几条可以直接拿来对照。

一、这个引用是人读的还是程序解析的? 文档正文里写 Frontend Developer 完全没问题,人读起来更顺。一旦这个字符串会被程序拿去查表、拼路径、做匹配,就必须换成稳定 id。agency-agents 的做法是两边都留:runbook 的说明文档(如 strategy/runbooks/scenario-startup-mvp.md)给人看,runbooks.json 给程序读。

二、被引用的那个字段,谁有权改、改的时候会不会想到你? 判断很简单:如果这个字段的修改属于「日常文案调整」,那它就不能当键。显示名、标题、描述都属于这一类。反过来,文件路径、目录结构的修改天然带有仪式感,改的人会更警惕。

三、有没有一个已经存在的天然 id 可以直接用? 这是 agency-agents 最省事的一步——它没有额外发明一套 id 体系,而是直接用了文件名主干。文件名本来就唯一(同目录下不可能重名),本来就稳定,本来就在版本控制里可见。能复用现成的唯一约束,就别新造一个需要自己维护唯一性的字段。

四、你能不能为这个引用写出一条自动校验? 这是最硬的一条检验标准。如果你选的键让「校验引用有效性」这件事变得写不出来或者写起来很别扭,多半是键选错了。反过来,键选对了,校验脚本会自然而然地简单到能顺手加进 CI。

五、一处引用还是多处引用? 只有一个地方引用时,用什么都行。像 agency-agents 这样,四个场景 runbook 加上安装脚本、转换脚本、目标路径模板都在引用同一批 agent,引用点一多,任何一次不一致的代价就被放大了。

几点限制

有几条需要说清楚,免得读者把这条设计想得太万能。

slug 并不是不会变。它就是文件名,重命名文件 slug 就变了。它的价值不在于永不改变,而在于改了以后能被立刻发现——文件路径变化在 diff 里显眼,引用断了 check-runbooks.sh 会在 CI 里报出来。稳定 id 解决的从来不是「不变」,而是「变了不会悄悄坏掉」。

显示名也不该被消灭。人得靠它工作,花名册、文档、激活提示词里用的都是显示名。正确的做法是两套并存、各司其职,而不是把机器口径推给人用。

最后,本文只讨论了引用机制本身。这套 runbook 与它上层的 NEXUS 方法论,是一批写在 markdown 与 JSON 里的文档和配置,靠提示词让模型按阶段推进,没有任何代码在强制执行阶段顺序——check-runbooks.sh 校验的也只是「slug 能不能解析到文件」,它管不着团队组得好不好、这批 agent 适不适合你的项目。引用键设计得干净,和这套方法论有没有用,是两码事。

延伸阅读


本文依据 agency-agents 官方仓库(github.com/msitarzewski/agency-agents)的 README、 tools.jsondivisions.jsonrunbooks.jsonscripts/ 下的安装与校验脚本整理,核对日 2026-08-09。 本文内容为仓库源码与文档口径,我们没有安装或运行过其中任何 agent。 目录、脚本与安装路径随上游更新而变动,请以仓库最新内容与 ./scripts/install.sh --help 的实际输出为准。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。