Agent 方法论框架 superpowers:技能文件的跨平台契约

2026-07-29

本文基于 superpowers 仓库 commit 44c9b2d(2026-07-27)梳理,该项目仍在持续迭代,具体行为以仓库 https://github.com/obra/superpowers 最新代码与文档为准。

一个技能文件能不能在另一个工具里被正确触发,取决于它有没有把「动作」和「工具名」拆开写。 技能正文里只允许出现”读一个文件""派一个 subagent""建一条待办”这类动作描述,真实的工具名一个都不许写进去——它们被挪到按平台切分的映射文件里。superpowers 这个仓库把这条约定写成了硬规则:docs/porting-to-a-new-harness.md 里明确讲,移植到一个新工具时”绝不伸手进 skills/*/SKILL.md 去换工具名”,如果你发现自己为了让移植跑通而在改技能正文,那说明改错了地方,修法在映射文件里。

这不是风格洁癖。它决定的是同一份技能文本能不能一字不改地在 Claude Code、Codex、Gemini CLI、pi 这些不同的运行环境里生效。下面按你能跟着走的顺序拆:目录、frontmatter、工具映射、注入链路,最后是代价和避坑。

站内已有的 Claude Code 技能机制结构化输出不稳定的排查 讲的是通用方法论——技能这个概念是什么、怎么让模型的输出可控。本篇不重复这些,只做一件事:把 superpowers 这个具体项目怎么把方法论落成可核对的文件约定,逐条摊开给你看。你可以自己 clone 下来对着核。

一、目录布局:一个技能就是一个目录

skills/writing-skills/SKILL.md 里给出的结构极简:

skills/
  skill-name/
    SKILL.md              # Main reference (required)
    supporting-file.*     # Only if needed

一个技能对应一个目录,目录里必须有 SKILL.md,其余文件按需添。文档把这套命名空间称为 Flat namespace——所有技能平铺在一个可搜索的命名空间里,没有分类子目录。仓库当前的 skills/ 下有 14 个技能目录,从 brainstormingwriting-skills,全都是同一层。

什么时候该拆出独立文件,文档给了两条判据:一是重参考(100 行以上的 API 文档、完整语法表),二是可复用工具(脚本、模板)。反过来,原则性内容、50 行以内的代码模式、其他所有东西,一律内联在 SKILL.md 里。

这条判据在仓库里能直接验证。skills/subagent-driven-development/ 下除了 SKILL.md,还躺着 implementer-prompt.mdtask-reviewer-prompt.mdre-review-prompt.md 和一个 scripts 目录——这些是提示词模板,属于”可复用工具”。skills/systematic-debugging/ 下拆得更细,有 condition-based-waiting.mdroot-cause-tracing.mddefense-in-depth.md 这类技术展开,还有 find-polluter.sh 这个脚本,以及 test-academic.mdtest-pressure-1.mdtest-pressure-3.md 这几份测试场景。而 skills/dispatching-parallel-agents/skills/executing-plans/skills/using-git-worktrees/ 这些目录里就只有一个 SKILL.md,全部内联。

命名上的约定同样明确:动词优先、主动语态。文档举的对照是 creating-skills 而非 skill-creationcondition-based-waiting 而非 async-test-helpersroot-cause-tracing 而非 debugging-techniques。给出的理由是”按你做的事或核心洞察来命名”,并且指出动名词(-ing)形式特别适合描述流程。回头看那 14 个目录名,brainstormingwriting-plansexecuting-plansrequesting-code-reviewreceiving-code-review——确实是一致贯彻的。

这对你意味着什么:如果你要给自己团队攒一套技能库,别急着建 frontend/backend/ 这种分类目录。检索靠的是名字和描述里的关键词,不是路径层级。

二、frontmatter:只有两个必填字段,和一条反直觉的规则

writing-skills/SKILL.md 对 YAML frontmatter 的规定很短:

  • 两个必填字段:namedescription(其余支持字段指向 agentskills.io/specification)
  • 全部 frontmatter 加起来不超过 1024 字符
  • name 只能用字母、数字和连字符,不许出现括号和特殊字符
  • description 用第三人称,建议以 “Use when…” 开头,尽量控制在 500 字符内

前四条都是机械约束。真正反直觉、也最容易写错的是第五条:description 只能描述何时使用,不能概括这个技能做什么。

文档把理由写得很具体,属于测出来的结论而不是审美偏好。原文记录的现象是:当描述里概括了技能的工作流程时,Agent 可能会照着描述执行,而不去读技能正文。举的例子是一条写着 “code review between tasks” 的描述,导致 Agent 只做了一次评审,尽管技能正文的流程图清楚画着两次(先查规格符合度,再查代码质量)。把描述改成不带任何流程信息的 “Use when executing implementation plans with independent tasks” 之后,Agent 才正确读了流程图并走完两阶段。

文档把这个现象叫做”陷阱”:概括流程的描述会造出一条 Agent 一定会走的捷径,技能正文于是变成被跳过的文档。

去仓库里核对,这条规则的执行度相当高。这几条是原样的:

  • test-driven-developmentUse when implementing any feature or bugfix, before writing implementation code
  • systematic-debuggingUse when encountering any bug, test failure, or unexpected behavior, before proposing fixes
  • subagent-driven-developmentUse when executing implementation plans with independent tasks in the current session
  • writing-plansUse when you have a spec or requirements for a multi-step task, before touching code

全是纯触发条件,没有一个字讲流程。注意 test-driven-developmentsystematic-debugging 这两条末尾都带了 “before …” 从句——文档在”为违规症状更新描述”那一节说得很直白:把”你即将违反这条规则”的症状写进描述里。你正要写实现代码、你正要提修复方案,这两个时刻正是技能该被拉起来的时刻。

例外只有一条。brainstorming 的描述是 You MUST use this before any creative work - creating features, building components, adding functionality, or modifying behavior. Explores user intent, requirements and design before implementation. 它不以 “Use when” 开头,也是仓库里唯一一条在 YAML 里加了双引号的描述。

描述字段的另一层作用是被检索。文档单列了”关键词覆盖”一节,要求把 Agent 会拿去搜的词铺进去:报错原文(“Hook timed out”、“ENOTEMPTY”、“race condition”)、症状词(“flaky”、“hanging”、“zombie”、“pollution”)、同义词组(“timeout/hang/freeze”、“cleanup/teardown/afterEach”)以及具体的命令和库名。同时提醒描述问题本身而不是某种语言的具体症状——写”竞态条件”而不是写 setTimeout,除非这个技能本来就是绑定某项技术的。这套写法和 Agent 工具描述该怎么写 里的思路是同一类问题:描述字段是被当作路由信号消费的,不是给人看的说明书。

至于为什么这么抠 500 字符和 1024 字符:writing-skills/anthropic-best-practices.md 开头那句话是理由——上下文窗口是公共资源。启动时预载的只有所有技能的元数据(name 和 description),正文要等技能相关时才读。所以描述字段是每次会话都要付的固定成本。这块的取舍逻辑,上下文预算怎么分配 里讲的是通用做法,superpowers 的处理是给不同类型的技能定死目标词数:入门流程类每个低于 150 词,高频加载的技能全文低于 200 词,其他技能低于 500 词,并给了 wc -w skills/path/SKILL.md 这条验证命令。

三、跨平台工具名映射:真实工具名住在哪里

docs/porting-to-a-new-harness.md 把整套体系拆成三个组件,这是理解跨平台契约的骨架:

  1. 技能(与平台无关)skills/ 下的一切是唯一事实来源,每个平台逐字共享。技能被写成描述动作——“invoke a skill”、“read a file”、“dispatch a subagent”、“create a todo”——从不指名某个具体工具。
  2. 工具映射(按平台):把这套动作词汇翻译成该平台的真实工具名,住在 skills/using-superpowers/references/<harness>-tools.md,或者内联进该平台的启动注入器。
  3. 启动注入(按平台):每次会话开始把 skills/using-superpowers/SKILL.md 完整注入模型上下文,用 <EXTREMELY_IMPORTANT> 包起来,后面接上工具映射。

第三条后面跟着一句判断:启动注入就是集成本身。 没有它,技能文件全都是死的——躺在磁盘上,永远不被调用。

references/ 目录当前有四个映射文件:antigravity-tools.mdcodex-tools.mdgemini-tools.mdpi-tools.md。其中三份(Gemini、pi、Antigravity)用的是同一句开场白——“Skills speak in actions”,技能说的是动作,在本平台上这些动作解析为下面这张表里的工具。codex-tools.md 是例外:它压根没有动作对照表,开篇直接讲一个配置开关,通篇只写差异项——配置门槛、环境探测、沙箱受限时怎么收尾。可见”映射文件”这个位置装的不只是词表,也是这个平台上所有跟别处不一样的地方。

gemini-tools.md 是最完整的一份,映射表列得很齐:读文件是 read_file,一次读多个文件是 read_many_files,新建文件是 write_file,改文件是 replace,跑 shell 是 run_shell_command,搜内容是 grep_search,按名字找文件是 glob,列目录是 list_directory,抓 URL 是 web_fetch,搜网页是 google_web_search,调用技能是 activate_skill,派 subagent 是 invoke_agent 并传 agent_name: "generalist",任务追踪是 write_todos。这份文件还额外说明了:技能里提到”你的指令文件”时,在 Gemini CLI 上指的是 GEMINI.md;个人技能目录在 ~/.gemini/skills/,同时 ~/.agents/skills/ 是跨运行时的别名,两者同时存在时后者优先。

有意思的是能力缺失时怎么写。pi-tools.md 的表只有两行——派 subagent 和任务追踪——因为 pi 核心既不自带标准 subagent 工具,也不自带标准任务清单工具。文件里写:如果装了 pi-subagents 这个可选配套包,就用它提供的 subagent 工具;如果没有任何 subagent 工具可用,不要伪造 Task 调用,改成在当前会话里串行执行,或者直接说明这项可选能力没装。任务追踪同理,退化到 Superpowers 的计划文件、Markdown 清单或者仓库里的 TODO.md。文件末尾还补了一句兼容说明:旧版文档里提到的 TodoWrite,一律按上面这个”任务追踪”动作理解。

antigravity-tools.md 里有一条更值得看的坑。它写着:Antigravity 没有 todo 工具——manage_task 管的是后台进程(list/kill/status/send_input),不是清单。所以技能说”建个待办清单”时,正确做法是维护一份任务工件:用 write_to_file 存一份 Markdown 清单,带上 IsArtifact: trueArtifactMetadata.ArtifactType: "task",过程中用 replace_file_content / multi_replace_file_content 改成 - [x]。派 subagent 则走 invoke_subagent,传内置的 TypeNameself 用于完整能力的工作,research 用于只读。

codex-tools.md 则暴露了另一类问题:能力可能被配置开关挡着。它要求在 ~/.codex/config.toml 里加:

[features]
multi_agent = true

开了才有 spawn_agentwait_agentclose_agentdispatching-parallel-agentssubagent-driven-development 这两个技能才跑得起来。这份文件还给了 subagent 的生命周期建议:评审 subagent 返回后就关掉;实现者 subagent 要一直开着直到它那条任务的评审通过(因为修复循环要接着用同一个实现者),然后再关;如果你的运行环境没法给已生成的 agent 再发消息,那就每轮修复都新派一个实现者,带上任务简报、报告文件和评审意见。这类关于 subagent 的分工与调度 的细节,在不同工具上差异相当大,映射文件就是承接这些差异的地方。

映射的存放位置本身也随集成形态变。Kimi Code 那份就不在 references/ 里——它内联在 .kimi-plugin/plugin.jsonskillInstructions 字段里,是一大段带转义换行的字符串,里面写着”技能提到 TodoWrite 时用 Kimi Code 的 TodoList 工具""技能说 Task tool (general-purpose) 时用 Agent 工具并传 Kimi 自己的 subagent 类型,不要把 general-purposesubagent_type 传进去”。pi 更麻烦,映射同时存在于两个地方:.pi/extensions/superpowers.ts 里的 piToolMapping() 内联版和 references/pi-tools.md。移植指南对此的原话是:如果你在两个地方维护,就两边都得更新,否则这个移植只做了一半。

组成部分它负责什么对应仓库位置你什么时候会碰到它
技能正文只写动作,不写工具名,各平台逐字共享skills/<name>/SKILL.md写新技能、改既有技能时
技能附属文件重参考与可复用工具,按需拆出skills/subagent-driven-development/implementer-prompt.mdskills/systematic-debugging/find-polluter.sh内容超过 100 行、或要复用脚本模板时
工具名映射把动作词汇翻成该平台真实工具名,并给出能力缺失时的降级写法skills/using-superpowers/references/ 下的 codex-tools.mdgemini-tools.mdpi-tools.mdantigravity-tools.md接一个新工具、或某个动作在你的工具里跑不通时
启动注入脚本每次会话把 using-superpowers 的内容送进模型上下文hooks/session-starthooks/run-hook.cmdhooks/hooks.jsonhooks/hooks-cursor.json技能压根不触发时,第一个要查的地方
各平台清单声明技能目录、hook 配置、上下文文件等安装组件.claude-plugin/plugin.json.codex-plugin/plugin.json.cursor-plugin/plugin.json.kimi-plugin/plugin.jsongemini-extension.jsonpackage.json做分发、加新平台时
版本同步登记列出所有带版本号的清单,供 scripts/bump-version.sh 统一改.version-bump.json新增了一份带 version 字段的清单时
移植指南三种集成形态、验收标准、踩坑索引docs/porting-to-a-new-harness.md动手接新工具之前

四、注入链路:三种形态和它们各自的坑

移植指南把集成分成三种结构形态,区分标准只有一条——启动注入怎么送到模型面前

形态 A:shell hook。 平台在会话开始时跑一条 shell 命令并读取它的 stdout。仓库里的实现是 hooks/run-hook.cmd 分发到 hooks/session-start,后者读完整的 SKILL.md(连 frontmatter 一起原样输出),包上前言,转义,然后打印该平台要的 JSON。坑在于 JSON 的字段名和嵌套每个平台都不一样,hooks/session-start 靠环境变量分三支:Cursor(设了 CURSOR_PLUGIN_ROOT)用 { "additional_context": "…" };Claude Code(设了 CLAUDE_PLUGIN_ROOT 且没设 COPILOT_CLI)用 { "hookSpecificOutput": { "hookEventName": "SessionStart", "additionalContext": "…" } };其余走 Copilot CLI / SDK 标准的 { "additionalContext": "…" }

指南直接把这称为陷阱:字段发错或者多发一个,注入要么根本不发生,要么发生两次——因为 Claude Code 会同时读 additional_contexthookSpecificOutput 且不去重,两个都输出就是双重注入。

hook 配置文件本身的 schema 也随平台变。对比仓库里这两份就很清楚:hooks/hooks.jsonSessionStart 大写键、带 matcher: "startup|clear|compact"、带 type/shell/async 字段、命令里引用 ${CLAUDE_PLUGIN_ROOT}hooks/hooks-cursor.json 则是 "version": 1、小写 sessionStart 键、相对路径 ./hooks/run-hook.cmdmatcher/type/async 一个都没有。指南的建议是照着最接近的那份现有文件抄,别指望有一个通用模板。

形态 B:进程内插件。 平台加载一个 JS/TS 模块,你在生命周期回调里拿代码注入。参考实现是 .opencode/plugins/superpowers.js.pi/extensions/superpowers.ts。这里的注入内容是你自己拼的:读 SKILL.md、剥掉 YAML frontmatter、拼上 <EXTREMELY_IMPORTANT>、一段”这个技能已经加载过了别再调”的前言、正文、内联工具映射、闭合标签。

三个必须复刻的细节:注入成 user 角色的消息而不是 system 消息(指南给的理由是 system 消息每轮重复会撑 token,且多条 system 消息会让某些模型出问题);要有去重守卫,因为生命周期回调会反复触发(OpenCode 的 transform 每个 agent step 都跑,pi 的 context 每轮都触发),注入前先查标记;要处理上下文压缩,压缩之后得重新注入,pi 的做法是在 session_startsession_compact 上置 injectBootstrap 标志、在 agent_end 上清掉,并把消息插在压缩摘要之后。

形态 C:指令文件。 平台既没 shell hook 也没代码插件,只有一个上下文文件——但必须是你安装的扩展自带并由清单声明的那个文件。仓库里的例子是 gemini-extension.json 里的 contextFileName 字段指向 GEMINI.md,而 GEMINI.md 里只有两个 @-include:启动技能和工具映射文件。这种形态没有注入器,所以不剥 frontmatter 也不拼字符串,平台原样加载。

三种形态之上还压着一条通用规则:一切通过平台自己的安装机制交付,绝不编辑用户的文件。 指南明确禁止移植代码去改用户的全局或个人配置(~/.gemini/config/AGENTS.mdsettings.jsontrustedFolders.json、手改 ~/.bashrc 等),理由是”平台自己决定加载什么,你的安装产物是你唯一能写的东西”。Gemini 的上下文文件之所以合规,是因为它随扩展一起装进去、由清单声明,平台加载的是扩展自带的文件,不是你在用户家目录里改过的文件。

还有一个容易忽略的反向操作:.codex-plugin/plugin.json 里那个空的 "hooks": {}故意写的,用来压掉 Codex 对 hooks/hooks.json 的自动发现——因为 Codex 原生就能发现技能,不需要跑会话启动 hook。

判定移植做完了没有,指南给的验收测试只有一句话:在干净会话里发 Let's make a react todo list,必须在写出任何代码之前自动触发 brainstorming 技能,并且要把完整对话记录贴进 PR。前置的冒烟检查更简单:开个会话问模型它有什么超能力,注入成功它就知道。

五、边界与代价:这套设计放弃了什么

描述字段不许写流程,代价是发现成本转移。 你扫一眼技能列表,只能看出”什么时候该用”,看不出”用了会发生什么”。想知道流程只能把正文读进来。这是拿”看一眼就懂”换”不会照着描述抄近路”,对做技能索引、做技能选型的人不友好。

正文不许出现工具名,代价是每加一个平台就多一份映射要维护。 pi 甚至维护两份。这些映射文件里的工具名会随平台版本漂移——manage_task 这类”名字看着像但功能不是”的工具,只能靠人工核对发现。指南对此的态度是”绝不发明工具名”,它认可的权威来源不是文档而是平台自己——在活会话里让模型逐行列出它能调用的工具机器名,用它报出来的那份。这意味着每个平台的映射都得有人在真实环境里跑一遍才敢写。

扁平命名空间,代价是没有层级检索。 14 个技能还行,几十上百个技能时,全靠描述里的关键词覆盖来命中。文档给出的补偿手段是关键词铺设和动词优先的命名,但这终究是软约束。

依赖会话启动自动注入,代价是有些工具进不来。 指南把”每次会话无需人工介入的自动注入”列为唯一不可协商的硬性要求,并直说:如果唯一的办法是让人每次会话手动粘一段提示词、跑一条命令、开一个模式,这个平台没法被正确支持,验收测试会挂,PR 会被关。这不是能力歧视,是承认了一个事实——手动触发的东西必然会被忘记。

subagent、todo、web 抓取都是”可降级”能力,降级是真降级。 指南对”可降级”的定义是:技能本身已经写好了缺这个工具时的兜底措辞。但兜底意味着 subagent-driven-development 在没有 subagent 工具的平台上,要么串行执行,要么直接报告能力缺失。并行加速这件事就没了。

流程本身让开发变慢,而且是设计如此。 writing-skills 里那条 Iron Law 写着:没有先失败的测试,就不许有技能。这条对新建技能和修改既有技能同样生效——“写了技能才测?删掉重来。改了技能没测?同样违规。“后面还堵死了一串退路:不许因为”只是加一节”就跳过,不许把没测过的改动留着”当参考”,删就是删。文档里还有一节专门列了跳过测试的常见借口和对应反驳,八条,“技能显然很清楚""只是个参考文档""测试是过度设计""我很有信心”全在里面。

微观测试那一节的成本更直观:每次调用一个全新上下文的样本,必须包含一个无指导的对照组,每个变体至少 5 次重复,每一条被标记命中的结果都要人工读一遍(因为模板回声和被引用的反例会伪装成命中)。对一个改三行字的调整来说,这是彻头彻尾的过度设计。

它会让 Agent 更啰嗦。 using-superpowers/SKILL.md 要求模型在任何响应或动作之前先调用相关技能——包括反问澄清问题、探索代码库、检查文件之前——然后声明 “Using [skill] to [purpose]“,并且技能里每有一条清单项就建一条待办。这些都是实打实的 token 和轮次开销。

明确不管的事。 这套契约管的是技能文件的形状和触发链路,不管技能里写的技术内容对不对。测试通过只证明 Agent 会照做,不证明照做是对的。它也不管模型选型、不管成本控制、不管你的代码风格。移植指南甚至留了个诚实的出口:有些”新平台”其实是既有集成换了个安装器(指南举的例子是 Factory 的 Droid,用自己的 plugin install 命令消费 Claude Code 插件),这种情况下”一次移植除了在 README 里加一段话什么都没往仓库里加,也是完全合格的结果”。

六、上手与避坑清单

把流程写进 description。 会踩是因为写文档的本能就是先说这东西做什么。后果是 Agent 照着描述执行,正文里的多阶段流程被压扁成一步。避法:描述里只留触发条件,第三人称,“Use when” 开头,流程一个字不写;写完自己读一遍,如果能从描述里推出步骤,就是没写对。

在技能正文里写死工具名。 会踩是因为你在自己惯用的工具里调试,顺手就写了当前工具的名字。后果是换到 Gemini CLI 上 read_file 才对、replace 才是改文件,正文里的名字全成了错误指令。避法:正文只写动作,工具名进 references/<harness>-tools.mdSKILL.md 的 “Platform Adaptation” 那一节是移植时唯一允许动的地方,因为它只是个指针列表。

hook 脚本带 .sh 后缀。 会踩是因为给 shell 脚本加扩展名是通用习惯。后果是 Claude Code 在 Windows 上会给任何含 .sh 的命令前面加 bash,变成双重调用。避法:hook 脚本一律不带扩展名(仓库里就是 hooks/session-start),跨平台靠 hooks/run-hook.cmd 这个既是合法 batch 又是合法 shell 脚本的多语言文件分发——Windows 上 cmd.exe 跑 batch 段去找 bash,Unix 上开头的 : 让 batch 段变成空操作。别写按操作系统分的多个变体。

同时输出两种注入 JSON 字段。 会踩是因为”多发一个总没坏处”的直觉。后果是 Claude Code 两个字段都读且不去重,启动内容被注入两遍,白烧 token 还可能让模型行为异常。避法:先确认目标平台到底吃哪个字段和哪层嵌套,注册一个临时 hook 打印环境变量和一个唯一标记串,观察哪个变量能识别平台、stdout 到底有没有被吃掉,确认了再写正式分支。

新增了带版本号的清单却没登记。 会踩是因为加清单和改版本号是两件事,很容易只做前一件。后果是 scripts/bump-version.sh 不认识它,发出去的是旧版本号。避法:新清单的路径和版本字段要写进 .version-bump.json,那里当前登记了七个条目(package.json、四份 plugin.jsonmarketplace.json 里的 plugins.0.versiongemini-extension.json);如果你的平台是搭已登记文件的车(pi 就是在根 package.json 里声明的),那就不用加。

为了塞启动内容去改用户的全局配置。 会踩是因为安装器可能会把你放进去的上下文文件悄悄丢掉——插件安装通常只拷贝它认识的组件(技能、agent、命令、MCP、hook、context),没声明的文件直接消失,于是你以为”这平台不支持”,转头去改用户配置。正确的解法不是投降,是把启动内容做成安装器认得的组件:有 contextFileName 这类字段就声明它,并且在安装时从活的 SKILL.md 加工具映射现生成,这样装上去的内容不会和仓库漂移。指南记了一个真实案例:有位移植者错误地下了”这平台做不到”的结论,原因是他把文件放进去了却没声明 contextFileName,于是被当成无法识别的文件剥掉了。

把”绝不用文件工具手动读技能文件”理解成”永远不许读”。 会踩是因为移植指南在讲”没有原生技能工具的平台怎么办”时,把这条禁令转述得很绝对。这里有个值得自己核一下的细节:指南把这句话归给 using-superpowers/SKILL.md,但当前版本的技能正文里已经找不到这句原话了,只剩指南在转述——这正好印证了指南自己那句”指南和代码打架时以代码为准”。禁令的实际意思是”不要绕过你所在平台的技能加载机制”。在没有技能工具的平台上,读 SKILL.md 就是那个机制,所以读它是遵守规则而不是破坏规则。避法:如果你在接的平台属于这种情况,就在工具映射里把”读 SKILL.md 是本平台被认可的加载路径”明说出来,别让模型自己纠结。

假设一个分叉出来的工具会继承母体行为。 会踩是因为它长得像、连清单字段和 @-include 语法都一样。后果是某个 Gemini 衍生的工具接受 @./path 语法,却把它当成”提示模型可以去读”(模型会发一次文件读取调用),而不是保证内联展开——这是”启动内容每次都在”和”模型也许会去读”的区别。避法:做唯一标记串测试,往里注入一个无意义的 token,开新会话确认这个 token 在没有任何工具调用的情况下就在上下文里;如果不在,把内容内联进去,别用 @-include。

收束

这套契约的核心其实只有一句话:内容与平台解耦,靠的是词汇层的纪律,不是靠抽象层。 技能说动作、映射说工具、注入说交付,三层各管各的,任何一层越界都会在别的平台上炸掉。

拿去自查的话,四个问题足够:你的 description 里能读出流程吗(能就重写);你的技能正文里出现过任何一个具体工具名吗(有就挪走);你的启动内容是通过安装机制交付的、还是你伸手改了用户的配置文件(后者要重做);在一个干净会话里发一句最普通的开发请求,该触发的技能触发了吗(没触发就先修注入,别管别的)。

接下来该读哪个文件,看你要干什么:想写技能,读 skills/writing-skills/SKILL.md 末尾那份创建清单——RED / GREEN / REFACTOR 三阶段之外还挂着”质量检查”和”部署”两组,一共五组勾选项,文档要求每一条都建一条待办;想接新平台,读 docs/porting-to-a-new-harness.md,尤其是 Appendix A 那张现有集成索引表——八行分别列出每个平台的入口文件、启动机制、工具映射、测试和分发渠道,找到跟你的目标最像的一行,然后去读它指的那几个文件。指南自己也写了:当指南和代码打架时,以代码为准,然后回来修指南。

本文属于 superpowers 方法论专题(共 30 篇,含三篇与其它开源 Agent 项目的对照)。想看把资产铺满的另一种取向,见 ECC 开源 Agent 套件专题

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