Agent Skills 完全教程
从零开始掌握AI智能体技能开发
在opencode中使用kimi2.5生成的skil教程。
目录
- [Agent Skills 简介](#Agent Skills 简介)
- [为什么需要Agent Skills](#为什么需要Agent Skills)
- 生态系统概览
- 核心概念与工作原理
- 快速开始
- [SKILL.md 完整规范](#SKILL.md 完整规范)
- 目录结构详解
- 编写最佳实践
- 实战:创建代码审查Skill
- 实战:创建API测试Skill
- 验证与调试
- 在OpenCode中使用Skills
- 集成到自定义Agent
- 高级技巧
- 附录:参考资源
1. Agent Skills 简介
1.1 什么是Agent Skills
Agent Skills 是由Anthropic开发并开源的一种轻量级、开放式格式,专门用于扩展AI智能体的能力。它是一种标准化的方式,让开发者可以将专业知识、工作流程和特定领域的操作封装成可复用的"技能包"。
简单来说,一个Skill就是一个包含指令、脚本和资源的文件夹,AI智能体可以按需加载和使用这些资源来完成特定任务。
1.2 核心特点
Agent Skills具有以下几个核心特点:
1. 简单开放
- 使用纯文本格式(Markdown + YAML)
- 无需复杂的配置或专有工具
- 完全开源,社区驱动发展
2. 一次编写,到处使用
- 编写好的Skill可以在多个兼容的AI工具中使用
- 支持20+主流AI开发工具(详见第3章)
- 跨平台、跨产品复用
3. 渐进式披露
- 智能体只在需要时加载相关技能
- 有效管理上下文窗口,避免信息过载
- 保持响应速度和准确性
4. 自文档化
- SKILL.md文件本身就是文档
- 易于审计、理解和改进
- 便于团队协作和知识共享
1.3 典型使用场景
领域专业知识
将法律审查流程、数据分析管道、医疗诊断指南等专业领域知识打包成可复用的技能。
新能力扩展
赋予智能体新能力,如创建演示文稿、构建MCP服务器、分析复杂数据集等。
可重复工作流
将多步骤任务转化为一致且可审计的工作流程,确保每次执行都遵循最佳实践。
组织知识管理
将企业、团队或个人的专业知识以可移植、版本控制的方式保存和共享。
2. 为什么需要Agent Skills
2.1 当前AI智能体的痛点
虽然AI智能体的能力越来越强,但在实际工作中常常面临以下问题:
1. 缺乏上下文
智能体往往缺少完成任务所需的领域知识和特定上下文。例如,当要求AI审查代码时,它可能不知道团队的代码规范;当要求AI处理PDF时,它可能不清楚具体的提取需求。
2. 重复工作
每次遇到类似任务都需要重新解释需求、提供背景信息,效率低下。
3. 一致性问题
不同时间、不同情境下,AI对同一类任务的处理方式可能不一致,难以保证质量。
4. 知识孤岛
团队成员的个人经验和最佳实践难以沉淀和共享。
2.2 Agent Skills如何解决这些问题
1. 提供专业知识上下文
Skills通过打包领域知识和工作流程,让智能体能够按需加载所需的专业知识。例如:
- 一个"代码审查"Skill可以包含团队的代码规范、审查检查清单和最佳实践
- 一个"PDF处理"Skill可以包含文档提取的具体步骤和工具使用方法
2. 标准化工作流程
将经常重复的任务标准化,智能体只需激活相应的Skill即可按照既定流程执行,无需每次都详细说明。
3. 确保一致性和质量
通过预定义的指令和脚本,确保每次执行都遵循相同的质量标准和工作流程。
4. 知识沉淀和共享
将个人和团队的知识封装成Skills,便于版本控制、分享和复用,避免知识流失。
2.3 Agent Skills的优势总结
| 优势 | 说明 |
|---|---|
| 便携性 | 纯文件格式,易于编辑、版本控制和分享 |
| 可扩展性 | 从简单文本指令到复杂脚本和模板,灵活性高 |
| 可审计性 | SKILL.md本身就是文档,易于理解和审查 |
| 互操作性 | 同一Skill可在多个AI工具中使用 |
| 渐进加载 | 智能管理上下文,按需加载资源 |
3. 生态系统概览
3.1 支持Agent Skills的主流工具
Agent Skills已被业界广泛接受和支持,目前已有超过20个主流AI开发工具兼容此格式。以下是主要支持的工具列表:
IDE和编辑器
- Cursor - AI-first代码编辑器
- VS Code - 配合相关插件使用
- TRAE - AI驱动的开发环境
- Roo Code - AI编程助手
命令行工具
- OpenCode - 智能编程助手(即本教程使用的工具)
- Gemini CLI - Google的AI命令行工具
- Claude Code - Anthropic的AI编程工具
- Goose - GitHub开发的AI助手
- OpenAI Codex - OpenAI的代码生成工具
- Command Code - AI命令行助手
企业级平台
- Databricks - 数据分析和AI平台
- Amp - AI开发平台
- Factory - AI软件工厂
其他工具
- Mux - Coder.com的AI编辑器
- Letta - AI代理框架
- Firebender - AI开发工具
- Spring AI - Spring框架的AI集成
- Piebald - AI辅助编程
- Autohand Code CLI - AI代码助手
- Ona - AI开发平台
- Agentman - AI代理管理工具
- Mistral AI Vibe - Mistral的AI工具
- VT Code - AI编程工具
3.2 不同工具的使用方式
Filesystem-based Agents(基于文件系统的智能体)
这类工具在计算机环境中运行,通过shell命令访问Skills。例如:
- 使用
cat /path/to/skill/SKILL.md加载技能 - 执行
scripts/目录中的脚本 - 读取
references/目录中的参考文档
代表工具:OpenCode、Claude Code、Goose
Tool-based Agents(基于工具的智能体)
这类工具在没有专门计算机环境的情况下运行,通过特定的工具实现来触发Skills和访问资源。开发者需要实现自己的工具来支持Skills。
代表工具:Cursor、VS Code插件、Web应用
3.3 社区和生态
GitHub仓库
- 官方规范仓库: https://github.com/agentskills/agentskills
- 示例Skills: https://github.com/anthropics/skills
- 参考库: https://github.com/agentskills/agentskills/tree/main/skills-ref
官方文档
- 主页: https://agentskills.io
- 完整规范: https://agentskills.io/specification
- 集成指南: https://agentskills.io/integrate-skills
社区贡献
Agent Skills是开放标准,欢迎社区贡献。开发者可以:
- 提交新的Skills示例
- 改进规范和文档
- 开发支持Skills的新工具
- 分享使用经验和最佳实践
4. 核心概念与工作原理
4.1 Skill的基本结构
一个Agent Skill是一个文件夹,至少包含一个SKILL.md文件。典型的Skill结构如下:
my-skill/
├── SKILL.md # 必需:包含元数据和指令
├── scripts/ # 可选:可执行脚本
│ ├── analyze.py
│ └── process.sh
├── references/ # 可选:参考文档
│ ├── REFERENCE.md
│ └── examples.md
└── assets/ # 可选:模板和资源
├── template.docx
└── schema.json
4.2 渐进式披露机制
Agent Skills的核心设计原则是渐进式披露(Progressive Disclosure),这是一种高效管理上下文窗口的机制:
第一层:元数据加载(约100 tokens)
在智能体启动时,系统只加载所有可用Skill的name和description字段。这让智能体知道有哪些技能可用,但不需要了解详细内容。
示例:
Skill名称: pdf-processing
描述: 从PDF文件中提取文本和表格,填充表单,合并文档
第二层:指令加载(建议< 5000 tokens)
当智能体判断某个Skill与当前任务相关时,它会读取该Skill的完整SKILL.md文件内容,包括所有指令和说明。
第三层:资源按需加载
只有在实际执行过程中,才会根据需要加载scripts/、references/或assets/目录中的具体文件。
4.3 技能发现与激活流程
1. 发现阶段(Discovery)
- 智能体启动时扫描配置的Skills目录
- 解析每个Skill的
SKILL.md文件,提取name和description - 构建可用技能列表
2. 匹配阶段(Matching)
- 用户输入任务描述
- 智能体根据任务内容匹配相关的Skill描述
- 确定哪些Skill可能有助于完成任务
3. 激活阶段(Activation)
- 智能体读取匹配Skill的完整
SKILL.md内容 - 将指令加载到上下文中
- 准备执行
4. 执行阶段(Execution)
- 智能体按照SKILL.md中的指令执行任务
- 根据需要调用scripts/目录中的脚本
- 查阅references/目录中的文档
- 使用assets/目录中的资源
4.4 SKILL.md文件解析
SKILL.md是Skill的核心文件,包含两部分内容:
Frontmatter(YAML前置元数据)
位于文件顶部,用---包围,包含Skill的元信息:
yaml
---
name: skill-name
description: 描述这个Skill的功能和使用场景
---
Body Content(Markdown正文)
位于frontmatter之后,包含实际的操作指令、示例和说明。使用标准的Markdown格式编写,没有严格的结构要求。
5. 快速开始
5.1 环境准备
要使用Agent Skills,您需要:
-
兼容的AI工具
- OpenCode(本教程使用)
- Claude Code
- Cursor
- 或其他支持Skills的工具
-
基本的文件操作能力
- 能够创建和编辑文件夹和文件
- 了解基本的Markdown和YAML语法
-
可选:Python环境
-
如果要编写Python脚本,需要Python 3.7+
-
安装skills-ref工具用于验证:
bashpip install skills-ref
-
5.2 创建第一个Skill
让我们创建一个简单的"问候"Skill来体验整个流程。
步骤1:创建Skill目录
bash
mkdir greeting-skill
cd greeting-skill
步骤2:创建SKILL.md文件
创建SKILL.md文件,内容如下:
yaml
---
name: greeting
description: 根据时间和用户偏好生成个性化的问候语。当用户需要问候、打招呼或需要礼貌开场时使用。
---
# 问候 Skill
## 何时使用
当用户需要问候语、打招呼或需要礼貌的开场白时使用此Skill。
## 如何生成问候语
1. **确定时间上下文**
- 早上(6:00-11:59):使用"早上好"
- 下午(12:00-17:59):使用"下午好"
- 晚上(18:00-23:59):使用"晚上好"
- 深夜(0:00-5:59):使用"深夜好"
2. **识别用户偏好**
- 正式场合:使用"您好"
- 非正式场合:使用"你好"或"嗨"
- 亲密关系:使用昵称或亲切的称呼
3. **添加个性化元素**
- 如果知道用户姓名,包含在问候中
- 可以添加表情符号增加亲和力(如用户偏好)
- 根据季节或节日添加相应元素
## 示例
- "早上好!希望您今天有个美好的一天!"
- "下午好,张先生!工作进展顺利吗?"
- "晚上好!今天过得怎么样?"
## 注意事项
- 保持简洁,避免过于冗长
- 考虑文化差异(不同地区问候习惯不同)
- 保持真诚和友好
步骤3:验证Skill结构
如果您安装了skills-ref工具,可以验证Skill:
bash
skills-ref validate ./greeting-skill
步骤4:在OpenCode中使用
将Skill文件夹放到OpenCode的skills目录中(通常在配置目录下)。然后在与OpenCode对话时,当你提到需要问候语时,它会自动激活此Skill。
5.3 快速测试
在OpenCode中输入:
请给我一个早上的问候语
OpenCode应该能够识别到这个任务与greeting Skill相关,并激活该Skill来生成合适的问候语。
5.4 注意事项
- 命名规范:Skill名称只能使用小写字母、数字和连字符,不能以下划线或连字符开头/结尾
- 描述清晰:描述字段对于Skill的激活至关重要,应该包含关键词帮助智能体识别何时使用该Skill
- 保持简洁:SKILL.md文件建议不超过500行,详细内容可以放到references/目录中
6. SKILL.md 完整规范
6.1 文件格式概述
SKILL.md是Agent Skills的核心文件,必须遵循以下格式:
-
YAML Frontmatter(必需)
- 位于文件开头
- 用
---包围 - 包含元数据字段
-
Markdown Body(内容部分)
- 位于frontmatter之后
- 使用标准Markdown格式
- 无严格结构要求
完整格式示例:
markdown
---
name: skill-name
description: Skill的描述
license: Apache-2.0
compatibility: 兼容性说明
metadata:
author: your-name
version: "1.0"
---
# Skill标题
## 章节1
内容...
## 章节2
内容...
6.2 Frontmatter字段详解
6.2.1 name(必需)
描述:Skill的唯一标识符
约束条件:
- 长度:1-64个字符
- 字符:仅允许小写字母(a-z)、数字和连字符(-)
- 不能以连字符开头或结尾
- 不能包含连续的连字符(--)
- 必须与父目录名称匹配
有效示例:
yaml
name: pdf-processing
name: code-review
name: data-analysis
name: api-testing-v2
无效示例:
yaml
name: PDF-Processing # 错误:包含大写字母
name: -pdf # 错误:以连字符开头
name: pdf--processing # 错误:连续的连字符
name: pdf_processing # 错误:使用下划线
6.2.2 description(必需)
描述:描述Skill的功能和使用场景
约束条件:
- 长度:1-1024个字符
- 不能为空
- 应描述Skill做什么以及何时使用它
编写建议:
- 包含具体的功能描述
- 包含使用场景和触发条件
- 包含相关关键词,帮助智能体识别何时使用该Skill
优秀示例:
yaml
description: 从PDF文件中提取文本和表格,填充PDF表单,合并多个PDF文档。当处理PDF文件或用户提到PDF、表单、文档提取时使用。
较差示例:
yaml
description: 帮助处理PDF。
6.2.3 license(可选)
描述:指定Skill的许可证
约束条件:
- 可以是许可证名称(如Apache-2.0、MIT等)
- 也可以引用捆绑的许可证文件
- 建议保持简短
示例:
yaml
license: Apache-2.0
license: MIT
license: Proprietary. LICENSE.txt中有完整条款
6.2.4 compatibility(可选)
描述:指示Skill的环境要求
约束条件:
- 长度:1-500个字符(如果提供)
- 只在Skill有特定环境要求时使用
- 可以指示目标产品、所需系统包、网络访问需求等
示例:
yaml
compatibility: 专为Claude Code(或类似产品)设计
compatibility: 需要git、docker、jq和网络访问
注意:大多数Skills不需要此字段。
6.2.5 metadata(可选)
描述:用于存储额外元数据的键值映射
约束条件:
- 键和值都必须是字符串
- 客户端可以使用此字段存储规范未定义的属性
- 建议使用唯一的键名以避免冲突
示例:
yaml
metadata:
author: example-org
version: "1.0"
category: data-processing
6.2.6 allowed-tools(可选)
描述:预先批准的工具列表,Skill可以使用这些工具
约束条件:
- 空格分隔的工具列表
- 实验性功能,不同智能体实现的支持程度可能不同
示例:
yaml
allowed-tools: Bash(git:*) Bash(jq:*) Read
6.3 Markdown正文规范
6.3.1 内容结构
SKILL.md的正文部分没有严格的结构要求,但建议包含以下章节:
推荐章节结构:
- 标题(H1) - Skill的主要标题
- 何时使用 - 描述触发条件和使用场景
- 操作步骤 - 详细的执行步骤(可以使用编号列表)
- 示例 - 输入输出示例
- 注意事项 - 常见边界情况和警告
- 参考 - 相关文档链接或文件引用
6.3.2 编写最佳实践
1. 使用清晰的标题层级
- 使用
#表示主标题 - 使用
##表示主要章节 - 使用
###表示子章节 - 最多使用四级标题(
####)
2. 使用列表和表格
- 使用编号列表(1. 2. 3.)表示步骤
- 使用无序列表(- 或 *)表示要点
- 使用表格展示对比信息
3. 提供具体示例
- 包含输入示例
- 包含输出示例
- 包含代码示例(如果适用)
4. 引用外部文件
- 使用相对路径引用scripts/、references/、assets/中的文件
- 格式:
[描述](路径)或直接写路径
示例:
markdown
详细技术信息请参考 [参考文档](references/REFERENCE.md)。
执行分析脚本:
```bash
scripts/extract.py --input data.csv
#### 6.3.3 文件引用规范
当引用Skill内的其他文件时:
**正确做法**:
- 使用相对路径从SKILL.md根目录开始
- 保持引用层级简单(建议最多一级)
- 使用清晰的链接描述
```markdown
查看 [技术参考](references/TECHNICAL.md)
运行脚本:scripts/process.sh
使用模板:assets/template.docx
避免的做法:
- 不要使用绝对路径
- 避免深度嵌套的引用链
- 不要引用Skill外部的文件
6.4 命名和验证规则总结
| 规则 | 要求 |
|---|---|
| 目录名 | 必须与name字段完全匹配 |
| 文件名 | 必须大写为SKILL.md |
| name字段 | 小写、数字、连字符,1-64字符 |
| description字段 | 1-1024字符,非空 |
| 文件编码 | UTF-8 |
| YAML格式 | 标准YAML语法 |
7. 目录结构详解
7.1 必需文件:SKILL.md
每个Skill必须包含一个SKILL.md文件,位于Skill目录的根目录。这是Skill的核心定义文件,包含所有元数据和指令。
位置 :skill-name/SKILL.md
内容:
- YAML frontmatter(元数据)
- Markdown正文(指令和说明)
7.2 可选目录:scripts/
scripts/目录包含可执行代码,智能体可以运行这些脚本来完成特定任务。
位置 :skill-name/scripts/
用途:
- 数据处理脚本
- 自动化任务脚本
- 辅助工具脚本
- 集成脚本
支持的语言 :
语言支持取决于智能体实现。常见的支持语言包括:
- Python(.py)
- Bash/Shell(.sh)
- JavaScript/Node.js(.js)
- Ruby(.rb)
脚本编写规范:
- 自包含性:脚本应该尽可能自包含,或清楚说明依赖项
- 错误处理:包含有用的错误消息
- 边界情况:优雅地处理边界情况
- 文档:在脚本开头包含注释说明用途和用法
示例:
my-skill/
├── SKILL.md
└── scripts/
├── analyze.py # 数据分析脚本
├── cleanup.sh # 清理脚本
└── validate.js # 验证脚本
7.3 可选目录:references/
references/目录包含额外的文档和参考资料,智能体在需要时可以读取这些文件。
位置 :skill-name/references/
用途:
- 详细的技术参考
- 表单模板和结构化数据格式
- 领域特定文档(如finance.md、legal.md)
- 示例和最佳实践
常见文件:
REFERENCE.md- 详细的技术参考文档FORMS.md- 表单模板或结构化数据格式说明EXAMPLES.md- 更多示例- 领域特定文件(如
api-reference.md、style-guide.md)
设计原则:
- 按需加载:这些文件只在需要时加载,因此较小的文件意味着更少的上下文使用
- 聚焦单一主题:每个参考文件应该专注于一个特定主题
- 渐进式详细程度:SKILL.md提供概述,references/提供详细信息
示例:
my-skill/
├── SKILL.md
└── references/
├── REFERENCE.md # 详细技术参考
├── API-GUIDE.md # API使用指南
├── STYLE-GUIDE.md # 样式指南
└── examples/
├── example-1.md
└── example-2.md
7.4 可选目录:assets/
assets/目录包含静态资源文件,如模板、图像和数据文件。
位置 :skill-name/assets/
用途:
- 模板:文档模板、配置模板、代码模板
- 图像:图表、示例截图、流程图
- 数据文件:查找表、模式定义、示例数据
- 配置文件:JSON、YAML配置文件
资源类型:
- 文档模板(.docx, .md, .txt)
- 配置文件(.json, .yaml, .xml)
- 图像文件(.png, .jpg, .svg)
- 数据文件(.csv, .json, .sql)
使用方式 :
智能体可以通过文件读取工具访问这些资源,或者在脚本中引用。
示例:
my-skill/
├── SKILL.md
└── assets/
├── templates/
│ ├── report-template.docx
│ └── email-template.md
├── schemas/
│ ├── data-schema.json
│ └── api-schema.yaml
└── images/
├── workflow-diagram.png
└── example-output.jpg
7.5 完整目录结构示例
以下是一个完整的Skill目录结构示例:
code-review-skill/
├── SKILL.md # 核心文件(必需)
├── scripts/ # 可执行脚本
│ ├── analyze-complexity.py # 代码复杂度分析
│ ├── check-style.sh # 代码风格检查
│ └── generate-report.js # 生成审查报告
├── references/ # 参考文档
│ ├── STYLE-GUIDE.md # 代码风格指南
│ ├── CHECKLIST.md # 审查检查清单
│ ├── COMMON-ISSUES.md # 常见问题
│ └── examples/
│ ├── good-example.js
│ └── bad-example.js
└── assets/ # 资源文件
├── templates/
│ └── review-template.md
└── config/
└── lint-rules.json
7.6 目录结构最佳实践
1. 从简单开始
不需要一开始就创建所有目录。可以从简单的SKILL.md开始,然后根据需要添加scripts/、references/和assets/。
2. 按需组织
- 只有当脚本、参考资料或资源文件较多时,才创建相应的子目录
- 如果只有少数几个文件,可以直接放在scripts/根目录
3. 清晰的命名
- 使用描述性的文件名
- 使用连字符分隔单词(kebab-case)
- 使用小写字母
4. 模块化设计
- 将大的SKILL.md拆分成references/中的多个小文件
- 每个脚本专注于一个具体任务
- 不同类型的资源放在不同子目录中
8. 编写最佳实践
8.1 上下文管理策略
1. 渐进式详细程度
-
第一层(元数据):只包含最基本的信息(约100 tokens)
- name和description字段
- 让智能体知道何时使用该Skill
-
第二层(指令):包含完整的操作指南(建议< 5000 tokens)
- SKILL.md的完整内容
- 详细的步骤和示例
-
第三层(资源):按需加载(无限制)
- 只有在实际需要时才加载scripts/、references/中的文件
- 保持主文件精简
2. 文件大小建议
- SKILL.md建议不超过500行
- 如果内容超过5000 tokens,考虑拆分到references/目录
- 保持主文件专注于核心流程
3. 分块加载
将详细内容放在references/目录中,智能体只在需要时读取:
markdown
# 主SKILL.md
## 详细说明
对于复杂的场景,请参考 [详细指南](references/DETAILED.md)。
## API参考
完整的API文档见 [API参考](references/API.md)。
8.2 描述字段优化
description字段是Skill的"门面",决定了智能体是否会在适当的时候激活该Skill。
1. 包含关键词
在描述中包含可能被用户提到的关键词:
yaml
# 好的描述
description: 从PDF文件中提取文本和表格,填充PDF表单,合并多个PDF文档。当处理PDF文件或用户提到PDF、表单、文档提取、PDF转换、PDF合并时使用。
# 不好的描述
description: 帮助处理PDF。
2. 明确使用场景
清楚地说明何时应该使用该Skill:
yaml
description: 执行代码审查,检查代码质量、潜在bug、安全问题和风格一致性。当用户要求审查代码、检查代码质量、进行代码评审或提到pull request审查时使用。
3. 避免过度宽泛
描述过于宽泛会导致Skill被错误激活:
yaml
# 避免
description: 帮助编程和开发。
# 推荐
description: 分析Python代码的性能瓶颈,提供优化建议。当用户提到Python性能问题、代码优化或慢查询时使用。
8.3 指令编写技巧
1. 使用编号步骤
将操作分解为清晰的编号步骤:
markdown
## 如何处理请求
1. **分析请求**
- 理解用户的核心需求
- 识别关键信息和约束条件
2. **验证输入**
- 检查输入数据的完整性
- 确保数据格式正确
3. **执行处理**
- 应用适当的处理逻辑
- 记录中间步骤
4. **生成输出**
- 格式化结果
- 提供清晰的解释
2. 提供具体示例
包含输入和输出示例:
markdown
## 示例
**输入**:
需要提取PDF中的表格数据
**处理步骤**:
1. 使用pdfplumber库打开PDF文件
2. 识别包含表格的页面
3. 提取表格数据到DataFrame
**输出**:
```csv
姓名,年龄,职位
张三,28,工程师
李四,32,设计师
**3. 处理边界情况**
明确说明常见边界情况的处理方式:
```markdown
## 边界情况处理
**空文件**:
- 如果输入文件为空,返回空结果并说明原因
- 不要抛出异常
**格式错误**:
- 如果数据格式不正确,尝试自动修复
- 如果无法修复,返回详细的错误信息
**大文件**:
- 对于超过10MB的文件,分批处理
- 显示进度信息
4. 使用决策树
对于复杂逻辑,使用决策树或流程图:
markdown
## 决策流程
用户请求
↓
是否包含代码?
↓ 是
检查代码语言
↓
Python? → 使用Python分析脚本
JavaScript? → 使用ESLint检查
其他? → 提供通用审查
↓
生成报告
8.4 脚本编写规范
1. 自包含性
脚本应该尽可能自包含,或在开头说明依赖项:
python
#!/usr/bin/env python3
"""
代码复杂度分析脚本
依赖项:
- Python 3.7+
- radon库: pip install radon
用法:
python analyze-complexity.py <file_path>
"""
import sys
import subprocess
def check_dependencies():
"""检查依赖项是否已安装"""
try:
import radon
except ImportError:
print("错误:需要安装radon库。运行: pip install radon")
sys.exit(1)
# 主逻辑...
2. 参数验证
验证输入参数并提供有用的错误消息:
python
import sys
import os
def validate_args():
if len(sys.argv) < 2:
print("错误:请提供文件路径")
print("用法:python script.py <file_path>")
sys.exit(1)
file_path = sys.argv[1]
if not os.path.exists(file_path):
print(f"错误:文件不存在: {file_path}")
sys.exit(1)
return file_path
3. 错误处理
使用try-except块处理可能的错误:
python
import json
def process_data(data):
try:
result = complex_operation(data)
return {"success": True, "data": result}
except ValueError as e:
return {"success": False, "error": f"数据格式错误: {str(e)}"}
except Exception as e:
return {"success": False, "error": f"处理失败: {str(e)}"}
4. 输出格式
使用结构化的输出格式(如JSON),便于智能体解析:
python
import json
def output_result(data):
"""输出JSON格式的结果"""
print(json.dumps(data, ensure_ascii=False, indent=2))
8.5 版本控制和维护
1. 版本号管理
在metadata中包含版本号:
yaml
metadata:
version: "1.0"
last-updated: "2024-01-15"
2. 变更日志
在SKILL.md末尾添加变更日志章节:
markdown
## 变更日志
### v1.1 (2024-01-20)
- 添加了对JavaScript代码的支持
- 优化了性能分析算法
### v1.0 (2024-01-15)
- 初始版本
- 支持Python代码审查
3. Git集成
将Skills放在Git仓库中进行版本控制:
bash
# 创建Skills仓库
mkdir my-skills
cd my-skills
git init
# 添加Skill
git add code-review-skill/
git commit -m "添加代码审查Skill v1.0"
9. 实战:创建代码审查Skill
9.1 需求分析
我们要创建一个实用的"代码审查"Skill,帮助智能体进行代码质量检查。该Skill应具备以下功能:
- 分析代码复杂度
- 检查潜在bug
- 评估代码风格
- 生成审查报告
9.2 创建Skill目录结构
bash
mkdir code-review-skill
cd code-review-skill
mkdir scripts references assets
touch SKILL.md
最终结构:
code-review-skill/
├── SKILL.md
├── scripts/
│ └── analyze.py
├── references/
│ ├── CHECKLIST.md
│ └── EXAMPLES.md
└── assets/
└── report-template.md
9.3 编写SKILL.md
创建SKILL.md文件:
yaml
---
name: code-review
description: 执行代码审查,分析代码质量、检查潜在bug、评估风格一致性并生成详细报告。当用户要求审查代码、检查代码质量、进行代码评审、review代码、检查代码问题或提到pull request审查时使用。
license: MIT
metadata:
author: your-name
version: "1.0"
---
# 代码审查 Skill
## 何时使用
当用户需要以下任何操作时激活此Skill:
- 审查代码质量
- 检查潜在bug
- 评估代码风格
- 进行代码评审(code review)
- 分析代码复杂度
- 检查pull request
- 请求代码改进建议
## 审查流程
### 1. 初步分析
1. **识别编程语言**
- 根据文件扩展名确定语言(.py, .js, .java等)
- 如果不确定,请询问用户
2. **确定审查范围**
- 单个文件还是多个文件?
- 是否包含测试代码?
- 是否有特定的关注点(性能、安全、可读性)?
### 2. 执行分析
#### 2.1 复杂度分析
运行复杂度分析脚本:
```bash
scripts/analyze.py complexity <file_path>
关注以下指标:
- 圈复杂度(Cyclomatic Complexity):应小于10,超过15需要重构
- 认知复杂度(Cognitive Complexity):应小于15
- 行数:函数/方法不应超过50行
2.2 代码检查
根据编程语言使用相应的工具:
- Python: 检查PEP 8合规性,使用pylint或flake8
- JavaScript: 检查ESLint规则
- Java: 检查Checkstyle规则
2.3 常见问题检查
参考 审查检查清单 进行人工审查:
- 空值检查是否充分?
- 异常处理是否完善?
- 资源是否正确释放?
- 是否存在硬编码值?
- 命名是否清晰有意义?
3. 生成报告
使用报告模板生成结构化报告:
报告模板
报告应包含以下部分:
3.1 摘要
- 审查的文件数量
- 发现的问题总数
- 严重程度分布(致命/严重/警告/建议)
3.2 详细发现
对每个问题提供:
- 位置:文件路径和行号
- 严重程度:致命(Critical)/严重(Major)/警告(Minor)/建议(Info)
- 描述:问题的详细说明
- 建议:如何修复的具体建议
- 示例:修复前后的代码对比(如果适用)
3.3 统计数据
- 代码行数
- 注释覆盖率
- 复杂度指标
- 问题密度(问题数/代码行数)
3.4 建议
- 优先级排序的改进建议
- 长期维护建议
- 重构机会
4. 严重程度定义
-
致命(Critical):会导致系统崩溃、数据丢失或安全漏洞的问题
- 示例:SQL注入漏洞、空指针异常、资源泄露
-
严重(Major):严重影响功能或性能的问题
- 示例:未处理的异常、性能瓶颈、逻辑错误
-
警告(Minor):不影响功能但影响代码质量的问题
- 示例:代码风格不一致、缺少文档字符串、魔术数字
-
建议(Info):改进建议,非必需但有益
- 示例:可简化代码、可使用新特性、可优化命名
示例
示例1:Python代码审查
输入:
python
def calculate_total(items):
total = 0
for i in range(len(items)):
total = total + items[i]['price'] * items[i]['quantity']
return total
审查结果:
警告:使用range(len())遍历列表
- 位置:第3行
- 描述:使用
range(len(items))不如直接遍历列表清晰 - 建议:改为
for item in items: - 修复后:
python
def calculate_total(items):
total = 0
for item in items:
total = total + item['price'] * item['quantity']
return total
建议:可使用sum()函数简化
- 位置:第2-5行
- 描述:可以使用sum()和生成器表达式简化代码
- 建议:考虑使用
return sum(item['price'] * item['quantity'] for item in items)
示例2:JavaScript代码审查
输入:
javascript
function getUserData(id) {
fetch('/api/users/' + id)
.then(res => res.json())
.then(data => {
console.log(data);
return data;
});
}
严重:未处理错误情况
- 位置:第2行
- 描述:fetch调用没有.catch()处理错误,也没有返回Promise,调用者无法处理错误
- 建议:添加错误处理并返回Promise
- 修复后:
javascript
function getUserData(id) {
return fetch('/api/users/' + id)
.then(res => {
if (!res.ok) throw new Error('Failed to fetch user');
return res.json();
})
.then(data => {
console.log(data);
return data;
})
.catch(error => {
console.error('Error fetching user:', error);
throw error;
});
}
边界情况处理
大型文件(>500行):
- 分批审查,每次审查一个模块或类
- 重点关注公共接口和高风险区域
- 建议用户将大文件拆分成小模块
二进制文件:
- 跳过非文本文件(图片、编译后的代码等)
- 记录跳过的文件列表
无法识别的语言:
- 进行通用代码质量检查(命名、结构、注释)
- 询问用户是否需要特定的审查标准
缺少上下文:
- 如果无法理解代码意图,询问用户代码的目的
- 查看相关的测试文件或文档
注意事项
- 保持建设性:以改进为目的,避免批评性语言
- 提供上下文:解释为什么某个做法不好,而不仅仅指出问题
- 优先级排序:帮助用户理解哪些是最重要的问题
- 考虑权衡:某些"问题"可能是合理的设计选择
- 关注安全:特别注意安全问题(注入、XSS、权限等)
- 尊重团队规范:如果已知团队有特定规范,优先应用
参考资源
-
审查检查清单 - 详细的检查项目列表
-
示例集合 - 常见问题的修复示例
-
报告模板 - 报告格式模板
9.4 编写脚本
创建
scripts/analyze.py:python#!/usr/bin/env python3 """ 代码分析脚本 依赖项: - Python 3.7+ - radon: pip install radon 用法: python analyze.py complexity <file_path> python analyze.py metrics <file_path> """ import sys import os import json import re from pathlib import Path def check_dependencies(): """检查依赖项""" try: from radon.complexity import cc_visit from radon.metrics import mi_visit except ImportError: return False, "需要安装radon库。运行: pip install radon" return True, None def get_language(file_path): """根据扩展名识别编程语言""" ext = Path(file_path).suffix.lower() language_map = { '.py': 'Python', '.js': 'JavaScript', '.ts': 'TypeScript', '.java': 'Java', '.cpp': 'C++', '.c': 'C', '.go': 'Go', '.rs': 'Rust', '.rb': 'Ruby' } return language_map.get(ext, 'Unknown') def analyze_complexity_python(file_path): """分析Python代码复杂度""" try: from radon.complexity import cc_visit from radon.metrics import mi_visit with open(file_path, 'r', encoding='utf-8') as f: code = f.read() # 圈复杂度分析 complexity_results = cc_visit(code) complexity_issues = [] for item in complexity_results: if item.complexity > 10: severity = "Critical" if item.complexity > 15 else "Major" complexity_issues.append({ "type": "complexity", "severity": severity, "location": f"{item.name} (line {item.lineno})", "message": f"圈复杂度过高: {item.complexity}", "suggestion": "考虑拆分函数,减少条件分支" }) # 可维护性指数 mi_score = mi_visit(code, multi=True) return { "success": True, "language": "Python", "complexity_issues": complexity_issues, "metrics": { "total_functions": len(complexity_results), "high_complexity_functions": len(complexity_issues), "maintainability_index": mi_score } } except Exception as e: return { "success": False, "error": str(e) } def analyze_code_style(file_path): """通用代码风格检查""" issues = [] try: with open(file_path, 'r', encoding='utf-8') as f: lines = f.readlines() except Exception as e: return {"success": False, "error": f"无法读取文件: {str(e)}"} for i, line in enumerate(lines, 1): stripped = line.strip() # 检查行长度 if len(line) > 100: issues.append({ "line": i, "type": "style", "severity": "Minor", "message": "行长度超过100字符" }) # 检查尾随空格 if line.rstrip() != line.rstrip('\n').rstrip(): issues.append({ "line": i, "type": "style", "severity": "Info", "message": "存在尾随空格" }) # 检查TODO/FIXME注释 if 'TODO' in stripped or 'FIXME' in stripped: issues.append({ "line": i, "type": "task", "severity": "Info", "message": f"发现待办事项: {stripped}" }) return { "success": True, "issues": issues, "total_lines": len(lines) } def main(): if len(sys.argv) < 3: print(json.dumps({ "success": False, "error": "用法: python analyze.py <command> <file_path>" })) sys.exit(1) command = sys.argv[1] file_path = sys.argv[2] if not os.path.exists(file_path): print(json.dumps({ "success": False, "error": f"文件不存在: {file_path}" })) sys.exit(1) # 检查依赖 deps_ok, deps_error = check_dependencies() if not deps_ok: print(json.dumps({ "success": False, "error": deps_error })) sys.exit(1) language = get_language(file_path) if command == "complexity": if language == "Python": result = analyze_complexity_python(file_path) else: result = { "success": True, "language": language, "message": f"暂不支持{language}的复杂度分析" } elif command == "metrics": result = analyze_code_style(file_path) else: result = { "success": False, "error": f"未知命令: {command}" } print(json.dumps(result, ensure_ascii=False, indent=2)) if __name__ == "__main__": main()
9.5 编写参考文档
创建references/CHECKLIST.md:
markdown
# 代码审查检查清单
## 通用检查项
### 代码质量
- [ ] 函数/方法是否单一职责?
- [ ] 函数长度是否超过50行?
- [ ] 参数数量是否过多(>5)?
- [ ] 是否有重复代码?
- [ ] 是否遵循DRY原则?
### 可读性
- [ ] 命名是否清晰有意义?
- [ ] 是否有足够的注释?
- [ ] 复杂逻辑是否有解释?
- [ ] 代码结构是否清晰?
### 错误处理
- [ ] 是否有适当的异常处理?
- [ ] 错误消息是否清晰?
- [ ] 是否处理了边界情况?
- [ ] 资源是否正确释放?
### 安全性
- [ ] 是否有SQL注入风险?
- [ ] 是否有XSS漏洞?
- [ ] 是否有敏感信息泄露?
- [ ] 输入是否经过验证?
## Python特定检查项
### 代码风格
- [ ] 是否遵循PEP 8?
- [ ] 导入顺序是否正确(标准库、第三方、本地)?
- [ ] 是否使用了类型提示?
- [ ] 文档字符串是否完整?
### Python特定问题
- [ ] 是否使用了列表推导式(代替循环)?
- [ ] 是否处理了None值?
- [ ] 是否使用了with语句管理资源?
- [ ] 是否避免使用可变默认参数?
## JavaScript/TypeScript特定检查项
### 代码风格
- [ ] 是否遵循ESLint规则?
- [ ] 是否使用了严格相等(===)?
- [ ] 是否避免了var,使用let/const?
- [ ] 回调函数是否过多?
### JS特定问题
- [ ] 异步代码是否正确处理?
- [ ] 是否处理了Promise错误?
- [ ] 是否避免了全局变量?
- [ ] 是否处理了this绑定问题?
## Java特定检查项
### 代码风格
- [ ] 是否遵循Checkstyle规则?
- [ ] 类名是否使用大驼峰?
- [ ] 方法名是否使用小驼峰?
- [ ] 常量是否全大写?
### Java特定问题
- [ ] 是否避免了空指针异常?
- [ ] 资源是否使用了try-with-resources?
- [ ] 集合是否使用了适当的类型?
- [ ] 是否避免了原始类型的装箱?
创建references/EXAMPLES.md:
markdown
# 常见问题修复示例
## Python示例
### 问题1:使用range(len())遍历列表
**问题代码**:
```python
def process_items(items):
for i in range(len(items)):
print(items[i])
修复后:
python
def process_items(items):
for item in items:
print(item)
或者需要索引时:
python
def process_items(items):
for i, item in enumerate(items):
print(f"{i}: {item}")
问题2:可变默认参数
问题代码:
python
def append_item(item, items=[]):
items.append(item)
return items
修复后:
python
def append_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
问题3:未处理文件关闭
问题代码:
python
def read_file(path):
f = open(path, 'r')
content = f.read()
f.close()
return content
修复后:
python
def read_file(path):
with open(path, 'r') as f:
return f.read()
JavaScript示例
问题1:使用而不是=
问题代码:
javascript
if (value == "5") {
// 也会匹配数字5
}
修复后:
javascript
if (value === "5") {
// 严格匹配字符串"5"
}
问题2:未处理Promise错误
问题代码:
javascript
fetch('/api/data')
.then(res => res.json())
.then(data => console.log(data));
修复后:
javascript
fetch('/api/data')
.then(res => {
if (!res.ok) throw new Error('Failed to fetch');
return res.json();
})
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
问题3:回调地狱
问题代码:
javascript
getData(function(a) {
getMoreData(a, function(b) {
getMoreData(b, function(c) {
console.log(c);
});
});
});
修复后(使用Promise/async-await):
javascript
async function fetchData() {
try {
const a = await getData();
const b = await getMoreData(a);
const c = await getMoreData(b);
console.log(c);
} catch (error) {
console.error('Error:', error);
}
}
Java示例
问题1:未关闭资源
问题代码:
java
public String readFile(String path) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader(path));
String content = reader.lines().collect(Collectors.joining("\n"));
reader.close();
return content;
}
修复后:
java
public String readFile(String path) throws IOException {
try (BufferedReader reader = new BufferedReader(new FileReader(path))) {
return reader.lines().collect(Collectors.joining("\n"));
}
}
问题2:空指针风险
问题代码:
java
public void processUser(User user) {
String name = user.getName().toUpperCase();
System.out.println(name);
}
修复后:
java
public void processUser(User user) {
if (user == null || user.getName() == null) {
System.out.println("Invalid user");
return;
}
String name = user.getName().toUpperCase();
System.out.println(name);
}
或使用Optional(Java 8+):
java
public void processUser(User user) {
Optional.ofNullable(user)
.map(User::getName)
.map(String::toUpperCase)
.ifPresent(System.out::println);
}
### 9.6 创建报告模板
创建`assets/report-template.md`:
```markdown
# 代码审查报告
## 基本信息
- **审查日期**: {date}
- **审查范围**: {files}
- **编程语言**: {languages}
- **总代码行数**: {lines_of_code}
## 执行摘要
### 总体评估
{overall_assessment}
### 统计概览
- **发现问题总数**: {total_issues}
- **致命问题**: {critical_count}
- **严重问题**: {major_count}
- **警告**: {minor_count}
- **建议**: {info_count}
- **问题密度**: {issue_density} 问题/千行代码
## 详细发现
{critical_issues_section}
{major_issues_section}
{minor_issues_section}
{info_issues_section}
## 复杂度分析
### 圈复杂度
- **平均复杂度**: {avg_complexity}
- **最高复杂度函数**: {highest_complexity_func}
- **需要重构的函数**: {functions_to_refactor}
### 可维护性指数
- **平均MI**: {avg_mi}
- **评级分布**: {mi_distribution}
## 代码风格
### 风格问题统计
- **行长度超限**: {long_line_count}
- **尾随空格**: {trailing_space_count}
- **待办事项**: {todo_count}
### 合规性评分
- **PEP 8合规性** (Python): {pep8_score}%
## 改进建议
### 高优先级(建议立即处理)
{high_priority_suggestions}
### 中优先级(建议近期处理)
{medium_priority_suggestions}
### 低优先级(建议逐步改进)
{low_priority_suggestions}
## 长期建议
{long_term_suggestions}
## 附录
### 审查检查清单
使用的检查项:{checklist_version}
### 工具版本
- 分析工具版本: {tool_version}
- 规则集版本: {ruleset_version}
9.7 验证Skill
使用skills-ref工具验证:
bash
cd code-review-skill
skills-ref validate .
如果没有安装skills-ref,可以手动检查:
- SKILL.md文件存在且格式正确
- name字段与目录名匹配
- description字段已填写
- scripts/目录中的脚本有执行权限(在Linux/Mac上)
9.8 测试Skill
在OpenCode中测试:
-
将code-review-skill目录复制到OpenCode的skills目录
-
启动OpenCode
-
输入测试指令:
请帮我审查以下Python代码: def calculate(x, y): if x > 0: if y > 0: return x + y return 0 -
OpenCode应该自动识别到code-review Skill并激活它
-
检查生成的审查报告是否符合预期
10. 实战:创建API测试Skill
10.1 需求分析
创建一个"API测试"Skill,帮助用户:
- 测试REST API端点
- 验证响应格式
- 检查状态码
- 生成测试报告
- 支持多种认证方式
10.2 创建目录结构
bash
mkdir api-testing-skill
cd api-testing-skill
mkdir -p scripts references assets/templates
touch SKILL.md
结构:
api-testing-skill/
├── SKILL.md
├── scripts/
│ ├── test-api.py
│ ├── validate-schema.py
│ └── generate-report.py
├── references/
│ ├── HTTP-CODES.md
│ ├── AUTH-METHODS.md
│ └── TEST-PATTERNS.md
└── assets/
└── templates/
└── test-report.md
10.3 编写SKILL.md
创建SKILL.md文件:
yaml
---
name: api-testing
description: 测试REST API端点,验证响应格式和状态码,支持多种认证方式,生成详细测试报告。当用户需要测试API、验证接口、检查端点、进行API集成测试或提到postman、curl、HTTP测试时使用。
license: MIT
metadata:
author: your-name
version: "1.0"
category: testing
---
# API测试 Skill
## 何时使用
当用户有以下需求时激活此Skill:
- 测试REST API端点
- 验证API响应
- 检查HTTP状态码
- 进行API集成测试
- 测试API认证
- 生成API测试报告
- 调试API问题
- 提到Postman、cURL、HTTP客户端测试
## 测试流程
### 1. 需求分析
#### 1.1 确定测试范围
询问或确认以下信息:
- **API基础URL**:例如 `https://api.example.com/v1`
- **测试端点**:例如 `/users`, `/orders/{id}`
- **HTTP方法**:GET、POST、PUT、DELETE等
- **认证方式**:Bearer Token、API Key、Basic Auth、OAuth2
#### 1.2 确定测试场景
- **功能测试**:验证API功能是否正常
- **边界测试**:测试极限值和异常输入
- **安全测试**:验证认证和授权
- **性能测试**:检查响应时间(可选)
### 2. 准备测试请求
#### 2.1 构建请求配置
根据API信息构建请求:
```json
{
"base_url": "https://api.example.com/v1",
"endpoint": "/users",
"method": "POST",
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer {token}"
},
"body": {
"name": "张三",
"email": "zhangsan@example.com"
}
}
2.2 选择认证方式
参考 认证方法 了解支持的认证方式。
3. 执行测试
3.1 运行API测试
使用测试脚本:
bash
scripts/test-api.py --config test-config.json --output results.json
4. 验证响应
4.1 HTTP状态码检查
参考 HTTP状态码 了解状态码含义。
4.2 响应格式验证
使用Schema验证脚本:
bash
scripts/validate-schema.py --response response.json --schema schema.json
5. 生成报告
使用报告模板生成结构化报告。
示例
示例1:测试GET请求
配置:
json
{
"name": "获取用户列表",
"base_url": "https://api.example.com/v1",
"endpoint": "/users",
"method": "GET",
"headers": {
"Authorization": "Bearer eyJhbGciOiJIUzI1NiIs..."
},
"expected": {
"status": 200
}
}
示例2:测试POST请求
配置:
json
{
"name": "创建用户",
"method": "POST",
"endpoint": "/users",
"body": {
"name": "测试用户",
"email": "test@example.com"
},
"expected": {
"status": 201
}
}
参考资源
-
10.4 编写参考文档
参考文档包含HTTP状态码说明、认证方法详解、测试模式指南等详细内容,这里限于篇幅不再完整展示。
10.5 编写核心脚本
创建
scripts/test-api.py:python#!/usr/bin/env python3 """API测试脚本""" import sys import json import time import requests def run_tests(config): """执行API测试""" results = [] base_url = config.get('base_url', '') for test in config.get('tests', []): result = { 'name': test.get('name', 'Unnamed'), 'status': 'unknown' } try: # 构建请求 url = f"{base_url}{test.get('endpoint', '')}" method = test.get('method', 'GET') headers = test.get('headers', {}) body = test.get('body') # 发送请求 start_time = time.time() response = requests.request( method=method, url=url, headers=headers, json=body, timeout=30 ) response_time = (time.time() - start_time) * 1000 # 验证结果 expected_status = test.get('expected_status') if expected_status and response.status_code == expected_status: result['status'] = 'passed' else: result['status'] = 'failed' result['error'] = f"状态码不匹配: 期望 {expected_status}, 实际 {response.status_code}" result['response_time'] = round(response_time, 2) result['status_code'] = response.status_code except Exception as e: result['status'] = 'failed' result['error'] = str(e) results.append(result) return results if __name__ == "__main__": # 简化的命令行接口 import argparse parser = argparse.ArgumentParser() parser.add_argument('--config', required=True) parser.add_argument('--output', required=True) args = parser.parse_args() with open(args.config, 'r') as f: config = json.load(f) results = run_tests(config) with open(args.output, 'w') as f: json.dump({'results': results}, f, indent=2) print(f"测试完成,结果保存到: {args.output}")
10.6 验证和测试
验证Skill结构并运行测试。
11. 验证与调试
11.1 使用skills-ref工具
安装:
bash
pip install skills-ref
验证Skill:
bash
skills-ref validate /path/to/your-skill
生成prompt XML:
bash
skills-ref to-prompt /path/to/skill1 /path/to/skill2
11.2 常见验证错误
错误1:name字段不匹配
错误:name字段'myskill'与目录名'my-skill'不匹配
解决:确保name字段与目录名完全一致
错误2:描述过短
警告:description字段过短,建议至少50个字符
解决:提供更详细的描述,包含关键词
错误3:非法字符
错误:name字段包含非法字符
解决:只使用小写字母、数字和连字符
11.3 调试技巧
- 检查文件编码:确保SKILL.md使用UTF-8编码
- 验证YAML格式:使用YAML验证器检查frontmatter格式
- 测试脚本独立运行:确保scripts/目录中的脚本可以独立运行
- 检查文件权限:在Linux/Mac上,确保脚本有执行权限
- 简化测试:从最简化的Skill开始测试,逐步添加功能
12. 在OpenCode中使用Skills
12.1 配置Skills目录
OpenCode支持通过配置文件指定Skills目录:
- 打开OpenCode配置文件
- 添加或修改skills配置项
- 重启OpenCode使配置生效
12.2 使用流程
- 创建或下载Skills:将Skills文件夹放入配置的Skills目录
- 启动OpenCode:自动扫描并加载所有Skills的元数据
- 自然语言激活:使用自然语言描述任务,OpenCode自动匹配并激活相关Skills
- 查看激活状态:在回复中体现相关的专业技能
- 提供反馈:如果Skill没有被正确激活,可以通过更明确的描述来引导
12.3 实际使用场景
场景1:代码审查
- 用户:"请帮我审查这个Python函数的质量"
- OpenCode:自动激活code-review Skill,执行复杂度分析、风格检查,生成审查报告
场景2:API测试
- 用户:"我想测试这个REST API的端点"
- OpenCode:自动激活api-testing Skill,指导用户配置测试,执行测试并生成报告
12.4 故障排除
- Skill未激活:检查描述字段是否包含相关关键词,尝试使用更明确的任务描述
- 脚本执行失败:检查脚本依赖项是否已安装,查看脚本权限设置
- 路径问题:确保Skills目录配置正确,文件路径使用相对路径
13. 集成到自定义Agent
13.1 集成方法
Filesystem-based Agents:
- 在计算机环境中运行,通过shell命令访问Skills
- 实现相对简单,适合有完整计算机环境的场景
Tool-based Agents:
- 通过特定工具实现访问Skills
- 实现相对复杂,但更灵活,适合Web应用或插件
13.2 XML格式示例
xml
<available_skills>
<skill>
<name>pdf-processing</name>
<description>从PDF文件中提取文本和表格...</description>
<location>/path/to/skills/pdf-processing/SKILL.md</location>
</skill>
</available_skills>
13.3 安全考虑
- 沙箱环境:在隔离环境中执行脚本
- 权限控制:限制脚本可以访问的资源和执行的操作
- 代码审查:审查scripts/目录中的代码
- 输入验证:验证所有用户输入
- 审计日志:记录所有脚本执行操作
14. 高级技巧
14.1 多Skill协作
复杂任务可能需要多个Skills协作完成:
- 清晰的职责分离
- 标准化的输出格式
- 明确的依赖关系
14.2 性能优化
- 精简元数据
- 延迟加载
- 缓存策略
- 脚本优化
- 并行执行
14.3 测试和CI/CD
- 单元测试
- 集成测试
- 自动验证
- 版本管理
15. 附录:参考资源
15.1 官方资源
- Agent Skills主页: https://agentskills.io
- GitHub仓库: https://github.com/agentskills/agentskills
- 规范文档: https://agentskills.io/specification
- 示例Skills: https://github.com/anthropics/skills
15.2 推荐的Skill示例
- 代码审查(code-review)
- API测试(api-testing)
- 文档生成(doc-generation)
- 数据处理(data-processing)
- Git操作(git-operations)
15.3 故障排除清单
Skill无法激活:
- 检查description字段是否包含相关关键词
- 验证name字段是否与目录名匹配
- 检查SKILL.md文件格式是否正确
脚本执行失败:
- 检查脚本依赖项是否已安装
- 验证脚本路径是否正确
- 检查脚本权限设置
15.4 社区和支持
- GitHub Issues: https://github.com/agentskills/agentskills/issues
- Discussions: 在GitHub Discussions中提问和分享经验
15.5 术语表
- Skill:包含SKILL.md文件和相关资源的文件夹
- Frontmatter:SKILL.md文件顶部的YAML元数据部分
- 渐进式披露:按需加载不同级别信息的上下文管理策略
- skills-ref:官方提供的参考库和CLI工具
--- 完 ---