系列文章导航:AI系列文章导航目录-持续更新中
第16课:全面学习Agent Skill系统
📝 本文摘要:本文从零讲解Agent Skill系统------Agent能力的"插件化"组织方式。内容包括:①Skill是什么(定义、与Tool/MCP的本质区别);②为什么需要Skill(单纯工具列表的四大问题、Skill如何解决);③Skill在Agent技术栈中的定位(三层架构图解);④Skill的核心结构(五大组成要素详解与案例);⑤Skill的生命周期(自动发现→注册→发现→加载→执行→卸载完整流程);⑥Skill的动态加载与编排(按需加载、冲突处理、组合模式);⑦Skill生态与标准化(OpenSpec、skills.sh、ClawHub等);⑧Skill设计的工程原则(六大原则与反模式)。适合AI小白从零理解Skill系统的本质、定位和实践。
Skill是Agent从"能调工具"到"真正有能力"的关键跃升。理解Skill,你就理解了Agent如何像人一样"学会"做一件事,而不只是"能用"一个工具。
一、Skill是什么
1.1 一句话定义
Skill = Agent可动态加载的"能力包"
类比: Skill之于Agent ≈ App之于手机 ≈ 插件之于浏览器
展开理解:
你的手机出厂时只有基础功能(打电话、发短信),但装了微信就能聊天,装了高德就能导航,装了美团就能点外卖。每个App不只是一个"按钮",而是一整套能力(界面+逻辑+数据+规则)。
Agent也一样。一个裸的Agent只有LLM的基础推理能力,但加载了"代码审查"Skill就能审查代码,加载了"故障排障"Skill就能排查故障,加载了"数据分析"Skill就能分析数据。
关键点:Skill ≠ 工具(Tool)。工具是"一把锤子",Skill是"会用锤子的木匠"------它不仅有工具,还有知识、经验、规则和方法论。
1.2 Skill vs Tool vs MCP:到底什么关系?
这是最容易混淆的概念,必须彻底讲清楚。
┌─────────────────────────────────────────────────────────────────────────┐
│ 三者的层级关系 │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ Skill(能力层) │
│ │
│ "我知道怎么做代码审查" │
│ = 工具 + 知识 + 提示词 + 规则 + 示例 │
│ = 一个完整的能力包 │
│ │
│ ┌───────────────────────────────────────────────────────────────────┐ │
│ │ MCP(连接层) │ │
│ │ │ │
│ │ "我标准化地暴露工具给所有Client用" │ │
│ │ = 工具的标准化连接协议 │ │
│ │ = 解决工具的发现、调用、复用问题 │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────────────┐ │ │
│ │ │ Tool(执行层) │ │ │
│ │ │ │ │ │
│ │ │ "我能读文件 / 我能查数据库 / 我能发邮件" │ │ │
│ │ │ = 最小粒度的单一功能 │ │ │
│ │ │ = 一个函数 │ │ │
│ │ └─────────────────────────────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
用一个具体例子说明三者的区别:
场景: Agent需要"审查代码安全性"
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
【只有Tool时】
Agent拿到的:
- read_file(path) → 读文件
- search_code(query) → 搜代码
Agent的困境:
"我有工具了,但是...
- 代码安全审查应该看哪些方面?我不知道
- SQL注入长什么样?我只有通用知识
- 审查报告应该什么格式?没人告诉我
- 我能不能直接修改代码?不确定边界"
结果: Agent可能漏掉关键安全问题,输出格式不统一,行为不可预测
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
【有MCP时】
改进: 工具的连接方式标准化了
- 不用自己写read_file的实现
- 从MCP Server动态获取工具
- 工具可以跨应用复用
但Agent的困境依然存在:
"工具连接方式标准化了,但我还是不知道怎么做安全审查..."
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
【有Skill时】
Agent拿到的是一个完整的"代码安全审查"能力包:
✅ 工具: read_file, search_code(知道用什么工具)
✅ 知识: SQL注入、XSS、CSRF的具体模式和检测方法
✅ 提示词: "请按以下5个维度审查..."(知道怎么做)
✅ 示例: 输入一段有漏洞的代码 → 期望的审查输出
✅ 约束: "只能审查,不能修改代码"(知道边界)
结果: Agent像一个经过培训的安全工程师,输出专业、一致、可控
一句话总结三者关系:
Tool = 锤子(一个工具)
MCP = 五金店的标准货架(工具的标准化管理方式)
Skill = 木匠师傅(知道用什么工具 + 怎么用 + 什么时候用 + 不能做什么)
你不会只给一个人一把锤子就说"去把房子建好"。
你需要给他完整的能力: 工具 + 图纸 + 规范 + 经验 + 安全守则。
这就是Skill做的事。
1.3 为什么需要Skill?(催生Skill的四大问题)
核心问题:只给Agent一堆工具,它真的能做好事情吗?
答案是:不能。就像只给一个实习生一堆工具但不给任何培训,他大概率会搞砸。
问题1: 工具太多,Agent不知道该用哪个
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
场景: 你的Agent连接了50个MCP Server,暴露了200个工具
问题:
- 每次请求都把200个工具定义传给LLM?→ Token爆炸,成本飙升
- LLM面对200个工具选择?→ 选择困难,容易选错
- 很多工具之间有依赖关系?→ LLM不知道先调A再调B
Skill的解决方案:
→ 按任务类型组织工具,每次只加载相关的Skill(5-10个工具)
→ Agent不需要面对200个工具,只需要面对当前任务相关的能力包
问题2: Agent缺乏领域知识,工具用不好
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
场景: Agent有query_database工具,用户说"帮我查一下最近的异常订单"
问题:
- "异常订单"的定义是什么?→ LLM只能猜
- 应该查哪张表?字段叫什么?→ LLM不知道你的数据库结构
- 查询结果怎么解读?→ LLM缺乏业务上下文
Skill的解决方案:
→ "订单分析"Skill内置了:
- 知识: 异常订单的定义(金额>10000 或 状态=refunded 且 创建<1小时)
- 知识: 数据库表结构(orders表、order_items表、字段说明)
- 提示: "查询异常订单时,请按以下SQL模板..."
问题3: Agent行为不可控,没有边界
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
场景: Agent有execute_sql工具,用户说"帮我清理一下过期数据"
问题:
- Agent可能执行 DELETE FROM orders WHERE ... → 删除了生产数据!
- Agent可能执行 DROP TABLE ... → 灾难性后果!
- 没有明确的"能做什么/不能做什么"的边界
Skill的解决方案:
→ "数据清理"Skill内置了安全约束:
- "只能执行SELECT和软删除(UPDATE status='deleted')"
- "禁止执行DROP、TRUNCATE、硬DELETE"
- "单次操作影响行数不能超过1000"
- "必须先执行COUNT确认影响范围,再执行实际操作"
问题4: Agent输出不一致,质量参差不齐
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
场景: 团队有5个Agent都需要做代码审查
问题:
- Agent A审查时关注安全性,Agent B关注性能,Agent C随机关注
- 输出格式不统一:有的用表格,有的用列表,有的写散文
- 审查标准不一致:同样的代码,不同Agent给出矛盾的结论
Skill的解决方案:
→ 统一的"代码审查"Skill:
- 统一的审查维度(安全/性能/可读性/最佳实践)
- 统一的输出格式模板
- 统一的评分标准
- 所有Agent加载同一个Skill → 行为一致
总结:Skill解决的核心问题
Tool/MCP解决的是: "Agent能不能调工具"(能力的有无)
Skill解决的是: "Agent能不能把事做好"(能力的质量)
类比:
Tool/MCP = 给你一把手术刀(你有了工具)
Skill = 给你完整的外科培训(你有了能力)
有手术刀不代表你能做手术。
有了完整的培训(知识+技能+规范+经验),你才真正有能力做手术。
二、Skill在Agent技术栈中的定位
2.1 Agent的完整技术栈
理解Skill的定位,需要看清Agent系统的完整分层:
┌─────────────────────────────────────────────────────────────────────────┐
│ Agent完整技术栈(从上到下) │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ 第1层: 用户交互层 │
│ 用户输入 → "帮我审查这段代码的安全性" │
└──────────────────────────────────┬──────────────────────────────────────┘
│
┌──────────────────────────────────▼──────────────────────────────────────┐
│ 第2层: Agent编排层(核心控制循环) │
│ │
│ ┌─────────────┐ ┌──────────────┐ ┌─────────────────────┐ │
│ │ Skill发现 │───▶│ Skill加载 │───▶│ 构建LLM请求 │ │
│ │ "这个任务需 │ │ 加载相关Skill │ │ system_prompt(Skill) │ │
│ │ 要什么能力" │ │ 的工具+知识 │ │ + tools(Skill) │ │
│ └─────────────┘ └──────────────┘ │ + messages(用户) │ │
│ └──────────┬──────────┘ │
│ │ │
│ ┌─────────────┐ ┌──────────────┐ │ │
│ │ 结果处理 │◀───│ 工具执行 │◀─────────────┘ │
│ │ 格式化输出 │ │ 调用实际工具 │ LLM返回tool_call │
│ └─────────────┘ └──────────────┘ │
└──────────────────────────────────────────────────────────────────────────┘
│ │
│ │ 实际执行工具
│ ┌───────────┴───────────────────────┐
│ │ │
┌────────▼──────────▼───┐ ┌────────────▼─────────────────┐
│ 第3层: Skill层 │ │ 第4层: 工具连接层 │
│ (能力的组织与管理) │ │ (MCP / 本地函数) │
│ │ │ │
│ ┌────────────────────┐ │ │ ┌──────────┐ ┌────────────┐ │
│ │ 代码审查 Skill │ │ │ │MCP Server│ │ 本地函数 │ │
│ │ - tools: [...] │ │ 调用工具 │ │(标准化) │ │(直接调用) │ │
│ │ - knowledge: ... │─┼─────────────────▶│ │ │ │ │ │
│ │ - prompt: ... │ │ │ └──────────┘ └────────────┘ │
│ │ - guardrails: ... │ │ │ │
│ └────────────────────┘ │ │ ↓ │
│ ┌────────────────────┐ │ │ ┌──────────────────────────┐ │
│ │ 故障排障 Skill │ │ │ │ 第5层: 实际外部服务 │ │
│ │ - tools: [...] │ │ │ │ (数据库/API/文件系统) │ │
│ │ - knowledge: ... │ │ │ └──────────────────────────┘ │
│ └────────────────────┘ │ └──────────────────────────────┘
└────────────────────────┘
2.2 Skill层的核心职责
Skill层做的事情(向上对Agent编排层负责):
1. 能力注册: 告诉Agent"我有哪些能力可用"
2. 能力发现: 根据用户任务,推荐最相关的能力
3. 能力加载: 把选中的Skill的工具+知识+提示注入Agent上下文
4. 能力约束: 限制Agent在当前Skill范围内的行为边界
5. 能力卸载: 任务完成后释放资源,避免上下文膨胀
Skill层不做的事情:
✗ 不负责工具的实际执行(那是MCP/本地函数的事)
✗ 不负责LLM的推理决策(那是LLM的事)
✗ 不负责用户交互(那是应用层的事)
2.3 Skill与MCP的协作关系
很多人会问:有了MCP,为什么还需要Skill?它们不是重复了吗?
答案:完全不重复。MCP管"连接",Skill管"组织"。它们是互补关系。
类比理解:
MCP = 图书馆的借阅系统
- 标准化地管理书籍(工具)的借出和归还
- 任何人(Client)都能用同一套流程借书
- 解决的是"怎么拿到书"的问题
Skill = 大学的课程体系
- 把相关的书籍组织成一门课(能力包)
- 告诉学生"学这门课需要读哪些书、按什么顺序、重点是什么"
- 解决的是"怎么用好这些书"的问题
实际协作流程:
1. Skill定义了"代码审查需要read_file和search_code工具"
2. Agent加载这个Skill时,通过MCP协议从对应的MCP Server获取这些工具
3. Skill提供的知识和提示词注入到LLM的上下文中
4. LLM决定调用工具时,通过MCP协议实际执行
5. Skill的约束规则在执行前/后进行校验
Skill负责"编排和约束",MCP负责"连接和执行"
三、Skill的核心结构
3.1 Skill的五大组成要素
一个完整的Skill包含以下五个部分:
┌─────────────────────────────────────────────────────────────────────────┐
│ Skill的五大组成要素 │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ ① 元数据 (Metadata) │
│ - name: Skill的唯一标识 │
│ - description: 能力描述(用于Skill发现时的匹配) │
│ - version: 版本号 │
│ - tags: 标签(用于分类和搜索) │
│ - author: 作者 │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ ② 工具集 (Tools) │
│ - 这个Skill需要用到的工具列表 │
│ - 可以是本地函数,也可以是MCP Server提供的工具 │
│ - 定义了Agent在这个Skill下"能做什么操作" │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ ③ 知识库 (Knowledge) │
│ - 使用这个Skill需要的领域知识 │
│ - 可以是文本、规则列表、数据库Schema等 │
│ - 注入到LLM上下文中,让Agent"懂行" │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ ④ 提示模板 (System Prompt) │
│ - 引导Agent正确使用这个能力的指令 │
│ - 包括: 工作流程、输出格式、注意事项 │
│ - 这是Skill的"灵魂"------决定了Agent的行为模式 │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ ⑤ 安全约束 (Guardrails) │
│ - 明确声明Agent在这个Skill下"不能做什么" │
│ - 防止Agent越界操作 │
│ - 可以是软约束(提示词中声明)或硬约束(代码层面拦截) │
└─────────────────────────────────────────────────────────────────────────┘
3.2 Skill的表现形式
上面讲了Skill的五大组成要素(元数据、工具集、知识库、提示模板、安全约束),那么在实际工程中,一个Skill到底长什么样?它是以什么形式存在的?
答案是:Skill本质上是一个文件夹 ,包含一个必需的 SKILL.md 文件和可选的捆绑资源目录。
3.2.1 Skill的标准目录结构
skill-name/
├── SKILL.md ← 必需:Skill的核心文件(元数据 + 指令正文)
└── 可选的捆绑资源/
├── scripts/ ← 可执行脚本(Python/Bash等)
├── references/ ← 参考文档(按需加载到上下文)
└── assets/ ← 输出资源(模板、图片、字体等)
关键理解 :Skill不是一段代码,不是一个API,而是一个自包含的文件包。Agent通过读取这个文件包中的内容来"获得"某项能力。
3.2.2 SKILL.md:Skill的核心文件
每个Skill必须有且只有一个 SKILL.md 文件,它由两部分组成:
① YAML Frontmatter(元数据)------ 始终在Agent上下文中,用于Skill的发现和触发:
yaml
---
name: code-security-review
description: >
审查代码中的安全漏洞,包括SQL注入、XSS、CSRF、敏感信息泄露等。
当用户要求进行代码安全审查、安全扫描、漏洞检测时触发此Skill。
---
② Markdown正文(指令)------ 只在Skill被触发后才加载到上下文:
markdown
# Code Security Review
## Workflow
1. Use list_files to understand project structure
2. Read entry files (routes, API endpoints) first
3. Check each file against known vulnerability patterns
4. Use search_code to find suspicious patterns across codebase
5. Output report in standard format
## Vulnerability Patterns
### SQL Injection
- Dangerous: f-string or % formatting in SQL queries
- Safe: parameterized queries, ORM usage
### XSS
- Dangerous: innerHTML with user input, render_template_string
- Safe: textContent, HTML escaping, CSP headers
## Output Format
| # | Severity | Type | Location | Description | Fix |
|---|----------|------|----------|-------------|-----|
## Constraints
- Read-only operations only
- Never expose full secrets in output (mask with ***)
- Only audit files within user-specified scope
注意 :description 字段是Skill的触发机制------Agent通过匹配description来决定是否加载这个Skill。因此description必须清晰描述"这个Skill做什么"和"什么时候该用它"。
3.2.3 捆绑资源:三种可选目录
scripts/ ------ 可执行脚本
存放需要确定性执行的代码,避免Agent每次重写相同逻辑。
code-security-review/
├── SKILL.md
└── scripts/
├── scan_sql_injection.py ← 自动扫描SQL注入模式
└── generate_report.py ← 生成标准格式的审查报告
什么时候用scripts/:
- 同样的代码需要反复执行(如格式转换、数据处理)
- 需要确定性结果(不能让LLM每次自由发挥)
- 复杂的多步骤操作(如PDF处理、图片编辑)
特点:脚本可以直接执行,不需要加载到上下文窗口中,因此不占用token。
references/ ------ 参考文档
存放Agent在工作过程中可能需要查阅的知识文档,按需加载。
big-query-analyst/
├── SKILL.md
└── references/
├── finance.md ← 财务相关的表结构和指标定义
├── sales.md ← 销售相关的表结构和指标定义
└── product.md ← 产品相关的表结构和指标定义
什么时候用references/:
- 领域知识量大,不适合全部塞进SKILL.md(如数据库Schema、API文档)
- 不同场景需要不同的知识子集(如用户问销售数据时只加载sales.md)
- 公司内部的规范、政策、模板等
特点:按需加载------Agent根据用户的具体问题决定读取哪个reference文件,避免一次性加载所有知识撑爆上下文。
assets/ ------ 输出资源
存放不需要被Agent"阅读理解",而是直接用于输出的文件。
frontend-webapp-builder/
├── SKILL.md
└── assets/
├── template/ ← React/HTML项目模板
│ ├── index.html
│ ├── styles.css
│ └── app.js
└── logo.png ← 品牌Logo
什么时候用assets/:
- 项目模板/脚手架(Agent基于模板创建新项目)
- 品牌资源(Logo、字体、图标)
- 文档模板(PPT模板、合同模板)
特点:Agent不需要把这些文件读入上下文来"理解"它们,而是直接复制、修改或引用。
3.2.4 渐进式披露:三级加载机制
Skill的设计遵循"渐进式披露"原则,按需逐级加载,节省上下文空间:
┌─────────────────────────────────────────────────────────────────────────┐
│ Skill的三级加载机制 │
└─────────────────────────────────────────────────────────────────────────┘
第1级: 元数据(name + description)
→ 始终在上下文中(约100词)
→ 用于Skill发现和触发判断
第2级: SKILL.md正文
→ Skill被触发后加载(建议<500行)
→ 包含核心工作流和指令
第3级: 捆绑资源(scripts/ references/ assets/)
→ Agent按需加载(无上限)
→ scripts可直接执行不占上下文
→ references按需读取特定文件
为什么这样设计? 上下文窗口是稀缺资源。如果Agent同时注册了50个Skill,不可能把所有Skill的全部内容都塞进上下文。三级加载机制确保:
- 50个Skill的元数据(~5000词)始终可见,用于匹配
- 只有被触发的1-2个Skill的正文(~2000词)被加载
- 只有真正需要的reference文件才被读取
3.2.5 完整案例:一个真实的Skill长什么样
以"代码安全审查"Skill为例,展示完整的文件结构:
code-security-review/
├── SKILL.md
├── scripts/
│ └── scan_patterns.py
└── references/
├── owasp-top10.md
└── company-security-policy.md
SKILL.md 完整内容:
markdown
---
name: code-security-review
description: >
Comprehensive code security audit covering OWASP Top 10 vulnerabilities
including SQL injection, XSS, CSRF, sensitive data exposure, and
authentication flaws. Use when the user asks to: review code security,
audit for vulnerabilities, check for security issues, scan for injection
flaws, or perform any security-related code analysis.
---
# Code Security Review
## Workflow
1. Run `scripts/scan_patterns.py` on target directory for automated detection
2. Review flagged files manually for false positives
3. Check entry points (routes, API handlers) for auth/authz issues
4. For OWASP details, see `references/owasp-top10.md`
5. For company-specific rules, see `references/company-security-policy.md`
6. Generate final report in standard format
## Quick Reference: Common Patterns
### Dangerous (flag immediately)
- String interpolation in SQL: `f"SELECT ... {user_input}"`
- innerHTML with user data
- Hardcoded secrets: `API_KEY = "sk-..."`
- Missing auth decorators on admin routes
### Safe (no flag)
- Parameterized queries
- ORM usage (SQLAlchemy, Django ORM)
- Environment variables for secrets
- Role-based access decorators
## Output Format
### Security Audit Report
**Scope**: [files reviewed]
**Risk Level**: 🔴 Critical / 🟡 Medium / 🟢 Low / ✅ Clean
| # | Severity | Type | File:Line | Description | Suggested Fix |
|---|----------|------|-----------|-------------|---------------|
## Constraints
- Read-only: never modify source files
- Mask secrets in output with ***
- Stay within user-specified directory scope
- Report only confirmed issues, not speculation
对比3.1的五大要素映射:
| 五大要素 | 在Skill文件中的体现 |
|---|---|
| ① 元数据 | YAML frontmatter(name + description) |
| ② 工具集 | Agent已有的工具(read_file, search_code等),Skill中通过指令引导使用 |
| ③ 知识库 | references/ 目录 + SKILL.md正文中的Quick Reference |
| ④ 提示模板 | SKILL.md正文(Workflow、Output Format等) |
| ⑤ 安全约束 | SKILL.md正文中的Constraints部分 |
3.3 各要素的作用机制
当Agent加载这个Skill后,实际发生了什么?
python
# Agent加载Skill后,构建给LLM的请求:
messages = [
{
"role": "system",
"content": f"""
{skill.system_prompt}
## 领域知识
{skill.knowledge}
## 安全约束(你必须遵守)
{chr(10).join(f'- {g}' for g in skill.guardrails)}
## 参考示例
输入: {skill.examples[0]['input']}
期望输出: {skill.examples[0]['output']}
"""
},
{
"role": "user",
"content": "请审查 /src/api/ 目录下的代码安全性"
}
]
tools = skill.tools # 只传这个Skill定义的工具,不是全部200个工具
response = openai.chat.completions.create(
model="gpt-4",
messages=messages,
tools=tools # LLM只看到3个工具,而不是200个
)
关键理解:Skill本质上是在"精心构造LLM的输入"------通过注入专业的system_prompt、领域knowledge、限定的tools和guardrails,让一个通用的LLM在特定任务上表现得像一个专家。
四、Skill的生命周期
4.0 谁来管理Skill的生命周期?
在进入具体流程之前,必须先搞清楚一个关键问题:Skill的生命周期由谁来管理?
答案是:由你(研发)编写的应用编排层代码来管理,而不是LLM自己。
┌─────────────────────────────────────────────────────────────────────────┐
│ Skill管理的职责分工 │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ 你的代码(应用编排层)负责: │
│ │
│ ✅ 注册: 把哪些Skill加入系统 │
│ ✅ 发现: 根据用户输入匹配到合适的Skill │
│ ✅ 加载: 把Skill的内容注入到LLM的上下文中 │
│ ✅ 卸载: 任务完成后释放上下文空间 │
│ ✅ 冲突处理: 多个Skill同时激活时的优先级管理 │
│ │
│ 简单说: 你的代码决定"什么时候给LLM什么能力" │
└─────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────┐
│ LLM负责: │
│ │
│ ✅ 执行: 在被注入Skill内容后,按照Skill的指令完成任务 │
│ ✅ 工具调用: 使用Skill中声明的工具 │
│ ✅ 遵守约束: 按照Skill的guardrails行事 │
│ │
│ 简单说: LLM只负责"用好被给予的能力" │
└─────────────────────────────────────────────────────────────────────────┘
为什么LLM不能自己管理Skill?
- LLM没有持久状态:每次请求都是独立的,它不知道系统里有哪些Skill可用
- LLM不能修改自己的输入:它不能自己决定"我要加载某个Skill"然后改变自己的system prompt
- 需要工程化保障:Skill的注册、版本管理、权限控制、冲突检测等都需要确定性的代码逻辑
类比理解:
Skill管理 之于 Agent ≈ 应用商店 之于 手机
- 应用商店(你的编排代码): 管理App的安装、更新、卸载、权限
- 手机操作系统(LLM): 运行被安装好的App
- 用户不会期望手机自己决定装什么App,而是通过应用商店来管理
在你的智能体项目中,这意味着:
你需要在LLM调用之外,编写一层"Skill编排代码",它的职责是:
python
# 伪代码: 你的应用编排层
def handle_user_request(user_message: str):
# 1. 你的代码负责发现合适的Skill(不是LLM决定的)
matched_skills = skill_registry.discover(user_message)
# 2. 你的代码负责把Skill内容注入到LLM的输入中
system_prompt = build_prompt_with_skills(matched_skills)
tools = collect_tools_from_skills(matched_skills)
# 3. LLM只负责在这个"被精心构造的环境"中执行任务
response = llm.chat(
system=system_prompt, # ← 已经包含了Skill的知识和指令
tools=tools, # ← 已经限定了Skill的工具集
message=user_message
)
# 4. 你的代码负责任务完成后的清理
unload_skills_if_done(matched_skills)
return response
理解了这个前提后,下面我们逐步看每个阶段的具体实现。
4.1 完整生命周期
┌──────────────────────────────────────────────────────────────────────────┐
│ Skill的完整生命周期 │
└──────────────────────────────────────────────────────────────────────────┘
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│自动发现 │────▶│ 注册 │────▶│ 匹配 │────▶│ 加载 │────▶│ 执行 │────▶│ 卸载 │
│ Scan │ │Register │ │ Match │ │ Load │ │Execute │ │ Unload │
└─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘
│ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼
扫描本地目录 解析SKILL.md 根据用户任务 Skill的知识/ Agent使用 任务完成后
发现所有Skill 注册到Registry 找到最匹配的 提示注入Agent Skill的能力 释放上下文
文件夹 Skill 上下文 完成任务 空间
4.2 Skill的自动发现
在4.0中我们说了"你的代码负责注册Skill",但一个自然的问题是:Skill从哪里来?你的代码怎么知道有哪些Skill可用?
这就是"自动发现"要解决的问题------Agent启动时(或运行时),自动扫描并识别所有可用的Skill,然后注册到Registry中。
常见的Skill发现方式
┌─────────────────────────────────────────────────────────────────────────┐
│ Skill的发现方式 │
└─────────────────────────────────────────────────────────────────────────┘
方式1: 本地目录扫描(最常见)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
约定一个目录存放所有Skill,Agent启动时扫描该目录:
~/.agent/skills/ ← 全局Skill目录
├── code-security-review/
│ └── SKILL.md
├── big-query-analyst/
│ ├── SKILL.md
│ └── references/
└── frontend-builder/
├── SKILL.md
└── assets/
典型实现: Cursor、Claude Code、Windsurf等IDE Agent
方式2: 项目级目录扫描
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
每个项目可以有自己的Skill目录,只在该项目中生效:
my-project/
├── .skills/ ← 项目级Skill目录
│ ├── db-migration/
│ │ └── SKILL.md
│ └── api-design/
│ └── SKILL.md
├── src/
└── package.json
适用场景: 团队共享的项目特定Skill(如特定业务的审查规则)
方式3: 配置文件声明
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
在配置文件中显式列出要加载的Skill:
# agent.yaml
skills:
- path: ./skills/code-review
- path: ~/.global-skills/security-audit
- remote: https://skills.sh/packages/data-analysis@2.1.0
适用场景: 需要精确控制加载哪些Skill、不希望自动扫描的场景
方式4: 远程市场同步
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
从Skill市场(如skills.sh、SkillHub)拉取并缓存到本地:
agent skill install code-security-review
# → 下载到 ~/.agent/skills/code-security-review/
# → 下次启动时自动被目录扫描发现
适用场景: 使用社区共享的Skill、团队统一分发Skill
方式5: 运行时热加载(文件监听)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Agent运行期间监听Skill目录的文件变化,新增/修改时自动重新加载:
# 开发者往目录里放了一个新Skill
cp -r my-new-skill/ ~/.agent/skills/
# → Agent检测到变化,自动解析并注册新Skill(无需重启)
适用场景: Skill开发调试阶段、需要动态扩展能力的长运行Agent
目录扫描的实现逻辑
以最常见的"本地目录扫描"为例,核心逻辑如下:
python
import os
import yaml
class SkillScanner:
"""Skill目录扫描器: 自动发现并解析Skill"""
def __init__(self, skill_dirs: list):
"""
Args:
skill_dirs: 要扫描的目录列表,如:
['~/.agent/skills', './project/.skills']
"""
self.skill_dirs = [os.path.expanduser(d) for d in skill_dirs]
def scan_all(self) -> list:
"""扫描所有目录,返回发现的Skill元数据列表"""
discovered = []
for base_dir in self.skill_dirs:
if not os.path.isdir(base_dir):
continue
# 遍历目录下的每个子文件夹
for entry in os.listdir(base_dir):
skill_path = os.path.join(base_dir, entry)
skill_md = os.path.join(skill_path, "SKILL.md")
# 判断是否是一个合法的Skill(必须有SKILL.md)
if os.path.isdir(skill_path) and os.path.isfile(skill_md):
metadata = self._parse_skill_md(skill_md)
if metadata:
metadata['path'] = skill_path
discovered.append(metadata)
print(f" 🔍 发现Skill: {metadata['name']} ({skill_path})")
return discovered
def _parse_skill_md(self, filepath: str) -> dict:
"""解析SKILL.md的YAML frontmatter,提取元数据"""
with open(filepath, 'r') as f:
content = f.read()
# 解析YAML frontmatter(--- 包裹的部分)
if content.startswith('---'):
end = content.find('---', 3)
if end != -1:
frontmatter = content[3:end].strip()
return yaml.safe_load(frontmatter)
return None
# 使用示例
scanner = SkillScanner([
'~/.agent/skills', # 全局Skill
'./.skills', # 项目级Skill
])
# Agent启动时自动扫描
skills = scanner.scan_all()
# 输出:
# 🔍 发现Skill: code-security-review (~/.agent/skills/code-security-review)
# 🔍 发现Skill: big-query-analyst (~/.agent/skills/big-query-analyst)
# 🔍 发现Skill: db-migration (./.skills/db-migration)
# 然后逐个注册到Registry
for skill_meta in skills:
registry.register(skill_meta)
多级目录的优先级
当全局目录和项目目录存在同名Skill时,需要定义优先级:
优先级(从高到低):
1. 项目级 ./.skills/ ← 最高优先级(项目特定覆盖)
2. 用户级 ~/.agent/skills/ ← 用户个人安装的Skill
3. 系统级 /etc/agent/skills/ ← 系统预装(如企业统一分发)
4. 远程市场缓存 ← 最低优先级
规则: 同名Skill,高优先级覆盖低优先级
这个优先级机制允许:
- 团队在项目中放置定制化Skill,覆盖通用版本
- 个人可以安装自己偏好的Skill
- 企业可以统一分发合规性相关的Skill
4.3 注册(Register)
python
class SkillRegistry:
"""Skill注册中心: 管理所有可用的Skill"""
def __init__(self):
self._skills: Dict[str, Skill] = {}
self._tag_index: Dict[str, List[str]] = {} # tag → skill names
def register(self, skill: Skill):
"""注册一个Skill到注册中心"""
self._skills[skill.name] = skill
# 建立标签索引,加速发现
for tag in skill.tags:
if tag not in self._tag_index:
self._tag_index[tag] = []
self._tag_index[tag].append(skill.name)
print(f"✅ Skill已注册: {skill.name} v{skill.version} (tags: {skill.tags})")
def unregister(self, name: str):
"""从注册中心移除一个Skill"""
if name in self._skills:
skill = self._skills.pop(name)
for tag in skill.tags:
if tag in self._tag_index:
self._tag_index[tag].remove(name)
print(f"❌ Skill已移除: {name}")
def list_all(self) -> List[str]:
"""列出所有已注册的Skill"""
return list(self._skills.keys())
def get(self, name: str) -> Optional[Skill]:
"""按名称获取Skill"""
return self._skills.get(name)
# 使用示例
registry = SkillRegistry()
registry.register(code_security_review_skill)
# 输出: ✅ Skill已注册: code_security_review v2.1.0 (tags: ['security', 'code-review', 'audit'])
4.4 发现(Discover)
Skill发现是整个系统中最关键的环节------Agent需要根据用户的任务,自动找到最相关的Skill。
python
class SkillRegistry:
# ... 前面的代码 ...
def discover(self, task_description: str, top_k: int = 3) -> List[Skill]:
"""根据任务描述,发现最相关的Skill
发现策略(从简单到复杂):
1. 关键词匹配(最简单,适合demo)
2. 标签匹配(中等复杂度)
3. 语义相似度(生产级,用embedding向量)
"""
scored_skills = []
task_lower = task_description.lower()
for name, skill in self._skills.items():
score = 0
# 策略1: 名称匹配(权重最高)
if any(word in task_lower for word in skill.name.split("_")):
score += 10
# 策略2: 描述关键词匹配
desc_words = skill.description.lower().split()
for word in desc_words:
if len(word) > 2 and word in task_lower:
score += 2
# 策略3: 标签匹配
for tag in skill.tags:
if tag.lower() in task_lower:
score += 5
if score > 0:
scored_skills.append((score, skill))
# 按分数降序排列
scored_skills.sort(key=lambda x: x[0], reverse=True)
return [skill for _, skill in scored_skills[:top_k]]
# 使用示例
results = registry.discover("帮我检查这段代码有没有SQL注入漏洞")
# → 返回 code_security_review_skill(因为匹配了"security"标签和描述中的"SQL注入")
生产级发现方案:语义搜索
python
# 生产环境中,通常用embedding向量做语义匹配
# 这样即使用户说"看看代码有没有安全隐患"(没有直接提到SQL注入),也能匹配到
from openai import OpenAI
class SemanticSkillDiscovery:
"""基于语义相似度的Skill发现"""
def __init__(self, registry: SkillRegistry):
self.client = OpenAI()
self.registry = registry
self._embeddings: Dict[str, List[float]] = {}
self._build_index()
def _build_index(self):
"""为所有Skill的描述生成embedding向量"""
for name, skill in self.registry._skills.items():
# 把Skill的名称+描述+标签组合成一段文本
text = f"{skill.name}: {skill.description}. Tags: {', '.join(skill.tags)}"
response = self.client.embeddings.create(
model="text-embedding-3-small",
input=text
)
self._embeddings[name] = response.data[0].embedding
def discover(self, task: str, top_k: int = 3) -> List[Skill]:
"""语义搜索最相关的Skill"""
# 生成任务描述的embedding
task_embedding = self.client.embeddings.create(
model="text-embedding-3-small",
input=task
).data[0].embedding
# 计算余弦相似度
scores = []
for name, emb in self._embeddings.items():
similarity = self._cosine_similarity(task_embedding, emb)
scores.append((similarity, name))
scores.sort(reverse=True)
return [self.registry.get(name) for _, name in scores[:top_k]]
@staticmethod
def _cosine_similarity(a, b):
import numpy as np
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
4.5 加载(Load)
python
class SkillAwareAgent:
"""能动态加载Skill的Agent"""
def __init__(self, registry: SkillRegistry):
self.registry = registry
self.active_skills: List[Skill] = [] # 当前激活的Skill
self.base_system_prompt = "你是一个智能助手。"
def load_skill(self, skill: Skill):
"""加载一个Skill到Agent的活跃上下文中"""
if skill not in self.active_skills:
self.active_skills.append(skill)
print(f" 📦 加载Skill: {skill.name} (工具数: {len(skill.tools)})")
def get_combined_system_prompt(self) -> str:
"""组合基础提示 + 所有活跃Skill的提示/知识/约束"""
parts = [self.base_system_prompt]
for skill in self.active_skills:
parts.append(f"\n{'='*60}")
parts.append(f"## 当前能力: {skill.name}")
parts.append(f"{'='*60}")
parts.append(skill.system_prompt)
if skill.knowledge:
parts.append(f"\n### 领域知识\n{skill.knowledge}")
if skill.guardrails:
parts.append(f"\n### ⚠️ 安全约束(必须遵守)")
for g in skill.guardrails:
parts.append(f"- {g}")
if skill.examples:
parts.append(f"\n### 参考示例")
for ex in skill.examples:
parts.append(f"输入: {ex['input'][:100]}...")
parts.append(f"输出: {ex['output'][:200]}...")
return "\n".join(parts)
def get_active_tools(self) -> List[dict]:
"""获取所有活跃Skill的工具(去重)"""
tools = []
seen_names = set()
for skill in self.active_skills:
for tool in skill.tools:
name = tool["function"]["name"]
if name not in seen_names:
tools.append(tool)
seen_names.add(name)
return tools
4.6 执行(Execute)
python
class SkillAwareAgent:
# ... 前面的代码 ...
def chat(self, user_message: str) -> str:
"""完整的对话流程: 发现→加载→执行"""
# Step 1: 自动发现相关Skill
relevant_skills = self.registry.discover(user_message, top_k=2)
# Step 2: 加载发现的Skill
for skill in relevant_skills:
self.load_skill(skill)
# Step 3: 构建LLM请求
messages = [
{"role": "system", "content": self.get_combined_system_prompt()},
{"role": "user", "content": user_message}
]
tools = self.get_active_tools()
print(f"\n 🤖 发送给LLM:")
print(f" System Prompt长度: {len(self.get_combined_system_prompt())}字")
print(f" 可用工具数: {len(tools)}")
# Step 4: 调用LLM(这里是伪代码,实际需要处理tool_call循环)
# response = openai.chat.completions.create(
# model="gpt-4",
# messages=messages,
# tools=tools
# )
# ... 处理tool_call,执行工具,循环直到LLM给出最终回复 ...
return "..."
def unload_all(self):
"""卸载所有Skill(任务完成后调用)"""
self.active_skills.clear()
print(" 🧹 所有Skill已卸载")
4.7 卸载(Unload)
为什么需要卸载?
1. 上下文窗口有限:
每个Skill的知识+提示可能占用2000-5000 token
如果不卸载,累积10个Skill就占了20000-50000 token
LLM的上下文窗口会被撑爆
2. 避免能力冲突:
"代码审查"Skill说"不能修改代码"
"代码修复"Skill说"请修改代码"
两个同时激活会让Agent精神分裂
3. 保持专注:
当前任务是"审查代码",不需要"故障排障"的知识
无关信息会干扰LLM的判断
卸载时机:
- 用户明确切换了任务
- 当前任务完成
- 上下文接近窗口上限时,卸载最不相关的Skill
五、Skill的动态加载与编排
5.1 按需加载模式
python
class SmartSkillLoader:
"""智能Skill加载器: 根据对话动态加载/卸载Skill"""
def __init__(self, registry: SkillRegistry, max_active: int = 3):
self.registry = registry
self.max_active = max_active # 最多同时激活的Skill数
self.active_skills: List[Skill] = []
self.usage_history: Dict[str, int] = {} # 使用频率统计
def on_new_message(self, message: str) -> List[Skill]:
"""每次收到新消息时,重新评估需要哪些Skill"""
# 发现与当前消息相关的Skill
needed = self.registry.discover(message, top_k=self.max_active)
# 计算需要加载和卸载的Skill
needed_names = {s.name for s in needed}
active_names = {s.name for s in self.active_skills}
to_load = needed_names - active_names
to_unload = active_names - needed_names
# 执行卸载
for name in to_unload:
self.active_skills = [s for s in self.active_skills if s.name != name]
print(f" 📤 卸载Skill: {name}")
# 执行加载
for skill in needed:
if skill.name in to_load:
self.active_skills.append(skill)
self.usage_history[skill.name] = self.usage_history.get(skill.name, 0) + 1
print(f" 📥 加载Skill: {skill.name}")
return self.active_skills
5.2 Skill冲突处理
python
class SkillConflictResolver:
"""处理Skill之间的冲突"""
# 预定义的冲突规则
CONFLICTS = {
("code_review", "code_fix"): "code_review说不能改代码,code_fix说要改代码",
("read_only_audit", "data_cleanup"): "审计要求只读,清理要求写入",
}
@classmethod
def check_conflicts(cls, skills: List[Skill]) -> List[str]:
"""检查一组Skill之间是否有冲突"""
warnings = []
names = [s.name for s in skills]
for (a, b), reason in cls.CONFLICTS.items():
if a in names and b in names:
warnings.append(f"⚠️ 冲突: {a} 与 {b} 不能同时激活 ({reason})")
return warnings
@classmethod
def resolve(cls, skills: List[Skill], task: str) -> List[Skill]:
"""解决冲突: 保留与当前任务更相关的Skill"""
conflicts = cls.check_conflicts(skills)
if not conflicts:
return skills
# 简单策略: 保留排名靠前的(即与任务更相关的)
# 生产环境可以用更复杂的策略
print(f" ⚠️ 检测到Skill冲突,自动解决:")
for c in conflicts:
print(f" {c}")
# 去掉冲突中排名靠后的
return skills[:len(skills)-len(conflicts)]
5.3 Skill组合模式
有些复杂任务需要多个Skill协作完成:
场景: "帮我审查代码,修复发现的安全问题,然后写一份报告"
这个任务需要3个Skill按顺序协作:
Step 1: code_security_review Skill(审查代码)
→ 输出: 安全审查报告(发现了哪些问题)
Step 2: code_fix Skill(修复代码)
→ 输入: 上一步发现的问题
→ 输出: 修复后的代码
Step 3: report_generation Skill(生成报告)
→ 输入: 审查结果 + 修复内容
→ 输出: 完整的安全审查修复报告
这就是Skill的"管道组合"模式:
Skill_A的输出 → Skill_B的输入 → Skill_C的输入 → 最终输出
python
class SkillPipeline:
"""Skill管道: 多个Skill按顺序协作"""
def __init__(self, skills: List[Skill]):
self.skills = skills
def describe(self) -> str:
"""描述这个管道的执行流程"""
steps = []
for i, skill in enumerate(self.skills, 1):
steps.append(f" Step {i}: {skill.name} - {skill.description}")
return "\n".join(steps)
# 定义一个"安全审查修复"管道
security_fix_pipeline = SkillPipeline([
code_security_review_skill, # 先审查
# code_fix_skill, # 再修复(假设已定义)
# report_generation_skill, # 最后生成报告
])
print(security_fix_pipeline.describe())
# Step 1: code_security_review - 审查代码中的安全漏洞...
# Step 2: code_fix - 根据审查结果修复代码...
# Step 3: report_generation - 生成完整的审查修复报告...
六、Skill生态与标准化
6.1 为什么Skill需要标准化
当前的问题(2024-2025):
每个Agent框架都有自己的Skill格式:
- Cursor: 用 .cursorrules 文件定义能力
- Claude: 用 system prompt + tools 组合
- AutoGPT: 用 Python类 定义能力
- LangChain: 用 Agent + Tools + Memory 组合
结果:
- 你为Cursor写的Skill,不能在Claude里用
- 你为LangChain写的Agent能力,不能在AutoGPT里用
- 大量重复开发
这和MCP出现前的情况一模一样!
MCP之前: 每个AI应用自己写工具连接代码 → MCP统一了
现在: 每个Agent框架自己定义Skill格式 → 需要一个"Skill的MCP"
正在发展的标准化方向:
1. skills.sh: 90,000+ 技能库,统一的Skill描述和分发格式
2. ClawHub: 40,000+ 技能市场,支持Skill的搜索和安装
3. OpenSpec: 开放的Agent能力描述规范
4. A2A (Google): Agent-to-Agent协议,让Agent之间共享能力
6.2 Skill的标准描述格式
目前社区正在收敛的Skill描述格式(以YAML为例):
yaml
# skill.yaml - 一个标准的Skill描述文件
# 元数据
name: code-security-review
version: 2.1.0
description: "审查代码中的安全漏洞,包括SQL注入、XSS、CSRF、敏感信息泄露"
author: security-team
license: MIT
tags:
- security
- code-review
- audit
# 能力声明
capabilities:
- sql_injection_detection
- xss_detection
- sensitive_data_detection
- permission_check
# 输入输出
inputs:
code_path:
type: string
required: true
description: "需要审查的代码目录路径"
language:
type: string
required: false
description: "编程语言(自动检测如果不指定)"
outputs:
report:
type: object
description: "安全审查报告"
properties:
risk_level: { type: string, enum: [high, medium, low, none] }
issues: { type: array }
summary: { type: string }
# 依赖的工具
tools_required:
- read_file
- search_code
- list_files
# 约束
constraints:
- read_only: true
- network_access: false
- max_files: 100
# 兼容性
compatible_with:
- cursor: ">=0.40"
- claude-desktop: ">=1.0"
- langchain: ">=0.2"
6.3 Skill市场与共享
当前主流的Skill/Prompt市场一览(截至2026年6月3日,数据来自各平台实时查询):
| 平台 | 地址 | 规模 | 特点 |
|---|---|---|---|
| skills.sh | https://skills.sh | 9,605 Skills,总安装量 651,691+ | The Agent Skills Directory,支持一键安装到Cursor/Claude Code/Windsurf等IDE,有官方认证标识 |
| Glama | https://glama.ai/mcp/servers | 30,517 MCP Servers | 最大的开源MCP Server注册表,提供质量评分(A/B/C级)、分类浏览、兼容性标注 |
| mcp.so | https://mcp.so | 自称最大MCP集合 | MCP Server聚合搜索平台,包含Awesome MCP Servers和Claude MCP集成 |
| Smithery | https://smithery.ai | 2,621 MCP Servers | MCP Server市场,支持一键部署和远程托管,提供详情页和安装指引 |
| SkillHub | https://www.skillhub.club | 7,000+ Skills | 通用Agent Skills市场,支持Claude Code/Codex CLI/Gemini CLI/OpenCode,提供Playground即时试用、5维度AI质量评估 |
| ClawHub | https://clawhub.ai | 快速Skill注册表 | 面向Agent的Skill注册中心,支持向量语义搜索,快速发现和安装 |
| Cursor Directory | https://cursor.directory | 社区驱动 | 专注Cursor Rules/Skills的社区分享平台,按语言/框架分类 |
| OpenTools | https://opentools.ai | 2,500+ AI Tools | AI工具+MCP Server综合目录,含对比和评测 |
| GitHub Topics | https://github.com/topics/agent-skills | 5,982 repos(agent-skills) 17,067 repos(mcp-server) | 通过GitHub Topics发现开源Skill和MCP Server |
💡 实际使用建议:
- 找Agent Skill:优先去 skills.sh(专注Skill,有安装量排行和官方认证)
- 找MCP Server:优先去 Glama(30,000+,最全且有质量评分),其次 Smithery(支持远程托管)
- 语义搜索:ClawHub 支持向量搜索,适合用自然语言描述需求来发现Skill
- 开源探索:GitHub Topics 是最原始的开源社区,适合深度研究和贡献
Skill的分发方式(类比App Store):
┌─────────────────────────────────────────────────────────────────────────┐
│ Skill生态系统 │
└─────────────────────────────────────────────────────────────────────────┘
┌──────────────────┐ ┌──────────────────┐
│ Skill开发者 │ │ Skill市场 │
│ │ 发布 │ │
│ 写Skill │────────▶│ skills.sh │
│ 测试Skill │ │ ClawHub │
│ 版本管理 │ │ GitHub │
└──────────────────┘ └────────┬─────────┘
│ 搜索/安装
▼
┌──────────────────┐
│ Agent应用 │
│ │
│ 安装Skill │
│ 加载Skill │
│ 使用Skill │
└──────────────────┘
实际的Skill安装流程(以Cursor为例):
1. 搜索: 在skills.sh搜索"code review"
2. 选择: 找到评分最高的code-security-review skill
3. 安装: 一键安装到你的Cursor工作区
4. 使用: Agent自动发现并使用这个Skill
类比:
写App → 发布到App Store → 用户搜索安装 → 手机获得新能力
写Skill → 发布到Skill市场 → Agent搜索安装 → Agent获得新能力
七、Skill设计的工程原则
7.1 六大设计原则
原则1: 单一能力(Single Responsibility)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ 好的Skill: "代码安全审查" --- 只做安全审查这一件事
❌ 坏的Skill: "开发助手" --- 又能审查、又能写代码、又能部署
为什么?
- 单一能力的Skill更容易被精确发现(用户说"审查安全"就能匹配)
- 单一能力的Skill更容易维护和测试
- 单一能力的Skill可以灵活组合(管道模式)
粒度参考:
太粗: "全栈开发" → 拆成 "前端开发" + "后端开发" + "数据库设计"
太细: "检测SQL注入" → 合并到 "代码安全审查"
刚好: "代码安全审查" / "性能优化建议" / "API设计审查"
原则2: 自包含(Self-Contained)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ 好的Skill: 加载后就能独立工作,不依赖其他Skill
❌ 坏的Skill: 必须先加载Skill A才能用Skill B
为什么?
- 减少加载复杂度
- 避免循环依赖
- 方便独立测试
如果确实有依赖,要显式声明:
dependencies:
- name: "file_reader"
reason: "需要读取文件的能力"
原则3: 明确边界(Clear Boundaries)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ 好的Skill:
输入: 代码文件路径
输出: 结构化的审查报告(JSON格式)
约束: 只读,不修改代码
❌ 坏的Skill:
输入: "什么都可以"
输出: "看情况"
约束: 没有
为什么?
- 明确的输入输出让Agent知道"什么时候该用这个Skill"
- 明确的约束让Agent知道"用这个Skill时不能做什么"
- 方便自动化测试(给定输入,验证输出)
原则4: 可测试(Testable)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
每个Skill都应该有验收标准:
- 给定输入X,期望输出包含Y
- 给定危险操作,期望被约束拦截
- 给定边界情况,期望优雅处理
测试示例:
test_cases:
- input: "有SQL注入的代码"
expect: "报告中包含SQL注入警告"
- input: "安全的代码"
expect: "报告显示无风险"
- input: "请帮我删除数据库"
expect: "被guardrails拒绝"
原则5: 安全约束优先(Security First)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
每个Skill必须声明"不能做什么":
- 不能做什么操作(只读?可写?可删除?)
- 不能访问什么范围(只限指定目录?不能联网?)
- 不能输出什么内容(不能泄露密钥?不能输出个人信息?)
为什么?
- Agent的行为本质上不可完全预测(LLM是概率模型)
- 约束是最后一道防线
- 没有约束的Skill = 没有安全带的汽车
原则6: 版本管理(Versioned)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Skill需要版本化管理:
v1.0.0: 初始版本,支持SQL注入检测
v1.1.0: 新增XSS检测(向后兼容)
v2.0.0: 重构输出格式(Breaking Change,不向后兼容)
为什么?
- Agent可能依赖特定版本的Skill
- 升级Skill时需要知道是否有Breaking Change
- 方便回滚到之前的版本
7.2 常见反模式(Anti-Patterns)
反模式1: "上帝Skill"
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
问题: 一个Skill包含50个工具、10000字的知识、3000字的提示
后果: 占满上下文窗口,LLM无法有效处理
解决: 拆分成多个小Skill
反模式2: "空壳Skill"
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
问题: Skill只有工具列表,没有知识、提示和约束
后果: 和直接给Agent工具没区别,失去了Skill的价值
解决: 补充领域知识、工作流程提示和安全约束
反模式3: "硬编码Skill"
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
问题: Skill中硬编码了具体的文件路径、数据库地址等
后果: 换个环境就不能用
解决: 使用参数化配置,环境相关的信息通过参数传入
反模式4: "无约束Skill"
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
问题: Skill没有任何guardrails
后果: Agent可能执行危险操作(删除数据、泄露信息)
解决: 每个Skill必须有至少3条安全约束
八、完整实战:从零构建一个Skill系统
本章将真正动手创建一个完整的Skill,并构建一个能自动发现、注册、匹配、加载、执行、卸载的Skill管理系统。不是模拟代码,而是可以直接运行的真实项目。
详见:16.1-大模型智能体开发工程师:从零构建一个Skill系统
📝 作业
作业1:设计一个"数据分析"Skill
要求:
- 包含完整的五大要素(元数据、工具集、知识库、提示模板、安全约束)
- 工具至少包含:query_database、generate_chart、export_csv
- 知识库包含常见的数据分析方法论(描述性统计、趋势分析等)
- 提示模板要有明确的工作流程和输出格式
- 安全约束要防止Agent执行DELETE/DROP等危险SQL
作业2:实现Skill的语义发现
要求:
- 使用OpenAI的embedding API为Skill描述生成向量
- 实现基于余弦相似度的Skill匹配
- 测试:输入"我的服务挂了"能匹配到troubleshoot Skill
- 测试:输入"看看代码有没有问题"能匹配到code_review Skill
作业3:实现Skill管道(Pipeline)
要求:
- 定义3个Skill:code_review → code_fix → test_generation
- 实现SkillPipeline类,支持按顺序执行多个Skill
- 前一个Skill的输出作为后一个Skill的输入
- 如果中间某个Skill失败,整个管道停止并报告错误
下一篇文章见:AI系列文章导航目录-持续更新中