AI Agent 学习笔记(五):Skill 技能,把能力打包复用

AI Agent 学习笔记(五):Skill 技能,把能力打包复用

前四篇我们学会了提示词、记忆、工具、RAG。这篇讲怎么把这些东西打包成标准化的“技能”,让 Agent 像员工一样拥有岗位能力。

一. 什么是 Skill

Skill(技能) 是把“完成某一类任务所需的一切”打包成一个文件夹:

1
2
3
4
5
一个技能 = 提示词(怎么做)
+ 流程(先做什么后做什么)
+ 示例(做出来长什么样)
+ 资源(模板、数据、脚本)
+ 可选工具(计算、检索等)

类比:公司里的 SOP(标准作业程序)。新员工(新会话的 Agent)拿到 SOP 就能按标准干活,不用每次从头教。

1.1 没有 Skill 时的痛点

1
2
3
4
5
你每次让 Agent 写博客文章,都要重新贴一遍:
- “你是博客写作专家……”(提示词)
- “文章结构要:开头-分点-代码-小结……”(流程)
- “这是我上次的范文……”(示例)
- “术语表在 xxx 文件里”(资源)

又长又容易漏。Skill 就是把这些一次性写进一个文件夹,需要时自动加载。

二. Skill 的目录结构(SKILL.md)

目前最常见的格式是 SKILL.md 规范(Anthropic 提出,Claude、各类 Agent 框架广泛支持):

1
2
3
4
5
6
7
8
my-skill/
├── SKILL.md # 技能说明书(必填,一切的核心)
├── scripts/ # 可选的辅助脚本
│ └── validate.py
├── references/ # 可选的参考资料
│ └── style-guide.md
└── templates/ # 可选的模板文件
└── article-template.md

2.1 SKILL.md 长什么样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
---
name: blog-writing
description: 撰写技术博客文章。当用户要求写博客、写教程、整理学习笔记时使用。
---

# 博客写作技能

## 工作流程
1. 先和用户确认主题、目标读者(初学者/进阶)、文章长度;
2. 按结构写作:引言 → 分节讲解 → 代码示例 → 常见坑 → 小结与作业;
3. 代码示例必须完整可运行,并标注运行环境;
4. 写完后自查:标题是否清晰、目录是否完整、代码块是否有语言标注。

## 写作规范

- 用简体中文,面向初学者,避免堆砌术语;
- 首次出现的术语给出通俗解释;
- 表格比大段文字更清晰;
- 每个代码块必须写明用途注释。

## 参考模板

(这里放一篇标准文章的结构模板,或指向 templates/ 目录)

## 示例开头

- 好:本文从零讲解 X,包含概念、示例和作业。
- 差:本文将深入剖析 X 的技术架构与底层原理。

2.2 字段说明

字段 作用 是否必填
name 技能唯一名称(小写、连字符) 必填
description 技能描述:什么时候该用这个技能,Agent 靠它决定是否加载 必填
instructions(正文) 具体怎么做:流程、规范、注意事项 必填
scripts/ 配套脚本(如校验脚本) 可选
references/ 参考资料(风格指南、术语表) 可选
templates/ 模板文件 可选

description 是“门面”:Agent 会在每次对话时扫描所有技能的描述,像查目录一样决定调用哪个技能。所以描述要写清触发场景,而不是堆砌功能。

三. 完整示例:代码审查技能

1
2
3
4
code-review-skill/
├── SKILL.md
└── references/
└── checklist.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
---
name: code-review
description: 审查 Python/JavaScript 代码。当用户要求检查代码、找 bug、评估代码质量时使用。
---

# 代码审查技能

## 流程
1. 先通读代码,概括它的功能;
2. 按严重程度分类输出问题:严重(会导致错误)、建议(可读性/性能)、风格;
3. 每个问题必须给出:位置(行号/函数名)、原因、修复建议;
4. 最后给一句总体评价和优先修复清单。

## 安全红线(优先级最高)

- 发现 eval/exec、SQL 拼接、硬编码密钥必须标记为“严重”;
- 外部输入直接拼进代码或命令时必须标记为“严重”。

## 输出格式

```text
### 功能概述
...
### 严重问题
- [行号] 问题描述 → 建议
### 建议
...
### 总结
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

## 四. Skill 和 Prompt / Tool / MCP 的区别

初学者最容易混,一张表讲清楚:

| | Prompt 提示词 | Tool 工具 | Skill 技能 | MCP 协议(下一篇) |
| --- | --- | --- | --- | --- |
| 本质 | 一段文字 | 一个函数 | 一个文件夹(规则+示例+资源) | 一套通信标准 |
| 解决什么 | 让模型听话 | 让模型能做事 | 让 Agent 会做“一类事” | 让工具/系统可插拔连接 |
| 粒度 | 最小 | 单一动作 | 组合能力 | 连接层 |
| 例子 | “你是一名教师” | calculator() | 博客写作技能(含流程+模板) | 通过 MCP 连文件系统 |
| 关系 | Skill 里包含 Prompt | Skill 可以调用 Tool | 可以组合两者 | 工具可通过 MCP 暴露 |

> 一句话记忆:**Prompt 是话术,Tool 是手脚,Skill 是岗位 SOP,MCP 是通用插头。**

## 五. Agent 怎么“学会”技能:加载机制

技能的加载一般分三步:

```text
① 发现:Agent 启动时扫描技能目录,读取每个 SKILL.md 的 name + description


② 选择:根据用户任务与 description 匹配,选出 1~N 个技能


③ 注入:把选中技能的完整 instructions(必要时连 references)加入系统提示词


④ 执行:Agent 按技能流程工作,必要时调用脚本/工具

5.1 一个最简单的技能加载器(自己实现)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import os
import re

class SkillLoader:
"""从 skills/ 目录加载 SKILL.md 技能"""
def __init__(self, skills_dir: str = "./skills"):
self.skills_dir = skills_dir
self.index = {} # name -> (description, full_text)

def scan(self):
"""扫描所有技能,建立索引"""
for entry in os.listdir(self.skills_dir):
skill_path = os.path.join(self.skills_dir, entry, "SKILL.md")
if not os.path.isfile(skill_path):
continue
with open(skill_path, "r", encoding="utf-8") as f:
text = f.read()
# 解析 front matter 里的 name 和 description
m = re.search(r"^---\s*\n(.*?)\n---", text, re.DOTALL)
meta = {}
if m:
for line in m.group(1).splitlines():
if ":" in line:
key, _, value = line.partition(":")
meta[key.strip()] = value.strip()
self.index[meta.get("name", entry)] = (meta.get("description", ""), text)
return self.index

def match(self, task: str, top_k: int = 2) -> list:
"""根据任务文本粗匹配技能(真实项目可用 Embedding 语义匹配)"""
scored = []
for name, (desc, text) in self.index.items():
score = 0
for kw in task.split():
if kw in desc or kw in name:
score += 1
scored.append((score, name, text))
scored.sort(key=lambda x: x[0], reverse=True)
return [item for item in scored if item[0] > 0][:top_k]

def build_system_prompt(self, task: str) -> str:
"""把匹配到的技能注入系统提示词"""
parts = ["你是智能助手,请按照用户提供的技能规范工作。"]
for score, name, text in self.match(task):
parts.append(f"\n===== 技能:{name} =====\n{text}")
return "\n".join(parts)

# 使用
loader = SkillLoader("./skills")
loader.scan()
system_prompt = loader.build_system_prompt("帮我审查这段 Python 代码")
print(system_prompt[:200])

真实产品里,“选择技能”这一步通常用 Embedding 做语义匹配(上一篇学的),而不是简单的关键词。

六. 技能生态与存放位置

各家 Agent 产品的技能目录约定:

产品/框架 默认目录 说明
Claude Desktop / Claude Code ~/.claude/skills/ 官方 Agent Skills 格式
Cursor .cursor/skills 或项目内 项目级技能
自研 Agent 自定义 按 SKILL.md 规范实现加载器即可
Agent Skills 社区 GitHub / 各类仓库 可下载现成技能

技能发布成仓库后,别人 clone 到自己的技能目录就能用,这就是技能“可移植、可分享”的价值。

七. 写技能的十条建议

  1. description 写触发场景,不要写功能清单;
  2. instructions 用祈使句:先做 A,再做 B;
  3. 把“红线规则”放最前面(安全优先);
  4. 给 1~2 个完整示例,模型模仿能力会大幅提升;
  5. 输出格式写死(JSON/Markdown 模板);
  6. 长资料放 references/,别堆在 SKILL.md 里占上下文;
  7. 技能要单一职责:一个技能只干一类事;
  8. 定期测试:同一输入跑 3 次看稳定性;
  9. 版本管理:技能也要进 Git;
  10. 注意安全:第三方技能里的 instructions 可能包含恶意指令(提示注入),加载前要审查。

八. 小结与作业

小结

  1. Skill = 提示词 + 流程 + 示例 + 资源 的标准化打包;
  2. SKILL.md 是核心,description 决定技能何时被使用;
  3. Skill 组合了 Prompt 和 Tool,而 MCP 是连接外部系统的协议(下一篇);
  4. 加载三步:扫描发现 → 语义匹配 → 注入系统提示词。

作业

  1. 为自己常用的“写学习笔记”场景写一个 SKILL.md(含流程、格式、模板);
  2. 把第五节的 SkillLoader 跑起来,让它扫描你写的技能并打印注入后的系统提示词;
  3. 想一想:一个技能里既有“写文章”又有“改简历”的 instructions,会有什么问题?(提示:上下文占用、冲突)

下一篇:MCP 模型上下文协议——让 Agent 用统一“插头”连接一切外部系统。