runbook 里的 slug 解析不到 agent 文件时怎么查

2026-08-09

agency-agents 仓库里有一层东西是纯文本的团队配置:strategy/runbooks.json。它按场景把一组 agent 打包成 roster,runbooks.json_note 说明了这份文件的用途——让上层应用把一个 runbook 变成「一键部署一个团队」:读 roster、把每个 slug 映射到目录里的 agent、然后整组安装。

映射这一步一旦断了,就是本文要讲的现象。

一、现象长什么样

典型有两种表现。一种是仓库自带的一致性脚本 scripts/check-runbooks.sh 报出问题——它守的就是「runbook 里引用的每个 slug 必须能解析到真实存在的 agent 文件」这一条。另一种是你手工照着某个 runbook 的名单往下装,把名单里的条目喂给安装脚本的 --agent 选择器,结果某几个条目对不上任何东西。

两种表现的内核是同一个:你手上的这个字符串,和磁盘上的 agent 文件对不上。

需要先划清一件事:check-runbooks.sh 这道门管的是「解析得到文件」。文件本身合不合规——有没有 frontmatter、name / description / color 三个必填字段齐不齐、行尾是不是 LF——那是 scripts/lint-agents.sh 那一套五道检查的职责。两道门解决两个问题,别指望其中一道替另一道兜底。

二、怎么确认是这个问题:三个可执行的判定动作

动作一,先把当前仓库真正认识的 agent 列出来。 安装脚本有一个列完就退出的开关:

./scripts/install.sh --list agents

--list 接受 toolsteamsagents 三种取值,列出后即退出,不写任何文件。你要找的那个字符串在不在这份清单里,一眼就有答案。在这里都找不到,说明问题在仓库这一侧,不是你的命令写错了。

动作二,用 --dry-run 走一遍完整的安装计划。 这是这个仓库对新手最有价值的开关:把计划打印出来但不落盘。

./scripts/install.sh --agent project-manager-senior --tool claude-code --dry-run

以上为按官方参数语义组合的示例,未逐项实测,以官方文档与 ./scripts/install.sh --help 的实际输出为准。它的价值在于,往 ~/.claude/agents/ 这类共享目录写上百个文件之前,你能先看一眼到底要写什么、写到哪。slug 对不上时,这一步就会暴露出来,而且什么都没弄脏。

动作三,跑仓库自己的一致性脚本。

./scripts/check-runbooks.sh

它是 CI 那一组自检脚本里专门管 runbook 的一支,和 check-divisions.sh(division 列表与磁盘、脚本数组、CI 路径过滤器保持一致)、check-tools.shtools.jsoninstall.shALL_TOOLSconvert.sh 的转换器集合保持一致)是同一个思路:把「配置漂移」当成明确的敌人。

Windows 上有个前置条件容易踩:这些都是 bash 脚本。install.sh 的平台注释写的是 Linux、macOS(需要 bash 3.2+)、Windows Git Bash / WSL。在 PowerShell 或 cmd 里直接敲,报的错和 slug 没有半点关系。

三、源码语义给出的处置

runbooks.json_note 把规则写得很直白:agents[] 里的条目是 slug——agent .md 文件的文件名主干(corpus id)

engineering/engineering-frontend-developer.md  →  engineering-frontend-developer
specialized/agents-orchestrator.md             →  agents-orchestrator

_note 还特别提醒了两点:文件名主干并不总是带 division 前缀;而显示名带前缀、会漂移。所以 roster 一律引用 slug——slug 抗改名、可测试。

这两句提醒基本覆盖了实际会翻车的全部情形:

偏差一:拿显示名当 slug 用。 花名册里有一个 agent 显示名是 Senior Project Manager,它的 slug 是 project-manager-senior。词序和显示名不一样,直接把显示名转成小写连字符是推不出来的。

偏差二:自己给 slug 补 division 前缀。 project-management 这个 division 下有七个 agent,其中六个的 slug 确实是 project-management- 开头(比如 project-management-studio-producer),第七个偏偏就是上面那个 project-manager-senior。再看 specialized:这个 division 有五十七个 agent,带 specialized- 前缀的只有十五个(比如 specialized-mcp-builderspecialized-codebase-archaeologist),剩下四十二个一个前缀都不带——agents-orchestratorbusiness-strategistlanguage-translator 都在这里。同一个目录下两种形态并存,前缀是文件名碰巧长成那样,不是规则。

偏差三:从编排文档里抄名字。 NEXUS 的激活提示词、七个 playbook、四份场景说明文档,正文里写的都是给人看的显示名——Trend Researcher、Evidence Collector、Studio Producer。那些是提示词文本,不是标识符。要 slug,回 runbooks.json 或花名册导出去核对,别从散文里反推。

偏差四:在不是 division 的目录里找文件。 divisions.json_note 明确列了几个顶层目录不算 division:integrations/convert.sh 写出的每工具转换产物,不是源 agent;strategy/ 放 playbook 和 runbook,没有 agent frontmatter;examples/scripts/ 同样被排除。check-divisions.sh 里用 NON_DIVISION_DIRS 排掉它们。顺带一个常被搞混的数字:仓库里 markdown 文件总数约 316,而带 frontmatter 的 agent 是 255 个,分布在 17 个 division,差额就是这些非 agent 文件。别拿 316 当 agent 数,也别在 integrations/ 里找源文件。

对应的处置方向就三条:拼错了就照文件名主干改回来;文件确实不在(改过名、还没提交、不在本次浅克隆里)就补文件或修 runbook 里的引用;找错目录就换目录。反过来说,如果你在自己项目里做类似的跨文件引用,这套设计值得直接照搬——引用稳定 id,不要引用展示名

四、处置后怎么验证

按顺序过三道,别只过一道:

  1. 重跑 ./scripts/check-runbooks.sh,让守 slug 解析的那道门自己说话,以脚本实际输出为准。
  2. 再跑一次 ./scripts/install.sh --list agents,确认改后的字符串确实出现在清单里——这一步验的是「安装脚本认识它」,和上一步的口径不完全重合。
  3. 如果这次动作里新建或改名了 agent 文件,补跑 ./scripts/lint-agents.sh。它有五道检查,其中三道是 ERROR 级:拒绝 CRLF 行尾、frontmatter 分隔符必须存在、name / description / color 三个必填字段必须齐全;推荐章节缺失和正文词数少于 50 只是 WARN,不会让检查失败。

第三步在 Windows 上尤其别跳过。lint-agents.sh 拒绝 CRLF 是有原因的,源码注释解释得很清楚:行尾多一个 \r,会让后面的 frontmatter 检查报出令人困惑的「missing frontmatter ---」,可文件开头明明就是 ---。Git 的行尾转换在 Windows 上默认就可能把文件变成这样,遇到这种自相矛盾的报错,先怀疑行尾。

如果这次还新建了 division 目录,divisions.json_note 给了固定顺序:建目录 → 在 divisions.json 加条目 → 跑 scripts/check-divisions.sh → 按它的报错去更新它指向的地方。别跳步,脚本会告诉你还有哪几处没同步。

五、什么情况说明不是这个原因

这一节是排查文章相对「报错大全」的真正增量。下面几种情形看着像 slug 解析失败,其实病根完全不在这里,按 slug 去改是白费功夫:

你在错的目录里找产物。 install.sh 的注释里,落点分两类:claude-codecodexgemini-clicopilotqwenzcodeosaurusopenclawhermesvibeantigravity 多在家目录,而 opencodecursoraiderwindsurf 写的是当前目录。给某个项目装完,跑到家目录去找,当然找不到;反过来也一样。tools.json 里部分工具还有 user 与 project 两套 dest 模板,比如 Claude Code 的两者都是 .claude/agents/{slug}.md,区别只在落家目录还是当前项目目录。要断言某个具体路径,回 tools.json 现查当前 scope,不要类推。

这个工具压根不按 agent 出文件。 tools.jsoninstallKind 定义为安装机制,一共三种:per-agent 是每个 agent 一份产物;roster 是所有 agent 合并成一个文件,Aider 的 CONVENTIONS.md 和 Windsurf 的 .windsurfrules 就是这一类;plugin 是构建出来的产物,不能按 agent 渲染成字符串,只能走 CLI,十六种工具里 Hermes 是唯一一个。你在 Aider 那边按 slug 找单个文件,找不到是必然的,跟 slug 写没写对无关。

装是装进去了,但工具里像没装。 Cursor 那条转换路径里,.mdc 的 frontmatter 是写死的 globs: ""alwaysApply: false——转换出来的规则默认不自动生效,需要在 Cursor 里按需引用。这个现象很容易被误判成「文件没落进去」,但它是转换规则本身决定的。

integrations/ 缺失或者过期。 链路是「源 agent markdown → convert.sh 渲染成各工具格式 → integrations/install.sh 拷到目标目录」。install.shintegrations/已转换的文件;集成文件缺失时它默认会自动调 convert.sh,除非你加了 --no-convert。加了这个开关又碰上产物没生成,报出来的问题跟 slug 无关。

你找的东西在 strategy/ 里,但那里没有可安装的 agent。 divisions.json_note 原话是 strategy/ 存放的是编排方法论,不是可安装的 agent。NEXUS 那套东西——三种激活模式、Phase 0 到 Phase 6 七个阶段、四份场景 runbook——是写在 markdown 里的方法论,不是一个可执行的调度器,没有任何代码在强制推进阶段或拦截质量门。它靠提示词让模型自己按阶段走。想在 strategy/ 下装出一个 agent,方向从一开始就是错的。

最后提一句 runbook 本身的设计。四份场景 runbook 里,incident-response 走的是 NEXUS-Micro,它的 roster 分成 always(6 个,含 support-infrastructure-maintainerengineering-devops-automatorengineering-backend-architectengineering-frontend-developer 等)和 post-fix(4 个:testing-evidence-collectortesting-api-testertesting-workflow-optimizerproduct-sprint-prioritizer)两组——把取证、回测、流程优化、重排优先级单独放在修复之后。这个「修完不算完」的结构,恰好也是排查 slug 问题时该有的态度:改对一个字符串只是修复,回头把 check-runbooks.sh 和 lint 补跑一遍,才算收尾。

另外,一次性把 255 个 agent 装进全局配置目录是有代价的——上下文占用、工具启动时的加载、命名冲突都可能找上门。用 --division--agent 收窄安装范围是更稳的做法。具体影响有多大我们没有测过,不给数字。

延伸阅读


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

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