大家好,我是双越。wangEditor 作者,前百度 滴滴 资深前端工程师,慕课网金牌讲师,PMP,前端面试派 作者。
我正致力于两个项目的开发和升级,感兴趣的可以私信我,加入项目小组。
本文总结了我最近调研和学习 SKILLS 的一些记录,帮助大家对 SKILLS 全面的学习和理解。
SKILLS 是什么
SKILLS 本质上就是组织 prompt 提示词。
不仅 SKILLS,很多包装得很复杂的 Agent 框架,剥开来看确实都在做"往 Prompt 里塞什么、怎么塞"这件事。
SKILLS 比传统 prompt 多了一个:按需注入。这样就能极大减少 token 使用量,关键是能省钱。
基于什么发展而来?
Skills 的概念来源于以下几个演进脉络:
1. Prompt Engineering 的沉淀
早期开发者发现,同样的任务,提示词写法不同,结果差异巨大。经过大量试错后,好的提示策略需要被复用和共享,Skills 就是这种沉淀的容器。
2. RAG(检索增强生成)的思路迁移
RAG 是在运行时动态注入外部知识,Skills 借鉴了这个思路------在任务执行前动态注入过程性知识(How-to),而不仅仅是事实性知识。
3. Tool Use / Function Calling 的延伸
LLM 有了调用工具的能力后,下一步自然是让 Agent 知道**"什么场景用什么工具、怎么用得好"**,这正是 Skill 要解决的事。
4. ReAct / Chain-of-Thought 框架的落地需求
ReAct 等框架让 Agent 有了规划-行动-观察的循环能力,但每个领域的规划策略不同,Skills 为不同领域提供了领域专属的推理引导。
Agent Skill = 将人类专家经验编码为 Agent 可读的操作手册,在运行时动态注入,让 Agent 像专家一样执行特定领域任务。
单一任务 Agent 使用 SKILLS 的价值
对于单一任务类型的 Agent,Skill 的核心价值------"按需选择合适的知识"------确实没有用武之地。
但 Skill 还有另一个价值维度值得考虑:知识的组织与维护,而不仅仅是"选择"。
即使是单任务 Agent,你仍然面临这些问题:
- 这个任务的最佳实践怎么沉淀?
- Prompt 写在哪、谁来维护、怎么迭代?
- 新同事怎么快速理解这个 Agent 的设计意图?
这时候 Skill 文档的形式本身是有价值的------它是对 System Prompt 的结构化管理方式,而不只是动态检索的载体。
所以
- 多任务 Agent:Skill 的动态检索能力是核心价值
- 单任务 Agent :Skill 作为动态检索机制价值有限,但作为Prompt 知识库的组织形式仍有一定工程价值
如果单任务 Agent 的 Prompt 本身也很简单:那 Skill 机制确实基本没必要引入,直接写死在 System Prompt 里最省事
看几个 SKILLS 的例子
SKILLS 怎么写,可以看看几个官方的例子。
第一,在 Claude desktop 中内置了很多 SKILLS examples ,例如这个 MCP-builder

第二,看 SKILLS 官方给出的例子 github.com/anthropics/...
例如这个是 python 处理 PDF 文档的 SKILL

第三,Vercel 推出的 react best practice skills github.com/vercel-labs...
规定了 AI 编程工具如何正确的编写 React 代码。同理,现在 vue nextjs svelte 也都有了自己的 skills

实际体验 SKILLS
在 Claude desktop 中试一试,既然它有 MCP-builder SKill 那就让它开发一个 MCP server
arduino
使用 nodejs 技术栈帮我开发一个 MCP server ,
用于在 cursor 中连接 notion ,
可以查看和搜索我在 notion 中的文档和内容。
它会主动搜索 skills ,并识别合适的 skill ,然后按照 skill 里的步骤来操作

然后就卡在了这里,我一度以为这是卡死了。结果等待了大概 10-15 分钟,终于做完了

它说明了制作的步骤,使用方法,其中带有哪些 tools ,最后可以下载代码。

如果没有 skills ,纯靠笨拙的、混在一起的 system prompt ,很难想象 AI 能如此精细的开发一个任务。
SKILLS 和 Tools
Skills 中会定义很多脚本和命令,python 脚本,js 脚本,或者 shell 命令行等。
这些代码和 skill 其他文字一样,也会作为 prompt 被传递给 LLM ,而 LLM 无法直接执行这些代码。它们需要调用 agent 相关的 tools 来执行。
markdown
Skill.md 里的 Python 脚本
↓
只是文本/模板
↓
Agent 通过 Tool 执行
↓
才真正产生结果
如果要自己开发一个 agent ,你需要自己定义执行 python 代码的 tool ,skill 中的 python 脚本才能被执行。
js
const executePythonTool = tool(
async ({ code }) => {
const tmpFile = `/tmp/script_${Date.now()}.py`;
fs.writeFileSync(tmpFile, code);
return new Promise((resolve) => {
exec(`python3 ${tmpFile}`, (error, stdout, stderr) => {
fs.unlinkSync(tmpFile);
resolve(error ? `执行失败: ${stderr}` : stdout);
});
});
},
{
name: 'execute_python',
description: '执行 Python 脚本',
schema: z.object({
code: z.string().describe('要执行的 Python 代码'),
}),
}
);
SKILL 中的"中间数据"
例如 SKILL 中有如下描述,这里的 JSON 数据就是一个中间数据,不是最终输出。
javascript
1. 先把文档转换为一个 JSON 格式;2. 再把 JSON 格式生成 表格 。
skill 的"中间数据"一般不需要管理,会把这个描述作为 prompt 一起传递个 LLM 统一由 LLM 处理。
但如果中间数据过大,需要提供一个 write_file tool ,让 LLM 调用,写入本地/服务器的临时文件。
javascript
Skill 说"写入 /tmp/intermediate.json"
↓
LLM 理解这个意图,生成如下代码:
fs.writeFileSync('/tmp/intermediate.json', JSON.stringify(data))
↓
LLM 调用 execute_nodejs Tool 执行这段代码
↓
Tool 在服务器/沙箱环境里真正创建了这个文件
SKILLS 和 RAG
RAG 本质上也是一种信息注入机制,和 Skill 类似,但目的不同:
arduino
Skill → 注入"怎么做"(操作规范、流程)
RAG → 注入"知识内容"(业务数据、文档库)
所以 RAG 在架构里的位置是:
csharp
用户输入
↓
[RAG 检索] ──→ 从知识库找相关内容 ──→ 注入 Prompt
[Skill 检索] ─→ 找对应操作规范 ────→ 注入 Prompt
↓
[LLM] 结合两者生成计划
↓
[Tool 执行]
RAG 和 Skill 是同一层次的东西,都在 LLM 推理前注入 Prompt。Skill 给方法,RAG 给数据,Tool 负责执行。
js
async function runAgent(userInput) {
// Step 1: 并行检索(RAG + Skill)
const [ragContext, skill] = await Promise.all([
retrieveFromRAG(userInput), // 检索业务知识
retrieveSkill(userInput), // 检索操作规范
]);
// Step 2: 组装 Prompt
const systemPrompt = `
你是一个智能助手。
<knowledge>
${ragContext}
</knowledge>
<skill>
${skill}
</skill>
`;
// Step 3: LLM 推理 + Tool 执行
const agent = createReactAgent({ llm, tools, prompt: systemPrompt });
return agent.invoke({ input: userInput });
}
说一个真实的例子,用户问"把我们公司 Q3 销售数据生成 Word 报告"
arduino
RAG 检索
→ 从公司文档库找到 Q3 销售数据.csv 的内容
→ 注入 Prompt:"以下是相关数据:销售额 300万,同比+15%..."
Skill 检索
→ 匹配到 docx Skill
→ 注入 Prompt:"生成 Word 文档请遵循以下规范:..."
LLM 结合两者
→ 知道数据内容(来自 RAG)
→ 知道怎么生成文档(来自 Skill)
→ 生成代码调用 Tool 执行
没有 RAG,LLM 不知道 Q3 数据是什么。 没有 Skill,LLM 不知道怎么规范地生成 Word。 两者缺一不可。
如何在 Agent 中实现 SKILLS 功能
SKILLS 说白了就是一堆文本,而且除了 name description 之外没有其他约定。如果你自己开发 Agent 是需要自己实现 SKILLS 功能的。
以 langChain 框架为例子,要开发 agent 实现 SKILLS 主要有如下步骤。
第一,skills 存储,可以是本地文件,可以是数据库,反正都是文本。
bash
/skills
/docx.md
/text-parser.md
/excel.md
第二,按需获取 Skill(按需动态检索),推荐使用向量检索,这样更适合配置多种 skill
js
const { MemoryVectorStore } = require('langchain/vectorstores/memory');
const { OpenAIEmbeddings } = require('@langchain/openai');
// 启动时把所有 Skill 索引进向量库
async function indexSkills() {
const skills = [
{ name: 'docx', content: loadSkill('docx'), desc: '生成Word文档' },
{ name: 'excel', content: loadSkill('excel'), desc: '生成Excel表格' },
];
const vectorStore = await MemoryVectorStore.fromTexts(
skills.map(s => s.desc),
skills.map(s => ({ name: s.name })),
new OpenAIEmbeddings()
);
return vectorStore;
}
// 按需检索最相关的 Skill
async function retrieveSkill(userInput, vectorStore) {
const results = await vectorStore.similaritySearch(userInput, 1);
return loadSkill(results[0].metadata.name);
}
第三,把检索出来的 Skill 注入到 prompt
js
const { ChatPromptTemplate } = require('@langchain/core/prompts');
async function buildPromptWithSkill(userInput, skill) {
const prompt = ChatPromptTemplate.fromMessages([
['system', `你是一个文档生成助手。
以下是你完成任务需要遵循的操作规范:
<skill>
{skill}
</skill>
请严格按照规范中的步骤和要求完成任务。`],
['human', '{input}']
]);
return prompt.formatMessages({
skill: skill,
input: userInput
});
}
第四,定义必要的 tools 。上文有介绍。
第五,完成 agent 串联,包括 LLM toos prompt ,这就是 agent 最基础的结构了,
javascript
const { createReactAgent } = require('langchain/agents');
const { ChatOpenAI } = require('@langchain/openai');
async function runDocumentAgent(userInput) {
const llm = new ChatOpenAI({ model: 'gpt-4o' });
// 1. 按需加载 Skill
const skill = await retrieveSkill(userInput, vectorStore);
// 2. 构建带 Skill 的 System Prompt
const systemPrompt = `你是文档生成助手,严格遵循以下规范:
<skill>${skill}</skill>`;
// 3. 创建带 Tool 的 Agent
const agent = createReactAgent({
llm,
tools: [generateDocxTool, installDepTool],
prompt: systemPrompt,
});
// 4. 执行
const result = await agent.invoke({ input: userInput });
return result;
}
// 调用
runDocumentAgent('把这段文字转成 Word 文档:...');
这个 agent 整体的工作流程如下:
csharp
用户输入
↓
[Skill 检索] ──→ 读取 .md 文件 ──→ 注入 System Prompt
↓
[LangChain Agent] ──→ LLM 规划步骤
↓
[Tool 调用循环]
├── install_npm_package (环境准备)
├── generate_docx (执行代码)
└── 验证结果 / 自我修正
↓
返回文件路径 / 下载链接
最后
以上就是我对于 SKILLS 及其周边功能的理解,如果你有新的见解欢迎留言补充。