给 AI 编码代理装"技能":一个文件决定它能做什么

给 AI 编码代理装

一、技能是什么

OpenCode 的"代理技能"机制,允许你用一个 SKILL.md 文件定义可复用的行为指令,放在仓库或主目录里,代理会把这些技能登记到工具描述中,需要时再按需加载完整内容。它不是插件、不是脚本,本质是一份结构化的说明书。

关键在"按需加载":代理平时只看到技能名称与描述,只有在判断需要时才读取全文。所以描述写得好不好,直接决定它会不会被选中。

二、放在哪:六个位置,就近优先

层级路径
项目(原生).opencode/skills/<name>/SKILL.md
全局(原生)~/.config/opencode/skills/<name>/SKILL.md
项目(Claude 兼容).claude/skills/<name>/SKILL.md
全局(Claude 兼容)~/.claude/skills/<name>/SKILL.md
项目(Agent 兼容).agents/skills/<name>/SKILL.md
全局(Agent 兼容)~/.agents/skills/<name>/SKILL.md

项目级的发现机制值得注意:它会从当前工作目录一路向上遍历,直到 git 工作树根目录,沿途加载所有匹配的技能。这意味着在子目录里启动代理,也能读到仓库根部的技能;但如果你在仓库外启动,项目级技能就完全读不到。

三、文件怎么写:两个必填字段

每个 SKILL.md 必须以 YAML frontmatter 开头,只识别这几个字段:name(必填)、description(必填)、license(可选)、compatibility(可选)、metadata(可选,字符串到字符串的映射)。未知字段会被忽略——不报错,直接丢。

name 的规则很严:长度 1–64 个字符,只能用小写字母和数字,可用单个连字符分隔,不能以连字符开头或结尾,不能有连续的 --,并且必须与所在目录名一致。

若把这条规则写成式子,就是"小写字母数字开头、以单个连字符分段、开头结尾不许连字符"。description 则要求 1–1024 个字符,必须具体到能让代理判断"什么时候该用我"。

判断描述写得好不好,有个简单标准:把技能名遮住,只读描述,你能说出它解决什么场景吗?说不出来,代理也选不中。

四、权限才是真正的安全边界

技能可以被限制。权限配置支持三种状态:

状态行为
allow技能立即加载
deny对代理隐藏,拒绝访问
ask加载前提示用户确认

规则支持通配符,可以按前缀批量管理,比如把内部类技能整体拒绝、把实验类技能设为需要确认。权限还能按代理覆盖:自定义代理在自己的 frontmatter 里声明,内置代理则写在全局配置里,让不同代理看到不同技能集。

如果某个代理完全不需要技能,可以彻底关掉这个工具,关闭后技能清单整块不再出现。

五、技能没生效?按这四步查

  1. 文件名必须全大写:SKILL.md,写成 Skill.md 就不会被识别;
  2. frontmatter 里 name 与 description 是否齐全;
  3. 技能名在所有位置是否唯一——同名冲突会导致行为不确定;
  4. 权限是否被设为 deny,被隐藏的技能不会出现在清单里。

这套机制的思路值得借鉴:把团队约定从聊天记录里搬出来,变成有版本、有权限、可审查的文件。对 AI 编码工具来说,"知道怎么做"比"更聪明"更能减少返工。