[CoPaw 教程系列] #11: Copaw Custom Skills

CoPaw 功能:自定义 Skills 开发

CoPaw 的强大之处在于你可以创建自定义 Skills,扩展其能力。本文将详细介绍如何开发和部署自定义 Skills,从简单的配置型 Skills 到复杂的编程型 Skills。

自定义 Skills 概述

为什么需要自定义 Skills?

虽然 CoPaw 提供了丰富的内置 Skills,但实际场景中你可能需要:

  • 特定领域的专业知识
  • 与内部系统集成
  • 自定义的工作流程
  • 特殊的数据处理逻辑
  • 个性化的交互方式

自定义 Skills 的类型

1. 配置型 Skills

特点:

  • 只需编写 Markdown 文件
  • 定义能力和使用方法
  • 依赖 CoPaw 的内置工具

适用场景:

  • 领域知识库
  • 业务规则说明
  • 工作流程指导
  • 回复模板

2. 编程型 Skills

特点:

  • 需要编写代码
  • 可以调用外部 API
  • 自定义工具函数
  • 复杂的逻辑处理

适用场景:

  • 与第三方系统集成
  • 自定义数据处理
  • 特定的业务逻辑
  • 高性能计算

创建配置型 Skills

配置型 Skills 是最简单的自定义 Skills,只需要编写 SKILL.md

文件。

基本结构

---

name: my_skill

description: 我的自定义能力说明


Skill 标题

功能说明

详细描述这个 Skill 的功能...

使用方法

如何使用这个 Skill...

注意事项

使用时需要注意的事项...

创建步骤

1. 创建目录

cd ~/.copaw/customized_skills/

mkdir my_skill

cd my_skill

touch SKILL.md

2. 编写 SKILL.md

---

name: weather_query

description: 天气查询 Skill


天气查询

功能说明

这个 Skill 可以查询指定城市的天气信息。

使用方法

在对话中直接输入城市名称即可,例如:

  • 北京今天天气怎么样?
  • 查一下上海明天的天气
  • 深圳现在的气温是多少?

支持的城市

  • 北京
  • 上海
  • 深圳
  • 广州
  • 杭州
  • ...

注意事项

  • 只支持国内主要城市
  • 天气数据来源于公共 API,可能有延迟
  • 数据更新频率为每小时

3. 重启 CoPaw

# 停止 CoPaw

Ctrl+C

重新启动

copaw app

实战案例

案例 1:领域知识库

场景:

为 CoPaw 添加特定领域的专业知识。

SKILL.md

---

name: blockchain_knowledge

description: 区块链技术知识库


区块链技术知识库

核心概念

区块(Block)

区块是区块链的基本单位,包含:

  • 区块头:区块的元数据
  • 区块体:实际交易数据
  • 哈希值:区块的唯一标识
  • 时间戳:区块生成时间

链(Chain)

链是区块的有序连接:

  • 每个区块包含前一个区块的哈希
  • 形成不可篡改的链式结构
  • 任何修改都会影响后续所有区块

共识机制

  • PoW(工作量证明):如比特币
  • PoS(权益证明):如以太坊 2.0
  • DPoS(委托权益证明):如 EOS

常见问题

Q: 什么是去中心化?

A: 去中心化是指系统不依赖单一中心节点,数据分布在多个节点上。

Q: 什么是智能合约?

A: 智能合约是运行在区块链上的自动执行程序,当满足条件时自动执行。

Q: 区块链的安全来自哪里?

A: 来自密码学保证和分布式共识机制。

回复风格

  • 使用专业但易懂的语言
  • 提供具体的例子
  • 适当使用图示和类比
  • 避免过于技术化的术语

使用示例:

你:什么是区块链?

CoPaw:(调用 blockchain_knowledge Skill)

区块链是一种分布式数据库技术,由多个区块组成,每个区块包含交易数据和前一个区块的哈希值。

想象一个共享的笔记本,每个人都有一个副本。每当有人添加新的交易,所有人都会同步更新。一旦记录下来,就无法被篡改,因为任何修改都会破坏整个链的完整性。

核心特点:

  1. 去中心化:没有单一的控制中心
  2. 不可篡改:一旦记录就无法修改
  3. 透明公开:所有人都可以查看交易记录

案例 2:工作流程指导

场景:

为 CoPaw 添加特定的工作流程指导。

SKILL.md

---

name: code_review_workflow

description: 代码审查工作流程


代码审查工作流程

审查前准备

1. 理解背景

  • 阅读需求文档或问题描述
  • 了解修改的目的和范围
  • 查看相关的 issue 或 ticket

2. 准备环境

  • 拉取最新代码
  • 运行测试,确保代码可以正常工作
  • 查看依赖的变更

审查步骤

第一步:整体概览

  • 查看 commit message
  • 了解修改的文件和代码量
  • 快速浏览主要变更

第二步:代码审查

  1. 功能性
  • 代码是否实现了需求?
  • 是否有遗漏的功能?
  • 是否有过度实现?
  1. 代码质量
  • 代码是否易于理解?
  • 是否符合团队的代码规范?
  • 变量/函数命名是否清晰?
  1. 性能
  • 是否有明显的性能问题?
  • 是否有不必要的计算或 I/O?
  • 是否考虑了大数据量情况?
  1. 安全性
  • 是否有安全漏洞?
  • 是否正确处理用户输入?
  • 是否泄露敏感信息?

第三步:测试检查

  • 单元测试是否充分?
  • 集成测试是否覆盖?
  • 边界情况是否考虑?

第四步:文档检查

  • 是否更新了相关文档?
  • 代码注释是否充分?
  • API 文档是否完整?

常见问题

应该指出的问题

  1. 功能性缺陷
  2. 严重的代码质量问题
  3. 安全性问题
  4. 性能问题

不应该指出的问题

  1. 个人编码风格偏好(除非违反团队规范)
  2. 可以优化的细节(不影响功能)
  3. 可以重构的地方(不在本次修改范围内)

回复风格

  • 建设性:指出问题并提供改进建议
  • 尊重:尊重作者的工作
  • 具体:提供具体的示例和代码
  • 优先级:指出问题的重要性(必须修复/建议修复/可选)

使用示例:

你:帮我看一下这段代码的问题

[代码内容]

CoPaw:(调用 code_review_workflow Skill)

我来按照代码审查流程检查这段代码...

代码审查报告

整体概览

  • 修改范围:2 个文件,50 行代码
  • 主要变更:添加用户登录功能

代码审查结果

功能性
  • 代码实现了登录需求
  • 功能完整
⚠️ 代码质量
  1. [必须修复] 缺少错误处理

python

# 当前代码

user = db.query_user(username)

password = user.password # 如果 user 为 None 会报错


建议修改:

python

user = db.query_user(username)

if user is None:

return error("用户不存在")

password = user.password


  1. [建议修复] 密码应该加密存储

python

# 建议使用 bcrypt 或类似库

hashed_password = bcrypt.hash(password)

性能
  • 没有明显的性能问题
⚠️ 安全性
  1. [必须修复] SQL 注入风险

python

# 当前代码

query = f"SELECT

FROM users WHERE username = '{username}'"


建议使用参数化查询:

python

query = "SELECT

FROM users WHERE username = %s"

cursor.execute(query, (username,))


测试检查

  • ⚠️ 缺少单元测试
  • 建议添加以下测试用例:
  • 用户名不存在的情况
  • 密码错误的情况
  • 登录成功的情况

文档检查

  • ✅ 已更新 API 文档
  • ⚠️ 缺少代码注释

总结

必须修复:
  1. 添加用户不存在检查
  2. 密码加密存储
  3. 修复 SQL 注入风险
建议修复:
  1. 添加单元测试
  2. 添加代码注释
评分:

7/10

创建编程型 Skills

编程型 Skills 允许你编写自定义代码,扩展 CoPaw 的能力。

基本结构

my_skill/

├── SKILL.md # Skill 说明文件

├── __init__.py # Python 包文件

├── tools.py # 自定义工具函数

└── requirements.txt # 依赖列表

创建步骤

1. 创建目录结构

cd ~/.copaw/customized_skills/

mkdir my_custom_skill

cd my_custom_skill

touch SKILL.md

touch __init__.py

touch tools.py

touch requirements.txt

2. 编写 SKILL.md

---

name: my_custom_skill

description: 我的自定义编程型 Skill


我的自定义 Skill

功能说明

这个 Skill 提供了自定义的功能。

使用方法

直接使用,CoPaw 会自动调用相应的工具函数。

可用工具

  • my_function - 说明功能

注意事项

使用时注意...

3. 编写 tools.py

from typing import Optional, Dict, Any

def my_function(param1: str, param2: Optional[int] = None) -> Dict[str, Any]:

"""

自定义工具函数

Args:

param1: 参数1说明

param2: 参数2说明(可选)

Returns:

返回结果

"""

# 实现你的逻辑

result = {

"status": "success",

"data": f"处理结果:{param1}"

}

return result

4. 编写 requirements.txt

requests>=2.28.0

numpy>=1.24.0

5. 重启 CoPaw

# 停止 CoPaw

Ctrl+C

重新启动

copaw app

实战案例

案例 1:调用外部 API

场景:

创建一个调用天气 API 的 Skill。

SKILL.md

---

name: weather_api

description: 天气 API 调用


天气 API

功能说明

调用外部天气 API 获取实时天气信息。

使用方法

  • 查询北京的天气
  • 上海今天天气怎么样
  • 明天的天气预报

可用工具

  • get_weather - 获取天气信息

注意事项

  • 需要配置 API Key
  • 数据更新频率有限制

tools.py

import requests

from typing import Dict, Any, Optional

配置 API Key

API_KEY = "your-api-key-here"

API_URL = "http://api.weather.com/v1/current"

def get_weather(city: str, days: int = 1) -> Dict[str, Any]:

"""

获取天气信息

Args:

city: 城市名称

days: 查询天数(1-7)

Returns:

天气信息

"""

try:

# 构建请求参数

params = {

"city": city,

"days": min(days, 7), # 最多 7 天

"key": API_KEY

}

# 发送请求

response = requests.get(API_URL, params=params)

response.raise_for_status()

# 解析响应

data = response.json()

# 格式化结果

result = {

"status": "success",

"city": city,

"current": {

"temperature": data["current"]["temp"],

"condition": data["current"]["text"],

"humidity": data["current"]["humidity"]

},

"forecast": [

{

"date": day["date"],

"temperature_max": day["temp_max"],

"temperature_min": day["temp_min"],

"condition": day["text"]

}

for day in data.get("forecast", [])[:days]

]

}

return result

except requests.RequestException as e:

return {

"status": "error",

"message": f"请求失败:{str(e)}"

}

except Exception as e:

return {

"status": "error",

"message": f"处理失败:{str(e)}"

}

requirements.txt

requests>=2.28.0

使用示例:

你:查一下北京的天气

CoPaw:(调用 get_weather 函数)

北京天气

当前天气

  • 气温:18°C
  • 天气:晴
  • 湿度:45%

未来 3 天预报

明天(3月16日)
  • 最高气温:22°C
  • 最低气温:10°C
  • 天气:多云
后天(3月17日)
  • 最高气温:24°C
  • 最低气温:12°C
  • 天气:晴
3月18日
  • 最高气温:20°C
  • 最低气温:11°C
  • 天气:阴

案例 2:数据处理

场景:

创建一个处理 CSV 文件的 Skill。

SKILL.md

---

name: csv_processor

description: CSV 文件处理


CSV 文件处理

功能说明

处理 CSV 文件,包括读取、分析、转换等。

使用方法

  • 读取 data.csv 文件
  • 分析这个 CSV 文件
  • 把 CSV 转换成 JSON

可用工具

  • read_csv - 读取 CSV 文件
  • analyze_csv - 分析 CSV 数据
  • convert_csv_to_json - 转换 CSV 为 JSON

注意事项

  • 支持 UTF-8 编码
  • 文件大小限制为 100MB

tools.py

import csv

import json

from typing import Dict, Any, List, Optional

from pathlib import Path

def read_csv(file_path: str, delimiter: str = ",") -> List[Dict[str, str]]:

"""

读取 CSV 文件

Args:

file_path: 文件路径

delimiter: 分隔符(默认为逗号)

Returns:

数据列表

"""

try:

with open(file_path, 'r', encoding='utf-8') as f:

reader = csv.DictReader(f, delimiter=delimiter)

data = [row for row in reader]

return data

except FileNotFoundError:

return []

except Exception as e:

raise Exception(f"读取文件失败:{str(e)}")

def analyze_csv(file_path: str) -> Dict[str, Any]:

"""

分析 CSV 文件

Args:

file_path: 文件路径

Returns:

分析结果

"""

data = read_csv(file_path)

if not data:

return {"error": "文件为空或读取失败"}

# 获取列名

columns = list(data[0].keys())

# 统计行数和列数

row_count = len(data)

col_count = len(columns)

# 分析每列的数据类型

column_types = {}

for col in columns:

values = [row[col] for row in data if col in row]

column_types[col] = _infer_column_type(values)

# 检查缺失值

missing_values = {}

for col in columns:

missing_count = sum(1 for row in data if col not in row or not row[col])

missing_values[col] = {

"count": missing_count,

"percentage": (missing_count / row_count * 100) if row_count > 0 else 0

}

return {

"file_path": file_path,

"row_count": row_count,

"column_count": col_count,

"columns": columns,

"column_types": column_types,

"missing_values": missing_values,

"sample_data": data[:5] # 前 5 行样本

}

def convert_csv_to_json(csv_path: str, json_path: Optional[str] = None) -> Dict[str, Any]:

"""

转换 CSV 为 JSON

Args:

csv_path: CSV 文件路径

json_path: JSON 文件路径(可选,默认为同目录同名)

Returns:

转换结果

"""

data = read_csv(csv_path)

if not data:

return {"error": "CSV 文件为空或读取失败"}

# 确定 JSON 文件路径

if json_path is None:

csv_path_obj = Path(csv_path)

json_path = str(csv_path_obj.with_suffix('.json'))

# 写入 JSON

try:

with open(json_path, 'w', encoding='utf-8') as f:

json.dump(data, f, ensure_ascii=False, indent=2)

return {

"status": "success",

"csv_path": csv_path,

"json_path": json_path,

"record_count": len(data)

}

except Exception as e:

return {

"status": "error",

"message": f"写入 JSON 失败:{str(e)}"

}

def _infer_column_type(values: List[str]) -> str:

"""

推断列的数据类型

Args:

values: 值列表

Returns:

数据类型

"""

if not values:

return "unknown"

# 检查是否为整数

try:

int_values = [int(v) for v in values if v]

if len(int_values) == len([v for v in values if v]):

return "integer"

except ValueError:

pass

# 检查是否为浮点数

try:

float_values = [float(v) for v in values if v]

if len(float_values) == len([v for v in values if v]):

return "float"

except ValueError:

pass

# 检查是否为布尔值

bool_values = [v.lower() for v in values if v]

if all(v in ['true', 'false', 'yes', 'no', '1', '0'] for v in bool_values):

return "boolean"

# 默认为字符串

return "string"

requirements.txt

# 无需额外依赖,使用标准库

使用示例:

你:分析一下 sales.csv 这个文件

CoPaw:(调用 analyze_csv 函数)

CSV 文件分析报告

文件信息

  • 文件路径:sales.csv
  • 行数:150
  • 列数:5

列信息

| 列名 | 数据类型 | 缺失值 | 缺失率 |

|------|---------|--------|--------|

| 日期 | string | 0 | 0% |

| 产品 | string | 0 | 0% |

| 数量 | integer | 0 | 0% |

| 单价 | float | 0 | 0% |

| 销售额 | float | 0 | 0% |

数据质量

  • ✅ 无缺失值
  • ✅ 数据类型正确
  • ✅ 数据完整性良好

样本数据(前 5 行)

| 日期 | 产品 | 数量 | 单价 | 销售额 |

|------|------|------|------|--------|

| 2024-03-01 | 产品A | 10 | 100 | 1000 |

| 2024-03-01 | 产品B | 5 | 200 | 1000 |

| 2024-03-02 | 产品A | 8 | 100 | 800 |

| 2024-03-02 | 产品C | 3 | 300 | 900 |

| 2024-03-03 | 产品B | 6 | 200 | 1200 |

建议

数据质量良好,可以直接进行分析和可视化。

Skills 最佳实践

1. 命名规范

  • 使用小写字母和下划线:my_skill 而不是 MySkill
  • 名称应该简洁且具有描述性
  • 避免与内置 Skill 冲突

2. 文档完整

SKILL.md

中提供:

  • 清晰的功能说明
  • 详细的使用方法
  • 可用工具列表
  • 注意事项和限制

3. 错误处理

  • 合理处理异常
  • 提供有意义的错误信息
  • 记录日志便于调试

4. 性能优化

  • 避免重复计算
  • 合理使用缓存
  • 注意资源消耗

5. 安全考虑

  • 不在代码中硬编码敏感信息
  • 验证输入参数
  • 限制资源使用

6. 测试覆盖

  • 编写单元测试
  • 测试边界情况
  • 集成测试

常见问题

Q1: 自定义 Skill 加载失败?

A: 检查:

  • SKILL.md 文件是否存在且格式正确
  • 目录结构是否正确
  • 依赖是否安装
  • CoPaw 是否重启

Q2: 如何调试自定义 Skill?

A:

  1. 检查 CoPaw 的日志
  2. 在代码中添加日志输出
  3. 使用 print 输出调试信息
  4. 检查返回值格式

Q3: 自定义 Skill 可以调用其他 Skill 吗?

A: 可以。但要注意循环依赖,建议保持 Skill 的独立性。

Q4: 如何分享自定义 Skill?

A:

  1. 将 Skill 上传到 GitHub
  2. 按照规范编写文档
  3. 在社区分享 Skill URL
  4. 提交到 Skills Hub

Q5: 如何更新自定义 Skill?

A:

  1. 直接编辑文件
  2. 或删除后重新创建
  3. 重启 CoPaw 使更改生效

下一步

现在你已经了解了如何创建自定义 Skills。接下来建议:

  1. 阅读下一篇:CoPaw 功能:MCP 模型上下文协议 - 学习 MCP 的使用
  2. 创建你的第一个 Skill:从简单的配置型 Skill 开始
  3. 探索编程型 Skills:尝试编写自定义工具函数
  4. 分享你的 Skills:与社区分享你的创建

总结

自定义 Skills 让 CoPaw 的能力无限扩展:

配置型 Skills

- 简单易用,无需编程

编程型 Skills

- 强大灵活,支持自定义逻辑

工具函数

- 调用外部 API 和系统

文档驱动

- 清晰的说明和使用方法

社区共享

- 分享和发现更多 Skills

通过自定义 Skills,你可以让 CoPaw 适应任何场景和需求。


相关资源

  • CoPaw 官方文档:https://copaw.agentscope.io/
  • CoPaw Skills 文档:https://copaw.agentscope.io/docs/skills
  • anthropics/skills:https://github.com/anthropics/skills
  • Skills Hub:https://skills.sh/

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注