# 解剖 Skill：Skill 工程化实战指南（二）

> Skill 是给模型的作业指导书,不是函数调用。四件套(Metadata / allowed-tools / SKILL.md / scripts)+ 三阶段生命周期(注册 → 匹配 → 执行),讲清何时该写、怎么写不跑偏。

- 原文链接: https://laojin.blog/blog/20260430_skill_engineering_guide_2
- 作者: 老金
- 发布日期: 2026-04-30
- 标签: Skill, Claude Code, AI 工程化, Prompt Engineering, Agent

---

![解剖 Skill：Skill 工程化实战指南（二）](https://pic-1258874139.cos.ap-hongkong.myqcloud.com/laojinblog/posts/20260430/00_cover.png)

在上一篇中,我们达成了一个共识:把 Prompt 当工程方案,迟早要出事。要让 AI 真正成为稳定输出的生产力组件,我们需要将其封装为 Skill(技能)。

很多开发者对 Skill 的理解还停留在"稍微高级一点的 Prompt 模板",这就大错特错了。今天,我们拿起"手术刀",划开 Skill 的外皮,看看它内部到底长什么样,以及当你在终端或 IDE 里敲下回车时,底层系统到底经历了怎样的一生。

## Skill 的"解剖学":一个标准件的四个单元

不要把 Skill 想象成一段纯文本。在 Claude Code 里,一个标准的 Skill 是一个**目录**,里面由四类文件各司其职。如果把它比作一个人体,它有四个不可或缺的器官:

```
.claude/skills/
└── cross-platform-code-review/
    ├── SKILL.md          ← ①②③ 元数据 + 指令骨架
    ├── references/       ← ③ 长参考资料(按需加载)
    │   └── harmonyos-api-compat.md
    └── scripts/          ← ④ 确定性逻辑(交给代码跑)
        └── run_linter.sh
```

![Skill 的四件套:元数据 Frontmatter、权限边界 allowed-tools、核心指令 SKILL.md、确定性脚本 scripts/](https://pic-1258874139.cos.ap-hongkong.myqcloud.com/laojinblog/posts/20260430/01_four_organs.png)

### ① 元数据(Frontmatter):AI 的"简历"

这是最容易被忽视,却决定了 Skill 能否被准确召唤的关键。它写在 SKILL.md 顶部的 YAML frontmatter 里,最关键的两个字段是 `name` 和 `description`。

在"手工作坊"时代,你起名字可能叫 `prompt_v3_final.txt`。但在 Skill 的世界里,`description` 是**写给大模型的"调度路由"看的** —— Claude Code 在会话启动时,只会把每个 Skill 的 name + description 放进可发现列表(这就是所谓的 progressive disclosure),正文要到被命中后才加载。所以 description 写得好不好,直接决定这个 Skill 会不会被用上。

❌ **反面教材:** `description: 用于检查代码。`(太宽泛,AI 根本不知道什么时候该调它)

✅ **工程规范:** `description: 当用户要求进行跨平台(如 Flutter/HarmonyOS)的 UI 组件代码审查时触发,重点检查状态管理、内存泄漏及平台特定 API 兼容性。`

一个完整的 frontmatter 大致长这样:

```yaml
---
name: cross-platform-code-review
description: 当用户要求进行跨平台(如 Flutter/HarmonyOS)的 UI 组件代码审查时触发,重点检查状态管理、内存泄漏及平台特定 API 兼容性。
allowed-tools: Read, Bash
---
```

### ② 权限边界(allowed-tools):真正的"安检门"

这是 Skill 工程化里最实用、也最容易被新手忽略的一个字段。`allowed-tools` 声明了这个 Skill **被允许使用哪些工具** —— Read / Write / Bash / WebFetch 等等。没写的工具,Skill 就调不到。

告别自然语言模糊性的正确姿势,不是给 Skill 定义 JSON Schema 入参(那是 Tool Use 的机制),而是**通过 allowed-tools 把权限边界收窄,再在 SKILL.md 正文里写清楚输入约定和输出结构**。用户再怎么胡言乱语,能干什么干不了什么都在这一行里被钉死:

```yaml
allowed-tools: Read, Bash
```

纯文本处理的 Skill 只开 `Read, Write` 就够;需要跑确定性脚本时再开 `Bash`,并在项目 `.claude/settings.json` 里把允许执行的命令收窄到精确白名单。**最小权限原则靠的是这一行,不是靠你在正文里写"请不要删库"这种口头约定。**

### ③ 核心指令(SKILL.md 正文):固化的"肌肉记忆"

这是传统 Prompt 演变来的部分,但因为有了前面两层的铺垫,你在这里**再也不需要写诸如"请以 JSON 格式输出"、"请不要说废话"这种防御性指令**了。你只需要专注在业务逻辑上 —— 具体的架构规范、代码风格、步骤清单。

这一部分的关键工程习惯是:**正文只写"步骤和决策规则",长知识挪到 `references/`**。

很多人喜欢把风格指南、行业术语表、合规红线一股脑塞进 SKILL.md 正文,结果正文膨胀到几千行,模型每次命中都要啃完整份 —— token 成本和注意力成本同时爆炸。正确姿势是把长资料抽成 `references/harmonyos-api-compat.md` 这种分册,在正文里用一句"按 `references/harmonyos-api-compat.md` 的清单逐项核对"按需引用,Claude 只在执行到那一步时才会读那份文件。

### ④ 确定性脚本(scripts/):伸向物理世界的"手"

Skill 往往不是孤立的。在检查完代码后,它可能需要调用本地的 Linter 跑一下,或者按固定规则校验输出字数、Emoji 数、JSON 结构是否合法。

这些**能交给代码的逻辑,就不要交给模型** —— 让模型"自己数 Emoji 个数"远不如让它跑一下 `scripts/validate_output.py` 靠谱。Skill 的 `scripts/` 目录就是放这些确定性处理脚本的地方,通过 `allowed-tools: Bash` 授权后由模型在步骤里调用。

如果需要更复杂的外部能力(连数据库、调内网 API、访问第三方服务),则走 **MCP** —— 在项目里挂一个 MCP server,SKILL.md 里调用它暴露的 tool 即可。Skill 本身不直接管外部系统接入,这件事交给 MCP。

## Skill 的生命周期:它是怎么被加载和激活的?

了解了构造,我们来看看一个 Skill 是如何在你的工作流里"活"过来的。它的生命周期主要分为三个阶段:

![Skill 三阶段生命周期:注册与发现 → 意图匹配与指令加载 → 执行与工具调用](https://pic-1258874139.cos.ap-hongkong.myqcloud.com/laojinblog/posts/20260430/02_lifecycle.png)

### 阶段一:注册与发现(扫描与挂载)

当你启动 Claude Code 时,系统会扫描两个目录:

- 项目级:`<repo>/.claude/skills/`
- 用户级:`~/.claude/skills/`

系统从每个 Skill 目录下读取 SKILL.md 的 **frontmatter**,把 `name` 和 `description` 放进"可发现 Skill 列表"。**注意:此时正文还没被加载进 context** —— 这是 Skill 相对于"塞进 system prompt 的超级 Prompt"最本质的优势,叫 progressive disclosure(渐进式披露)。否则你装 50 个 Skill,context 第一轮就爆炸了。

这时候,AI 就像一个拿着一串钥匙名牌的管家:它知道每把钥匙叫什么、能干什么,但还没真正取出钥匙。

### 阶段二:意图匹配与指令加载(路由)

当你在对话框输入:"帮我看一下 `login_page.dart`,马上要上鸿蒙了,查一下有没有坑。" Claude 底层会进行如下决策:

1. **意图识别**:用户在请求代码审查,涉及跨平台(HarmonyOS)。
2. **Skill 匹配**:扫描可发现列表,发现 `cross-platform-code-review` 的 description 完美命中。
3. **正文加载**:把这个 Skill 的 `SKILL.md` 正文加载进当前 context,作为后续生成的指令基线。

这一步和 Tool Use 有一个本质差异:**Skill 不会"从用户自然语言里强制抽取参数成 JSON"** —— 用户的原话整段保留,由模型在加载了 SKILL.md 指令之后去自行理解和抽取。"待审查文件是 `login_page.dart`"、"目标平台是 HarmonyOS"这些信息的识别,发生在模型按 SKILL.md 步骤执行时,而不是在一个独立的"参数抽取器"里。

### 阶段三:执行与工具调用

拿到指令后,模型按 SKILL.md 的步骤逐条执行:

- 需要读文件 → 调用 `Read` 工具(前提是 `allowed-tools` 允许)
- 需要跑脚本 → 调用 `Bash` 执行 `scripts/run_linter.sh`
- 需要长参考 → 读取 `references/harmonyos-api-compat.md`
- 需要外部服务 → 调 MCP server 暴露的 tool

最后把干净、格式化的结果吐给你。整个过程,你只觉得是跟 AI 说了一句话,但在底层,它经历了一次**"发现 → 加载 → 按 runbook 执行"**的完整作业流程。

> 💡 **关键心智模型**:Skill 不是函数调用(那是 Tool Use),而更像"模型发现并执行了一份可复用的作业指导书(runbook)"。没有函数签名,没有强类型返回值,有的是步骤、决策、工具授权和确定性校验。

## 什么时候应该果断写一个 Skill?

虽然 Skill 很好,但如果你把所有需求都封装成 Skill,那叫过度设计。作为一个高阶工程师,你需要有一套判断标准。

![三种情况:高频重复、团队纪律、自动化流转,立刻把它写成 Skill](https://pic-1258874139.cos.ap-hongkong.myqcloud.com/laojinblog/posts/20260430/03_when_to_write.png)

当你遇到以下三种情况,**立刻把它写成 Skill:**

- **🚨 场景一:高频重复的"脏活累活"**
    如果你发现自己这周已经是第三次输入"请帮我把这段逻辑转成包含完整单元测试的代码"时,这就是明确的信号。高频调用的场景值得被固化 —— 一次写好,未来每次只需要一句话触发。

- **🚨 场景二:需要强迫 AI 遵守"团队纪律"时**
    团队协作最怕千人千面。如果你带一个十几人的研发组,你肯定不希望新人让 AI 生成的代码风格和老员工天差地别。把团队的架构规范、命名规约封装成**项目级 Skill**(放在仓库的 `.claude/skills/` 下跟随代码走),相当于让 AI 扮演一个无情的、标准统一的代码审查员 —— 且规范版本随 Git 历史可追溯。

- **🚨 场景三:上下游自动化流转(Pipeline)节点**
    如果这个 AI 任务的输出结果,不是给人看的,而是要喂给下一个脚本的(比如从网页提取数据后直接存入数据库,或者根据 PR 自动生成 Release Note 并在企微发通知)—— 面对这种对格式要求 100% 严苛的场景,正确做法是 **SKILL.md 正文里明确写死输出结构 + `scripts/` 里跑 schema 校验脚本 + `allowed-tools` 锁死权限边界**,三板斧把不确定性压到最低。

---

## 总结

理解 Skill 的结构和生命周期，是我们掌控 AI 的前提。过去我们是把需求“抛”给大模型，祈祷它返回好结果；现在，我们是通过规范输入、定义边界，将大模型的能力“压榨”进我们设计好的管道里。

但光知道原理还不够，纸上得来终觉浅。在下一篇，我们将打开编辑器，从零开始完整构建一个工业级的 Skill，并聊聊如何像写单元测试一样，去测试和打磨它。
