1. Agent Skills 是什么?
核心概念
Agent Skills 是 Anthropic 为 Claude 设计的一种模块化知识和能力扩展机制。它本质上是一个包含特定领域最佳实践、工作流程和工具使用说明的文档系统。
具体形态
一个 Skill 通常是一个包含以下内容的文件夹:
skill-name/
├── SKILL.md # 主文档,包含触发条件、使用指南
├── examples/ # 示例文件
├── templates/ # 模板文件
└── utils/ # 辅助脚本(可选)
SKILL.md 的典型结构
# Skill Name
## Description
何时触发这个 skill,它能解决什么问题
## Trigger Conditions
- 用户提到某个关键词
- 用户上传特定类型的文件
- 任务需要特定的输出格式
## Instructions
1. 第一步做什么
2. 如何处理数据
3. 输出格式要求
4. 常见错误和解决方案
## Code Examples
具体的代码示例和最佳实践
## Dependencies
需要的工具、库、API
工作流程
用户请求
↓
Claude 分析请求
↓
查看 available_skills 列表
↓
匹配相关 skill(可能多个)
↓
使用 view 工具读取 SKILL.md
↓
按照 skill 指引执行任务
↓
返回结果
实际执行示例
用户: "帮我创建一个 Word 文档"
# Claude 的内部流程
1. 识别关键词 "Word 文档" → 匹配 docx skill
2. view("/mnt/skills/public/docx/SKILL.md")
3. 读取最佳实践:
- 使用 python-docx 库
- 注意段落格式
- 表格创建技巧
- 图片插入方法
4. 按照 skill 指引生成代码
5. 创建文件并输出
2. Skills vs MCP 的区别
本质差异对比表
| 维度 | Agent Skills | MCP (Model Context Protocol) |
|---|---|---|
| 定位 | 知识库 + 工作流指南 | 工具调用协议 |
| 内容 | 文档、最佳实践、模板 | 可执行的函数/工具 |
| 执行方式 | Claude 读取后自己写代码 | 直接调用外部服务 |
| 数据来源 | 静态文档(Markdown) | 动态 API/数据库 |
| 适用场景 | 文档生成、格式转换、编码规范 | 外部系统集成、实时数据查询 |
具体例子对比
场景: 创建 Excel 报表
使用 Skill
# Claude 读取 xlsx skill 后的执行
import openpyxl
from openpyxl.styles import Font, PatternFill
# skill 教 Claude 如何:
wb = openpyxl.Workbook()
ws = wb.active
# 1. 设置标题格式(skill 提供的最佳实践)
header_fill = PatternFill(start_color="4472C4", fill_type="solid")
ws['A1'].fill = header_fill
# 2. 添加数据验证(skill 中的示例)
from openpyxl.worksheet.datavalidation import DataValidation
dv = DataValidation(type="list", formula1='"选项1,选项2"')
ws.add_data_validation(dv)
# Claude 自己写完整代码
wb.save('report.xlsx')
使用 MCP
# MCP Server 提供的工具
tools = [
{
"name": "create_excel_report",
"description": "创建 Excel 报表",
"input_schema": {
"type": "object",
"properties": {
"data": {"type": "array"},
"template": {"type": "string"}
}
}
}
]
# Claude 直接调用
result = mcp_server.create_excel_report(
data=sales_data,
template="monthly_report"
)
MCP 会被淘汰吗?
不会,它们是互补的
- Skills 优势场景:
- 文档格式转换(Word/Excel/PDF)
- 前端代码生成(React/Vue)
- 遵循特定编码规范
- 创意内容生成
- MCP 优势场景:
- 访问实时数据库
- 调用第三方 API
- 执行系统级操作
- 需要认证的服务
- 协同工作示例:
用户: "从数据库读取销售数据,生成 PPT 报告"
Claude:
1. 用 MCP 连接数据库获取数据
2. 用 pptx skill 学习如何创建专业 PPT
3. 结合两者生成最终报告
3. 如何使用和创建 Skills
3.1 查找现有 Skills
系统提供的 Skills 位置
/mnt/skills/public/ # Anthropic 官方 skills
/mnt/skills/examples/ # 示例 skills
/mnt/skills/user/ # 用户自定义 skills
查看可用 skills
# 在 Claude 的计算机环境中
ls /mnt/skills/public/
# 输出: docx/ pptx/ xlsx/ pdf/ frontend-design/ ...
3.2 使用 Skill 的标准流程
用户视角
你: "帮我创建一个 Vue3 项目的组件"
Claude: (自动触发相关 skill,你无需手动操作)
开发者视角(如果你想查看 skill 内容)
# Claude 内部会执行
view("/mnt/skills/public/frontend-design/SKILL.md")
3.3 创建自定义 Skill - Vue3 项目示例
Step 1: 创建 Skill 文件结构
/mnt/skills/user/vue3-component-builder/
├── SKILL.md
├── templates/
│ ├── component-template.vue
│ ├── composable-template.ts
│ └── store-template.ts
└── examples/
├── data-table.vue
└── form-builder.vue
Step 2: 编写 SKILL.md
# Vue3 Component Builder Skill
## Description
为 Vue3 + TypeScript + Pinia + Vite 项目生成高质量组件。
遵循 Vue3 Composition API 最佳实践。
## Trigger Conditions
- 用户提到 "Vue3 组件"
- 用户要求创建 .vue 文件
- 用户提到 "Composition API"
- 任务涉及 Pinia store 或 composables
## Core Principles
### 1. 组件结构规范
````vue
<script setup lang="ts">
// 1. 导入顺序
import { ref, computed, onMounted } from 'vue'
import type { ComponentType } from '@/types'
// 2. Props 定义
interface Props {
modelValue: string
disabled?: boolean
}
const props = withDefaults(defineProps<Props>(), {
disabled: false,
})
// 3. Emits 定义
const emit = defineEmits<{
'update:modelValue': [value: string]
change: [value: string]
}>()
// 4. 响应式数据
const localValue = ref(props.modelValue)
// 5. Computed
const displayValue = computed(() => localValue.value.toUpperCase())
// 6. Methods
const handleChange = () => {
emit('update:modelValue', localValue.value)
}
// 7. Lifecycle
onMounted(() => {
console.log('Component mounted')
})
</script>
<template>
<div class="component-wrapper">
<!-- 模板内容 -->
</div>
</template>
<style scoped>
.component-wrapper {
/* 样式 */
}
</style>
```text ### 2. Composables 规范 ```typescript // useCounter.ts import { ref,
computed } from 'vue' export function useCounter(initialValue = 0) { const count
= ref(initialValue) const doubled = computed(() => count.value * 2) const
increment = () => count.value++ const decrement = () => count.value-- return {
count, doubled, increment, decrement } } ```text ### 3. Pinia Store 规范
```typescript // stores/user.ts import { defineStore } from 'pinia' import {
ref, computed } from 'vue' export const useUserStore = defineStore('user', () =>
{ // State const user = ref
<User | null></User>
#### Step 4: 添加示例
##### examples/data-table.vue
```vue
<script setup lang="ts">
import { ref, computed } from 'vue'
interface Column {
key: string
label: string
sortable?: boolean
}
interface Props {
columns: Column[]
data: Record<string, any>[]
}
const props = defineProps<Props>()
const sortKey = ref<string>('')
const sortOrder = ref<'asc' | 'desc'>('asc')
const sortedData = computed(() => {
if (!sortKey.value) return props.data
return [...props.data].sort((a, b) => {
const aVal = a[sortKey.value]
const bVal = b[sortKey.value]
const order = sortOrder.value === 'asc' ? 1 : -1
return aVal > bVal ? order : -order
})
})
const handleSort = (key: string) => {
if (sortKey.value === key) {
sortOrder.value = sortOrder.value === 'asc' ? 'desc' : 'asc'
} else {
sortKey.value = key
sortOrder.value = 'asc'
}
}
</script>
<template>
<table class="data-table">
<thead>
<tr>
<th
v-for="col in columns"
:key="col.key"
@click="col.sortable && handleSort(col.key)"
:class="{ sortable: col.sortable }"
>
{{ col.label }}
<span v-if="sortKey === col.key">
{{ sortOrder === 'asc' ? '↑' : '↓' }}
</span>
</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, index) in sortedData" :key="index">
<td v-for="col in columns" :key="col.key">
{{ row[col.key] }}
</td>
</tr>
</tbody>
</table>
</template>
<style scoped>
.data-table {
width: 100%;
border-collapse: collapse;
}
.data-table th,
.data-table td {
padding: 12px;
text-align: left;
border-bottom: 1px solid #e5e7eb;
}
.data-table th.sortable {
cursor: pointer;
user-select: none;
}
.data-table th.sortable:hover {
background-color: #f3f4f6;
}
</style>
```
### 3.4 使用自定义 Skill
创建好 skill 后,上传到 Claude:
```plain
你: "我上传了一个 Vue3 项目的 skill,帮我创建一个数据表格组件"
Claude:
1. 检测到 vue3-component-builder skill
2. 读取 SKILL.md
3. 参考 examples/data-table.vue
4. 按规范生成组件
```
---
## 4. Skills 实现外部知识检索
### 4.1 传统 RAG vs Skills 对比
#### 传统 RAG 架构
```plain
用户查询
↓
向量化查询
↓
在向量数据库中检索 (Top-K)
↓
拼接检索到的文档片段
↓
发送给 LLM
↓
LLM 基于片段生成答案
```
##### 问题
- 检索到的片段可能不连贯
- 缺少上下文信息
- 无法执行复杂工作流
- 依赖外部向量数据库
#### Skills 架构
```plain
用户请求
↓
匹配相关 skill
↓
读取完整 skill 文档
↓
Claude 理解完整上下文
↓
执行文档中的工作流
↓
生成结果
```
##### 优势
- 完整的上下文理解
- 包含可执行的代码示例
- 工作流程清晰
- 无需外部依赖
### 4.2 实际案例: 公司内部知识库
#### 场景设定
某科技公司需要让 Claude 回答关于内部技术栈、编码规范、部署流程的问题。
#### 传统 RAG 实现
##### 步骤 1: 准备向量数据库
```python
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
# 文档分块
docs = [
"我们使用 Vue3 + Vite...",
"部署流程: 1. 运行测试 2. 构建...",
"代码审查规范..."
]
# 向量化
embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_texts(docs, embeddings)
```
###### 步骤 2: 查询时检索
```python
query = "如何部署前端项目?"
relevant_docs = vectorstore.similarity_search(query, k=3)
# 拼接上下文
context = "\n".join([doc.page_content for doc in relevant_docs])
# 发送给 Claude
response = claude.complete(
prompt=f"基于以下文档回答: {context}\n\n问题: {query}"
)
```
###### 问题示例
```plain
检索到的片段:
1. "...运行测试..."
2. "...Vue3 配置..."
3. "...Docker 命令..."
缺少:
- 完整部署流程
- 前置条件
- 错误处理步骤
```
#### Skills 实现
##### 创建 deployment skill
````markdown
# Company Deployment Skill
## Frontend Deployment Workflow
### Prerequisites
- Node.js 18+
- 访问 GitLab CI
- AWS CLI 配置完成
### Step-by-Step Process
#### 1. 本地测试
````bash
npm run test:unit
npm run test:e2e
npm run lint
```text
#### 2. 构建生产版本
```bash
npm run build
## 验证构建产物
ls -la dist/
```text
#### 3. 部署到 Staging
```bash
## 使用公司 CLI 工具
company-cli deploy --env=staging --project=frontend
## 等待健康检查
company-cli health-check --env=staging
```text
#### 4. 运行冒烟测试
```bash
npm run test:smoke -- --env=staging
```text
#### 5. 部署到 Production
```bash
## 需要审批
company-cli deploy --env=production --project=frontend --require-approval
## 监控指标
company-cli monitor --env=production --duration=30m
```text
### Rollback Procedure
如果部署失败:
```bash
company-cli rollback --env=production --to-version=previous
```text
### Common Issues
#### Issue: 构建失败 "Module not found"
Solution:
```bash
rm -rf node_modules package-lock.json
npm install
```text
#### Issue: 健康检查超时
Solution:
1. 检查 AWS 安全组规则
2. 验证环境变量配置
3. 查看 CloudWatch 日志
### Notification Channels
- Slack: #deployments
- PagerDuty: 生产环境问题
### Related Documentation
- [AWS 架构图](https://internal.wiki/aws-arch)
- [CI/CD 配置](https://gitlab.company.com/docs/cicd)
```plain
### 使用示例:
```text
你: "如何部署我们的前端项目到生产环境?"
Claude:
1. 读取 deployment skill
2. 理解完整流程
3. 返回详细步骤
根据公司的部署规范,你需要按以下步骤操作:
[返回完整流程,包含命令、检查点、错误处理]
如果遇到健康检查超时,可以检查 AWS 安全组规则...
```plain
### 4.3 Skills 的优势总结
| 维度 | 传统 RAG | Skills |
|------|----------|--------|
| 上下文完整性 | 片段化 | 完整文档 |
| 代码示例 | 可能被截断 | 完整可执行 |
| 工作流支持 | 难以表达 | 内置支持 |
| 维护成本 | 需要向量数据库 | 纯文件系统 |
| 版本控制 | 困难 | Git 友好 |
| 调试 | 不透明 | 可直接查看 |
| 实时更新 | 需要重新索引 | 直接编辑文件 |
### 4.4 混合方案: Skills + RAG
对于超大规模知识库,可以结合使用:
```text
外层: RAG 检索相关 skill 名称 ↓ 中层: 加载对应的 skill 文档 ↓ 内层: Claude 按 skill 执行
```plain
#### 示例代码:
```python
# 1. 用 RAG 找到相关 skill
query = "前端性能优化"
relevant_skills = vectorstore.search(query)
# 结果: ["frontend-performance", "vue3-optimization"]
# 2. 加载这些 skills
for skill_name in relevant_skills:
skill_content = read_skill(f"/mnt/skills/user/{skill_name}/SKILL.md")
# Claude 获得完整的优化指南
# 3. Claude 综合所有 skills 给出答案
---
## 5. 实战演示: 完整的 Vue3 组件生成
### 场景
用户需要一个带搜索、排序、分页的数据表格组件。
### 执行流程
#### Step 1: 触发 skill
```plain
用户: "创建一个 Vue3 数据表格组件,要支持搜索、排序和分页"
```
#### Step 2: Claude 读取 skill
```python
view("/mnt/skills/user/vue3-component-builder/SKILL.md")
view("/mnt/skills/user/vue3-component-builder/examples/data-table.vue")
```
#### Step 3: 生成代码
```typescript
// src/components/DataTable.vue
<script setup lang="ts">
import { ref, computed } from 'vue'
interface Column {
key: string
label: string
sortable?: boolean
width?: string
}
interface Props {
columns: Column[]
data: Record<string, any>[]
pageSize?: number
}
const props = withDefaults(defineProps<Props>(), {
pageSize: 10
})
// 搜索
const searchQuery = ref('')
const filteredData = computed(() => {
if (!searchQuery.value) return props.data
return props.data.filter(row =>
Object.values(row).some(value =>
String(value).toLowerCase().includes(searchQuery.value.toLowerCase())
)
)
})
// 排序
const sortKey = ref<string>('')
const sortOrder = ref<'asc' | 'desc'>('asc')
const sortedData = computed(() => {
if (!sortKey.value) return filteredData.value
return [...filteredData.value].sort((a, b) => {
const aVal = a[sortKey.value]
const bVal = b[sortKey.value]
const order = sortOrder.value === 'asc' ? 1 : -1
if (typeof aVal === 'number' && typeof bVal === 'number') {
return (aVal - bVal) * order
}
return String(aVal).localeCompare(String(bVal)) * order
})
})
const handleSort = (key: string) => {
if (sortKey.value === key) {
sortOrder.value = sortOrder.value === 'asc' ? 'desc' : 'asc'
} else {
sortKey.value = key
sortOrder.value = 'asc'
}
}
// 分页
const currentPage = ref(1)
const totalPages = computed(() =>
Math.ceil(sortedData.value.length / props.pageSize)
)
const paginatedData = computed(() => {
const start = (currentPage.value - 1) * props.pageSize
const end = start + props.pageSize
return sortedData.value.slice(start, end)
})
const goToPage = (page: number) => {
if (page >= 1 && page <= totalPages.value) {
currentPage.value = page
}
}
</script>
<template>
<div class="data-table-container">
<!-- 搜索框 -->
<div class="search-bar">
<input
v-model="searchQuery"
type="text"
placeholder="搜索..."
class="search-input"
/>
</div>
<!-- 表格 -->
<table class="data-table">
<thead>
<tr>
<th
v-for="col in columns"
:key="col.key"
:style="{ width: col.width }"
@click="col.sortable && handleSort(col.key)"
:class="{ sortable: col.sortable, active: sortKey === col.key }"
>
{{ col.label }}
<span v-if="sortKey === col.key" class="sort-indicator">
{{ sortOrder === 'asc' ? '↑' : '↓' }}
</span>
</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, index) in paginatedData" :key="index">
<td v-for="col in columns" :key="col.key">
{{ row[col.key] }}
</td>
</tr>
</tbody>
</table>
<!-- 分页 -->
<div class="pagination">
<button
@click="goToPage(currentPage - 1)"
:disabled="currentPage === 1"
class="pagination-btn"
>
上一页
</button>
<span class="page-info">
第 {{ currentPage }} / {{ totalPages }} 页
(共 {{ sortedData.length }} 条)
</span>
<button
@click="goToPage(currentPage + 1)"
:disabled="currentPage === totalPages"
class="pagination-btn"
>
下一页
</button>
</div>
</div>
</template>
<style scoped>
.data-table-container {
display: flex;
flex-direction: column;
gap: 16px;
}
.search-bar {
display: flex;
justify-content: flex-end;
}
.search-input {
padding: 8px 12px;
border: 1px solid #d1d5db;
border-radius: 6px;
width: 300px;
font-size: 14px;
}
.search-input:focus {
outline: none;
border-color: #3b82f6;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
.data-table {
width: 100%;
border-collapse: collapse;
background: white;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.data-table th,
.data-table td {
padding: 12px 16px;
text-align: left;
border-bottom: 1px solid #e5e7eb;
}
.data-table th {
background-color: #f9fafb;
font-weight: 600;
color: #374151;
}
.data-table th.sortable {
cursor: pointer;
user-select: none;
transition: background-color 0.2s;
}
.data-table th.sortable:hover {
background-color: #f3f4f6;
}
.data-table th.active {
background-color: #e5e7eb;
}
.sort-indicator {
margin-left: 4px;
color: #3b82f6;
}
.data-table tbody tr:hover {
background-color: #f9fafb;
}
.pagination {
display: flex;
justify-content: center;
align-items: center;
gap: 16px;
}
.pagination-btn {
padding: 8px 16px;
border: 1px solid #d1d5db;
border-radius: 6px;
background: white;
cursor: pointer;
font-size: 14px;
transition: all 0.2s;
}
.pagination-btn:hover:not(:disabled) {
background-color: #f3f4f6;
border-color: #9ca3af;
}
.pagination-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.page-info {
font-size: 14px;
color: #6b7280;
}
</style>
```
#### Step 4: 生成使用示例
```vue
<!-- App.vue -->
<script setup lang="ts">
import { ref } from 'vue'
import DataTable from './components/DataTable.vue'
const columns = [
{ key: 'id', label: 'ID', sortable: true, width: '80px' },
{ key: 'name', label: '姓名', sortable: true },
{ key: 'email', label: '邮箱', sortable: true },
{ key: 'role', label: '角色', sortable: true },
{ key: 'createdAt', label: '创建时间', sortable: true },
]
const data = ref([
{
id: 1,
name: '张三',
email: 'zhang@example.com',
role: '管理员',
createdAt: '2024-01-15',
},
{
id: 2,
name: '李四',
email: 'li@example.com',
role: '用户',
createdAt: '2024-01-16',
},
{
id: 3,
name: '王五',
email: 'wang@example.com',
role: '用户',
createdAt: '2024-01-17',
},
// ... 更多数据
])
</script>
<template>
<div class="app">
<h1>用户管理</h1>
<DataTable :columns="columns" :data="data" :page-size="5" />
</div>
</template>
```
#### Step 5: 生成类型定义
```typescript
// src/types/table.ts
export interface Column {
key: string
label: string
sortable?: boolean
width?: string
formatter?: (value: any) => string
}
export interface TableData {
[key: string]: any
}
export type SortOrder = 'asc' | 'desc'
```
---
## 6. 总结
### Skills 的核心价值
1. **知识封装**: 将最佳实践、模板、示例打包成可复用模块
2. **上下文完整**: 提供完整的工作流程,而非碎片化信息
3. **即时可用**: 无需外部数据库,纯文件系统即可
4. **易于维护**: 可通过 Git 版本控制,易于协作
5. **灵活组合**: 多个 skills 可协同工作
### 何时使用 Skills vs MCP vs RAG
#### 使用 Skills
- 文档生成(Word/Excel/PPT/PDF)
- 代码生成(遵循特定规范)
- 工作流程执行
- 模板化任务
##### 使用 MCP
- 访问外部系统(数据库/API)
- 需要认证的服务
- 实时数据查询
- 系统集成
###### 使用 RAG
- 海量文档检索
- 语义搜索
- 动态知识库
- 不确定的查询范围
**混合使用:** 大多数复杂应用会结合三者:
```plain
RAG 找到相关领域 → MCP 获取数据 → Skills 指导处理流程
```
### 下一步
1. 查看系统提供的 skills: `view /mnt/skills/public/`
2. 创建你的第一个自定义 skill
3. 在实际项目中测试和迭代
4. 分享给团队使用
记住: Skills 是 Claude 的"技能树",合理构建可以极大提升 AI 助手的专业能力。