跳到主要内容
Agent Skills 完全指南:从零开发智能体技能 | 极客日志
Python AI
Agent Skills 完全指南:从零开发智能体技能 Agent Skills 是 Anthropic 推出的开源格式,用于扩展 AI 智能体能力。本文详解其核心概念、SKILL.md 规范及目录结构,通过代码审查和 API 测试实战案例,展示如何编写脚本、管理上下文并集成到自定义 Agent 中。涵盖环境准备、最佳实践、验证调试等全流程,帮助开发者构建可复用的智能体技能包。
Agent Skills 完全教程
从零开始掌握 AI 智能体技能开发
Agent Skills 是由 Anthropic 开发并开源的一种轻量级、开放式格式,专门用于扩展 AI 智能体的能力。它是一种标准化的方式,让开发者可以将专业知识、工作流程和特定领域的操作封装成可复用的'技能包'。简单来说,一个 Skill 就是一个包含指令、脚本和资源的文件夹,AI 智能体可以按需加载和使用这些资源来完成特定任务。
核心特点
Agent Skills 具有以下几个核心特点:
1. 简单开放
使用纯文本格式(Markdown + YAML)
无需复杂的配置或专有工具
完全开源,社区驱动发展
2. 一次编写,到处使用
编写好的 Skill 可以在多个兼容的 AI 工具中使用
支持 20+ 主流 AI 开发工具
跨平台、跨产品复用
3. 渐进式披露
智能体只在需要时加载相关技能
有效管理上下文窗口,避免信息过载
保持响应速度和准确性
4. 自文档化
SKILL.md 文件本身就是文档
易于审计、理解和改进
便于团队协作和知识共享
典型使用场景
领域专业知识
将法律审查流程、数据分析管道、医疗诊断指南等专业领域知识打包成可复用的技能。
新能力扩展
赋予智能体新能力,如创建演示文稿、构建 MCP 服务器、分析复杂数据集等。
可重复工作流
将多步骤任务转化为一致且可审计的工作流程,确保每次执行都遵循最佳实践。
组织知识管理
将企业、团队或个人的专业知识以可移植、版本控制的方式保存和共享。
为什么需要 Agent Skills
当前 AI 智能体的痛点
虽然 AI 智能体的能力越来越强,但在实际工作中常常面临以下问题:
1. 缺乏上下文
智能体往往缺少完成任务所需的领域知识和特定上下文。例如,当要求 AI 审查代码时,它可能不知道团队的代码规范;当要求 AI 处理 PDF 时,它可能不清楚具体的提取需求。
2. 重复工作
每次遇到类似任务都需要重新解释需求、提供背景信息,效率低下。
3. 一致性问题
不同时间、不同情境下,AI 对同一类任务的处理方式可能不一致,难以保证质量。
4. 知识孤岛
团队成员的个人经验和最佳实践难以沉淀和共享。
Agent Skills 如何解决这些问题
1. 提供专业知识上下文
Skills 通过打包领域知识和工作流程,让智能体能够按需加载所需的专业知识。例如:
一个'代码审查'Skill 可以包含团队的代码规范、审查检查清单和最佳实践
一个'PDF 处理'Skill 可以包含文档提取的具体步骤和工具使用方法
2. 标准化工作流程
将经常重复的任务标准化,智能体只需激活相应的 Skill 即可按照既定流程执行,无需每次都详细说明。
3. 确保一致性和质量
通过预定义的指令和脚本,确保每次执行都遵循相同的质量标准和工作流程。
4. 知识沉淀和共享
将个人和团队的知识封装成 Skills,便于版本控制、分享和复用,避免知识流失。
Agent Skills 的优势总结
优势 说明 便携性 纯文件格式,易于编辑、版本控制和分享 可扩展性 从简单文本指令到复杂脚本和模板,灵活性高 可审计性 SKILL.md 本身就是文档,易于理解和审查 互操作性 同一 Skill 可在多个 AI 工具中使用 渐进加载 智能管理上下文,按需加载资源
生态系统概览
支持 Agent Skills 的主流工具 Agent Skills 已被业界广泛接受和支持,目前已有超过 20 个主流 AI 开发工具兼容此格式。以下是主要支持的工具列表:
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 编程工具
不同工具的使用方式 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 应用
社区和生态 社区贡献
Agent Skills 是开放标准,欢迎社区贡献。开发者可以:
提交新的 Skills 示例
改进规范和文档
开发支持 Skills 的新工具
分享使用经验和最佳实践
核心概念与工作原理
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
渐进式披露机制 Agent Skills 的核心设计原则是渐进式披露(Progressive Disclosure) ,这是一种高效管理上下文窗口的机制:
第一层:元数据加载(约 100 tokens)
在智能体启动时,系统只加载所有可用 Skill 的 name 和 description 字段。这让智能体知道有哪些技能可用,但不需要了解详细内容。
Skill 名称:pdf-processing
描述:从 PDF 文件中提取文本和表格,填充表单,合并文档
第二层:指令加载(建议 < 5000 tokens)
当智能体判断某个 Skill 与当前任务相关时,它会读取该 Skill 的完整 SKILL.md 文件内容,包括所有指令和说明。
第三层:资源按需加载
只有在实际执行过程中,才会根据需要加载 scripts/、references/ 或 assets/ 目录中的具体文件。
技能发现与激活流程
智能体启动时扫描配置的 Skills 目录
解析每个 Skill 的 SKILL.md 文件,提取 name 和 description
构建可用技能列表
用户输入任务描述
智能体根据任务内容匹配相关的 Skill 描述
确定哪些 Skill 可能有助于完成任务
智能体读取匹配 Skill 的完整 SKILL.md 内容
将指令加载到上下文中
准备执行
智能体按照 SKILL.md 中的指令执行任务
根据需要调用 scripts/ 目录中的脚本
查阅 references/ 目录中的文档
使用 assets/ 目录中的资源
SKILL.md 文件解析 SKILL.md 是 Skill 的核心文件,包含两部分内容:
Frontmatter(YAML 前置元数据)
位于文件顶部,用 --- 包围,包含 Skill 的元信息:
---
name: skill-name
description: 描述这个 Skill 的功能和使用场景
---
Body Content(Markdown 正文)
位于 frontmatter 之后,包含实际的操作指令、示例和说明。使用标准的 Markdown 格式编写,没有严格的结构要求。
快速开始
环境准备
兼容的 AI 工具
OpenCode(本教程使用)
Claude Code
Cursor
或其他支持 Skills 的工具
基本的文件操作能力
能够创建和编辑文件夹和文件
了解基本的 Markdown 和 YAML 语法
可选:Python 环境
如果要编写 Python 脚本,需要 Python 3.7+
创建第一个 Skill 让我们创建一个简单的'问候'Skill 来体验整个流程。
mkdir greeting-skill
cd greeting-skill
步骤 2:创建 SKILL.md 文件
创建 SKILL.md 文件,内容如下:
---
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:
skills-ref validate ./greeting-skill
步骤 4:在 OpenCode 中使用
将 Skill 文件夹放到 OpenCode 的 skills 目录中(通常在配置目录下)。然后在与 OpenCode 对话时,当你提到需要问候语时,它会自动激活此 Skill。
快速测试 OpenCode 应该能够识别到这个任务与 greeting Skill 相关,并激活该 Skill 来生成合适的问候语。
注意事项
命名规范 :Skill 名称只能使用小写字母、数字和连字符,不能以下划线或连字符开头/结尾
描述清晰 :描述字段对于 Skill 的激活至关重要,应该包含关键词帮助智能体识别何时使用该 Skill
保持简洁 :SKILL.md 文件建议不超过 500 行,详细内容可以放到 references/ 目录中
SKILL.md 完整规范
文件格式概述 SKILL.md 是 Agent Skills 的核心文件,必须遵循以下格式:
YAML Frontmatter (必需)
Markdown Body (内容部分)
位于 frontmatter 之后
使用标准 Markdown 格式
无严格结构要求
---
name: skill-name
description: Skill 的描述
license: Apache-2.0
compatibility: 兼容性说明
metadata:
author: your-name
version: "1.0"
---
内容...
内容...
Frontmatter 字段详解
name(必需)
长度:1-64 个字符
字符:仅允许小写字母(a-z)、数字和连字符(-)
不能以连字符开头或结尾
不能包含连续的连字符(--)
必须与父目录名称匹配
name: pdf-processing
name: code-review
name: data-analysis
name: api-testing-v2
name: PDF-Processing
name: -pdf
name: pdf--processing
name: pdf_processing
description(必需)
长度:1-1024 个字符
不能为空
应描述 Skill 做什么以及何时使用它
包含具体的功能描述
包含使用场景和触发条件
包含相关关键词,帮助智能体识别何时使用该 Skill
description: 从 PDF 文件中提取文本和表格,填充 PDF 表单,合并多个 PDF 文档。当处理 PDF 文件或用户提到 PDF、表单、文档提取时使用。
license(可选)
可以是许可证名称(如 Apache-2.0、MIT 等)
也可以引用捆绑的许可证文件
建议保持简短
license: Apache-2.0
license: MIT
license: Proprietary. LICENSE.txt 中有完整条款
compatibility(可选)
长度:1-500 个字符(如果提供)
只在 Skill 有特定环境要求时使用
可以指示目标产品、所需系统包、网络访问需求等
compatibility: 专为 Claude Code(或类似产品)设计
compatibility: 需要 git、docker、jq 和网络访问
metadata(可选)
键和值都必须是字符串
客户端可以使用此字段存储规范未定义的属性
建议使用唯一的键名以避免冲突
metadata:
author: example-org
version:"1.0"
category: data-processing
allowed-tools(可选) 描述 :预先批准的工具列表,Skill 可以使用这些工具
空格分隔的工具列表
实验性功能 ,不同智能体实现的支持程度可能不同
allowed-tools: Bash(git:*) Bash(jq:*) Read
Markdown 正文规范
内容结构 SKILL.md 的正文部分没有严格的结构要求,但建议包含以下章节:
标题(H1) - Skill 的主要标题
何时使用 - 描述触发条件和使用场景
操作步骤 - 详细的执行步骤(可以使用编号列表)
示例 - 输入输出示例
注意事项 - 常见边界情况和警告
参考 - 相关文档链接或文件引用
编写最佳实践
使用 # 表示主标题
使用 ## 表示主要章节
使用 ### 表示子章节
最多使用四级标题(####)
使用编号列表(1. 2. 3.)表示步骤
使用无序列表(- 或 *)表示要点
使用表格展示对比信息
包含输入示例
包含输出示例
包含代码示例(如果适用)
使用相对路径引用 scripts/、references/、assets/ 中的文件
格式:[描述](路径) 或直接写路径
详细技术信息请参考 [参考文档 ](references/REFERENCE.md )。
执行分析脚本:
```bash
scripts/extract.py --input data.csv
##### 文件引用规范
当引用 Skill 内的其他文件时:
**正确做法** :
- 使用相对路径从 SKILL.md 根目录开始
- 保持引用层级简单(建议最多一级)
- 使用清晰的链接描述
```markdown
查看 [技术参考](references/TECHNICAL.md)
运行脚本:scripts/process.sh
使用模板:assets/template.docx
不要使用绝对路径
避免深度嵌套的引用链
不要引用 Skill 外部的文件
命名和验证规则总结 规则 要求 目录名 必须与 name 字段完全匹配 文件名 必须大写为 SKILL.md name 字段 小写、数字、连字符,1-64 字符 description 字段 1-1024 字符,非空 文件编码 UTF-8 YAML 格式 标准 YAML 语法
目录结构详解
必需文件:SKILL.md 每个 Skill 必须包含一个 SKILL.md 文件,位于 Skill 目录的根目录。这是 Skill 的核心定义文件,包含所有元数据和指令。
YAML frontmatter(元数据)
Markdown 正文(指令和说明)
可选目录:scripts/ scripts/ 目录包含可执行代码,智能体可以运行这些脚本来完成特定任务。
数据处理脚本
自动化任务脚本
辅助工具脚本
集成脚本
支持的语言 :
语言支持取决于智能体实现。常见的支持语言包括:
Python(.py)
Bash/Shell(.sh)
JavaScript/Node.js(.js)
Ruby(.rb)
自包含性 :脚本应该尽可能自包含,或清楚说明依赖项
错误处理 :包含有用的错误消息
边界情况 :优雅地处理边界情况
文档 :在脚本开头包含注释说明用途和用法
my -skill/
├── SKILL.md
└── scripts/
├── analyze.py
├── cleanup.sh
└── validate.js
可选目录: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
├── STYLE-GUIDE.md
└── examples/
├── example-1 .md
└── example-2 .md
可选目录:assets/ 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
完整目录结构示例 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
目录结构最佳实践 1. 从简单开始
不需要一开始就创建所有目录。可以从简单的 SKILL.md 开始,然后根据需要添加 scripts/、references/ 和 assets/。
只有当脚本、参考资料或资源文件较多时,才创建相应的子目录
如果只有少数几个文件,可以直接放在 scripts/ 根目录
使用描述性的文件名
使用连字符分隔单词(kebab-case)
使用小写字母
将大的 SKILL.md 拆分成 references/ 中的多个小文件
每个脚本专注于一个具体任务
不同类型的资源放在不同子目录中
编写最佳实践
上下文管理策略
第一层(元数据) :只包含最基本的信息(约 100 tokens)
name 和 description 字段
让智能体知道何时使用该 Skill
第二层(指令) :包含完整的操作指南(建议 < 5000 tokens)
第三层(资源) :按需加载(无限制)
只有在实际需要时才加载 scripts/、references/ 中的文件
保持主文件精简
SKILL.md 建议不超过 500 行
如果内容超过 5000 tokens,考虑拆分到 references/ 目录
保持主文件专注于核心流程
3. 分块加载
将详细内容放在 references/ 目录中,智能体只在需要时读取:
# 主 SKILL.md
## 详细说明
对于复杂的场景,请参考 [详细指南 ](references/DETAILED.md )。
## API 参考
完整的 API 文档见 [API 参考 ](references/API.md )。
描述字段优化 description 字段是 Skill 的'门面',决定了智能体是否会在适当的时候激活该 Skill。
1. 包含关键词
在描述中包含可能被用户提到的关键词:
description: 从 PDF 文件中提取文本和表格,填充 PDF 表单,合并多个 PDF 文档。当处理 PDF 文件或用户提到 PDF、表单、文档提取、PDF 转换、PDF 合并时使用。
description: 帮助处理 PDF。
2. 明确使用场景
清楚地说明何时应该使用该 Skill:
description: 执行代码审查,检查代码质量、潜在 bug、安全问题和风格一致性。当用户要求审查代码、检查代码质量、进行代码评审或提到 pull request 审查时使用。
3. 避免过度宽泛
描述过于宽泛会导致 Skill 被错误激活:
description: 帮助编程和开发。
description: 分析 Python 代码的性能瓶颈,提供优化建议。当用户提到 Python 性能问题、代码优化或慢查询时使用。
指令编写技巧 ## 如何处理请求
1. **分析请求**
- 理解用户的核心需求
- 识别关键信息和约束条件
2. **验证输入**
- 检查输入数据的完整性
- 确保数据格式正确
3. **执行处理**
- 应用适当的处理逻辑
- 记录中间步骤
4. **生成输出**
- 格式化结果
- 提供清晰的解释
## 示例
**输入** :
需要提取 PDF 中的表格数据
**处理步骤** :
1. 使用 pdfplumber 库打开 PDF 文件
2. 识别包含表格的页面
3. 提取表格数据到 DataFrame
**输出** :
```csv
姓名,年龄,职位
张三,28,工程师
李四,32,设计师
**3. 处理边界情况**
明确说明常见边界情况的处理方式:
```markdown
## 边界情况处理
**空文件**:
- 如果输入文件为空,返回空结果并说明原因
- 不要抛出异常
**格式错误**:
- 如果数据格式不正确,尝试自动修复
- 如果无法修复,返回详细的错误信息
**大文件**:
- 对于超过 10MB 的文件,分批处理
- 显示进度信息
4. 使用决策树
对于复杂逻辑,使用决策树或流程图:
## 决策流程
用户请求
↓
是否包含代码?
↓ 是
检查代码语言
↓
Python? → 使用 Python 分析脚本
JavaScript? → 使用 ESLint 检查
其他?→ 提供通用审查
↓
生成报告
脚本编写规范 1. 自包含性
脚本应该尽可能自包含,或在开头说明依赖项:
"""代码复杂度分析脚本
依赖项:
- 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. 参数验证
验证输入参数并提供有用的错误消息:
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 块处理可能的错误:
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),便于智能体解析:
import json
def output_result (data ):
"""输出 JSON 格式的结果"""
print (json.dumps(data, ensure_ascii=False , indent=2 ))
版本控制和维护 1. 版本号管理
在 metadata 中包含版本号:
metadata:
version:"1.0"
last-updated:"2024-01-15"
2. 变更日志
在 SKILL.md 末尾添加变更日志章节:
## 变更日志
### v1.1 (2024-01-20)
- 添加了对 JavaScript 代码的支持
- 优化了性能分析算法
### v1.0 (2024-01-15)
- 初始版本
- 支持 Python 代码审查
3. Git 集成
将 Skills 放在 Git 仓库中进行版本控制:
mkdir my-skills
cd my-skills
git init
git add code-review-skill/
git commit -m "添加代码审查 Skill v1.0"
实战:创建代码审查 Skill
需求分析 我们要创建一个实用的'代码审查'Skill,帮助智能体进行代码质量检查。该 Skill 应具备以下功能:
分析代码复杂度
检查潜在 bug
评估代码风格
生成审查报告
创建 Skill 目录结构 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
编写 SKILL.md ---
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) :会导致系统崩溃、数据丢失或安全漏洞的问题
严重 (Major) :严重影响功能或性能的问题
警告 (Minor) :不影响功能但影响代码质量的问题
建议 (Info) :改进建议,非必需但有益
示例
示例 1:Python 代码审查 def calculate_total (items ):
total = 0
for i in range (len (items)):
total = total + items[i]['price' ] * items[i]['quantity' ]
return total
位置:第 3 行
描述:使用 range(len(items)) 不如直接遍历列表清晰
建议:改为 for item in items:
修复后:
def calculate_total (items ):
total = 0
for item in items:
total = total + item['price' ] * item['quantity' ]
return total
位置:第 2-5 行
描述:可以使用 sum() 和生成器表达式简化代码
建议:考虑使用 return sum(item['price'] * item['quantity'] for item in items)
示例 2:JavaScript 代码审查 function getUserData (id ){
fetch ('/api/users/' + id).then (res => res.json ()).then (data => {
console .log (data);
return data;
});
}
位置:第 2 行
描述:fetch 调用没有.catch() 处理错误,也没有返回 Promise,调用者无法处理错误
建议:添加错误处理并返回 Promise
修复后:
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;
});
}
边界情况处理
分批审查,每次审查一个模块或类
重点关注公共接口和高风险区域
建议用户将大文件拆分成小模块
跳过非文本文件(图片、编译后的代码等)
记录跳过的文件列表
进行通用代码质量检查(命名、结构、注释)
询问用户是否需要特定的审查标准
如果无法理解代码意图,询问用户代码的目的
查看相关的测试文件或文档
注意事项
保持建设性 :以改进为目的,避免批评性语言
提供上下文 :解释为什么某个做法不好,而不仅仅指出问题
优先级排序 :帮助用户理解哪些是最重要的问题
考虑权衡 :某些'问题'可能是合理的设计选择
关注安全 :特别注意安全问题(注入、XSS、权限等)
尊重团队规范 :如果已知团队有特定规范,优先应用
参考资源
创建 `scripts/analyze.py`:
```python
"""代码分析脚本
依赖项:
- 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" : "存在尾随空格"
})
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()
编写参考文档 创建 references/CHECKLIST.md:
# 代码审查检查清单
## 通用检查项
### 代码质量
- [ ] 函数/方法是否单一职责?
- [ ] 函数长度是否超过 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:
# 常见问题修复示例
## Python 示例
### 问题 1:使用 range(len()) 遍历列表
**问题代码** :
```python
def process_items(items):
for i in range(len(items)):
print(items[i])
def process_items (items ):
for item in items:
print (item)
def process_items (items ):
for i, item in enumerate (items):
print (f"{i} : {item} " )
问题 2:可变默认参数 def append_item (item, items=[] ):
items.append(item)
return items
def append_item (item, items=None ):
if items is None :
items = []
items.append(item)
return items
问题 3:未处理文件关闭 def read_file (path ):
f = open (path, 'r' )
content = f.read()
f.close()
return content
def read_file (path ):
with open (path, 'r' ) as f:
return f.read()
JavaScript 示例
问题 1:使用 == 而不是 ===
问题 2:未处理 Promise 错误 fetch ('/api/data' ).then (res => res.json ()).then (data => console .log (data));
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:回调地狱 getData (function (a ){
getMoreData (a,function (b ){
getMoreData (b,function (c ){
console .log (c);
});
});
});
修复后(使用 Promise/async-await) :
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:未关闭资源 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;
}
public String readFile (String path) throws IOException{
try (BufferedReader reader = new BufferedReader (new FileReader (path))){
return reader.lines().collect(Collectors.joining("\n" ));
}
}
问题 2:空指针风险 public void processUser (User user) {
String name = user.getName().toUpperCase();
System.out.println(name);
}
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);
}
public void processUser (User user) {
Optional.ofNullable(user).map(User::getName).map(String::toUpperCase).ifPresent(System.out::println);
}
#
创建 `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}
验证 Skill cd code-review-skill
skills-ref validate .
如果没有安装 skills-ref,可以手动检查:
SKILL.md 文件存在且格式正确
name 字段与目录名匹配
description 字段已填写
scripts/ 目录中的脚本有执行权限(在 Linux/Mac 上)
测试 Skill
将 code-review-skill 目录复制到 OpenCode 的 skills 目录
启动 OpenCode
OpenCode 应该自动识别到 code-review Skill 并激活它
检查生成的审查报告是否符合预期
请帮我审查以下 Python 代码:
def calculate(x, y):
if x > 0 :
if y > 0 :
return x + y
return 0
实战:创建 API 测试 Skill
需求分析
测试 REST API 端点
验证响应格式
检查状态码
生成测试报告
支持多种认证方式
创建目录结构 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
编写 SKILL.md ---
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": "[email protected] "
}
}
2.2 选择认证方式
3. 执行测试
3.1 运行 API 测试 scripts/test-api.py --config test-config.json --output results.json
4. 验证响应
4.1 HTTP 状态码检查
4.2 响应格式验证 scripts/validate-schema.py --response response.json --schema schema.json
5. 生成报告
示例
示例 1:测试 GET 请求 {
"name" : "获取用户列表" ,
"base_url" : "https://api.example.com/v1" ,
"endpoint" : "/users" ,
"method" : "GET" ,
"headers" : {
"Authorization" : "Bearer eyJhbGciOiJIUzI1NiIs..."
} ,
"expected" : {
"status" : 200
}
}
示例 2:测试 POST 请求 {
"name" : "创建用户" ,
"method" : "POST" ,
"endpoint" : "/users" ,
"body" : {
"name" : "测试用户" ,
"email" : "[email protected] "
} ,
"expected" : {
"status" : 201
}
}
参考资源
参考文档包含 HTTP 状态码说明、认证方法详解、测试模式指南等详细内容,这里限于篇幅不再完整展示。
创建 `scripts/test-api.py`:
```python
"""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} " )
验证和测试
验证与调试
使用 skills-ref 工具 skills-ref validate /path/to/your-skill
skills-ref to-prompt /path/to/skill1 /path/to/skill2
常见验证错误 错误:name 字段'myskill' 与目录名'my-skill' 不匹配
警告:description 字段过短,建议至少 50 个字符
调试技巧
检查文件编码 :确保 SKILL.md 使用 UTF-8 编码
验证 YAML 格式 :使用 YAML 验证器检查 frontmatter 格式
测试脚本独立运行 :确保 scripts/ 目录中的脚本可以独立运行
检查文件权限 :在 Linux/Mac 上,确保脚本有执行权限
简化测试 :从最简化的 Skill 开始测试,逐步添加功能
在 OpenCode 中使用 Skills
配置 Skills 目录 OpenCode 支持通过配置文件指定 Skills 目录:
打开 OpenCode 配置文件
添加或修改 skills 配置项
重启 OpenCode 使配置生效
使用流程
创建或下载 Skills :将 Skills 文件夹放入配置的 Skills 目录
启动 OpenCode :自动扫描并加载所有 Skills 的元数据
自然语言激活 :使用自然语言描述任务,OpenCode 自动匹配并激活相关 Skills
查看激活状态 :在回复中体现相关的专业技能
提供反馈 :如果 Skill 没有被正确激活,可以通过更明确的描述来引导
实际使用场景
用户:'请帮我审查这个 Python 函数的质量'
OpenCode:自动激活 code-review Skill,执行复杂度分析、风格检查,生成审查报告
用户:'我想测试这个 REST API 的端点'
OpenCode:自动激活 api-testing Skill,指导用户配置测试,执行测试并生成报告
故障排除
Skill 未激活 :检查描述字段是否包含相关关键词,尝试使用更明确的任务描述
脚本执行失败 :检查脚本依赖项是否已安装,查看脚本权限设置
路径问题 :确保 Skills 目录配置正确,文件路径使用相对路径
集成到自定义 Agent
集成方法
在计算机环境中运行,通过 shell 命令访问 Skills
实现相对简单,适合有完整计算机环境的场景
通过特定工具实现访问 Skills
实现相对复杂,但更灵活,适合 Web 应用或插件
XML 格式示例 <available_skills >
<skill >
<name > pdf-processing</name >
<description > 从 PDF 文件中提取文本和表格...</description >
<location > /path/to/skills/pdf-processing/SKILL.md</location >
</skill >
</available_skills >
安全考虑
沙箱环境 :在隔离环境中执行脚本
权限控制 :限制脚本可以访问的资源和执行的操作
代码审查 :审查 scripts/ 目录中的代码
输入验证 :验证所有用户输入
审计日志 :记录所有脚本执行操作
高级技巧
多 Skill 协作
性能优化
精简元数据
延迟加载
缓存策略
脚本优化
并行执行
测试和 CI/CD
附录:参考资源
官方资源
推荐的 Skill 示例
代码审查(code-review)
API 测试(api-testing)
文档生成(doc-generation)
数据处理(data-processing)
Git 操作(git-operations)
故障排除清单
检查 description 字段是否包含相关关键词
验证 name 字段是否与目录名匹配
检查 SKILL.md 文件格式是否正确
检查脚本依赖项是否已安装
验证脚本路径是否正确
检查脚本权限设置
社区和支持
术语表
Skill :包含 SKILL.md 文件和相关资源的文件夹
Frontmatter :SKILL.md 文件顶部的 YAML 元数据部分
渐进式披露 :按需加载不同级别信息的上下文管理策略
skills-ref :官方提供的参考库和 CLI 工具
相关免费在线工具 RSA密钥对生成器 生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
Mermaid 预览与可视化编辑 基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
curl 转代码 解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
Markdown转HTML 将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online