Agent_Skills_完全教程「AI生成」

Agent Skills 完全教程

从零开始掌握AI智能体技能开发


在opencode中使用kimi2.5生成的skil教程。

目录

  1. [Agent Skills 简介](#Agent Skills 简介)
  2. [为什么需要Agent Skills](#为什么需要Agent Skills)
  3. 生态系统概览
  4. 核心概念与工作原理
  5. 快速开始
  6. [SKILL.md 完整规范](#SKILL.md 完整规范)
  7. 目录结构详解
  8. 编写最佳实践
  9. 实战:创建代码审查Skill
  10. 实战:创建API测试Skill
  11. 验证与调试
  12. 在OpenCode中使用Skills
  13. 集成到自定义Agent
  14. 高级技巧
  15. 附录:参考资源

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仓库

官方文档

社区贡献

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的namedescription字段。这让智能体知道有哪些技能可用,但不需要了解详细内容。

示例:

复制代码
Skill名称: pdf-processing
描述: 从PDF文件中提取文本和表格,填充表单,合并文档

第二层:指令加载(建议< 5000 tokens)

当智能体判断某个Skill与当前任务相关时,它会读取该Skill的完整SKILL.md文件内容,包括所有指令和说明。

第三层:资源按需加载

只有在实际执行过程中,才会根据需要加载scripts/references/assets/目录中的具体文件。

4.3 技能发现与激活流程

1. 发现阶段(Discovery)

  • 智能体启动时扫描配置的Skills目录
  • 解析每个Skill的SKILL.md文件,提取namedescription
  • 构建可用技能列表

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,您需要:

  1. 兼容的AI工具

    • OpenCode(本教程使用)
    • Claude Code
    • Cursor
    • 或其他支持Skills的工具
  2. 基本的文件操作能力

    • 能够创建和编辑文件夹和文件
    • 了解基本的Markdown和YAML语法
  3. 可选:Python环境

    • 如果要编写Python脚本,需要Python 3.7+

    • 安装skills-ref工具用于验证:

      bash 复制代码
      pip 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的核心文件,必须遵循以下格式:

  1. YAML Frontmatter(必需)

    • 位于文件开头
    • ---包围
    • 包含元数据字段
  2. 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的正文部分没有严格的结构要求,但建议包含以下章节:

推荐章节结构

  1. 标题(H1) - Skill的主要标题
  2. 何时使用 - 描述触发条件和使用场景
  3. 操作步骤 - 详细的执行步骤(可以使用编号列表)
  4. 示例 - 输入输出示例
  5. 注意事项 - 常见边界情况和警告
  6. 参考 - 相关文档链接或文件引用
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)

脚本编写规范

  1. 自包含性:脚本应该尽可能自包含,或清楚说明依赖项
  2. 错误处理:包含有用的错误消息
  3. 边界情况:优雅地处理边界情况
  4. 文档:在脚本开头包含注释说明用途和用法

示例

复制代码
my-skill/
├── SKILL.md
└── scripts/
    ├── analyze.py      # 数据分析脚本
    ├── cleanup.sh      # 清理脚本
    └── validate.js     # 验证脚本

7.3 可选目录:references/

references/目录包含额外的文档和参考资料,智能体在需要时可以读取这些文件。

位置skill-name/references/

用途

  • 详细的技术参考
  • 表单模板和结构化数据格式
  • 领域特定文档(如finance.mdlegal.md
  • 示例和最佳实践

常见文件

  • REFERENCE.md - 详细的技术参考文档
  • FORMS.md - 表单模板或结构化数据格式说明
  • EXAMPLES.md - 更多示例
  • 领域特定文件(如api-reference.mdstyle-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应具备以下功能:

  1. 分析代码复杂度
  2. 检查潜在bug
  3. 评估代码风格
  4. 生成审查报告

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行)

  • 分批审查,每次审查一个模块或类
  • 重点关注公共接口和高风险区域
  • 建议用户将大文件拆分成小模块

二进制文件

  • 跳过非文本文件(图片、编译后的代码等)
  • 记录跳过的文件列表

无法识别的语言

  • 进行通用代码质量检查(命名、结构、注释)
  • 询问用户是否需要特定的审查标准

缺少上下文

  • 如果无法理解代码意图,询问用户代码的目的
  • 查看相关的测试文件或文档

注意事项

  1. 保持建设性:以改进为目的,避免批评性语言
  2. 提供上下文:解释为什么某个做法不好,而不仅仅指出问题
  3. 优先级排序:帮助用户理解哪些是最重要的问题
  4. 考虑权衡:某些"问题"可能是合理的设计选择
  5. 关注安全:特别注意安全问题(注入、XSS、权限等)
  6. 尊重团队规范:如果已知团队有特定规范,优先应用

参考资源

  • 审查检查清单 - 详细的检查项目列表

  • 示例集合 - 常见问题的修复示例

  • 报告模板 - 报告格式模板

    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,可以手动检查:

  1. SKILL.md文件存在且格式正确
  2. name字段与目录名匹配
  3. description字段已填写
  4. scripts/目录中的脚本有执行权限(在Linux/Mac上)

9.8 测试Skill

在OpenCode中测试:

  1. 将code-review-skill目录复制到OpenCode的skills目录

  2. 启动OpenCode

  3. 输入测试指令:

    复制代码
    请帮我审查以下Python代码:
    
    def calculate(x, y):
        if x > 0:
            if y > 0:
                return x + y
        return 0
  4. OpenCode应该自动识别到code-review Skill并激活它

  5. 检查生成的审查报告是否符合预期


10. 实战:创建API测试Skill

10.1 需求分析

创建一个"API测试"Skill,帮助用户:

  1. 测试REST API端点
  2. 验证响应格式
  3. 检查状态码
  4. 生成测试报告
  5. 支持多种认证方式

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
  }
}

参考资源

  • HTTP状态码参考

  • 认证方法

  • 测试模式

    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 调试技巧

  1. 检查文件编码:确保SKILL.md使用UTF-8编码
  2. 验证YAML格式:使用YAML验证器检查frontmatter格式
  3. 测试脚本独立运行:确保scripts/目录中的脚本可以独立运行
  4. 检查文件权限:在Linux/Mac上,确保脚本有执行权限
  5. 简化测试:从最简化的Skill开始测试,逐步添加功能

12. 在OpenCode中使用Skills

12.1 配置Skills目录

OpenCode支持通过配置文件指定Skills目录:

  1. 打开OpenCode配置文件
  2. 添加或修改skills配置项
  3. 重启OpenCode使配置生效

12.2 使用流程

  1. 创建或下载Skills:将Skills文件夹放入配置的Skills目录
  2. 启动OpenCode:自动扫描并加载所有Skills的元数据
  3. 自然语言激活:使用自然语言描述任务,OpenCode自动匹配并激活相关Skills
  4. 查看激活状态:在回复中体现相关的专业技能
  5. 提供反馈:如果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 官方资源

15.2 推荐的Skill示例

  • 代码审查(code-review)
  • API测试(api-testing)
  • 文档生成(doc-generation)
  • 数据处理(data-processing)
  • Git操作(git-operations)

15.3 故障排除清单

Skill无法激活

  • 检查description字段是否包含相关关键词
  • 验证name字段是否与目录名匹配
  • 检查SKILL.md文件格式是否正确

脚本执行失败

  • 检查脚本依赖项是否已安装
  • 验证脚本路径是否正确
  • 检查脚本权限设置

15.4 社区和支持

15.5 术语表

  • Skill:包含SKILL.md文件和相关资源的文件夹
  • Frontmatter:SKILL.md文件顶部的YAML元数据部分
  • 渐进式披露:按需加载不同级别信息的上下文管理策略
  • skills-ref:官方提供的参考库和CLI工具

--- 完 ---

相关推荐
工程师老罗4 小时前
目标检测的常见数据集
人工智能·目标检测·计算机视觉
AI周红伟4 小时前
周红伟:数小时两度改名:爆火 AI 助手 Clawdbot 变身 OpenClaw中性
人工智能
大模型玩家七七4 小时前
证据不足 vs 证据冲突:哪个对模型更致命
数据库·人工智能·pytorch·深度学习·安全
zhangfeng11334 小时前
CSDN星图 支持大模型微调 trl axolotl Unsloth 趋动云 LLaMA-Factory Unsloth ms-swift 模型训练
服务器·人工智能·swift
风静如云4 小时前
Claude Code:Ubuntu设置中转
人工智能
Yeats_Liao4 小时前
压力测试实战:基于Locust的高并发场景稳定性验证
人工智能·深度学习·机器学习·华为·开源·压力测试
大模型任我行4 小时前
上海AI Lab:构建诊断型Agent守门员
人工智能·语言模型·自然语言处理·论文笔记
AndrewHZ4 小时前
【AI黑话日日新】什么是skills?
语言模型·大模型·llm·claude code·skills