小白福音!手把手教你给 OpenClaw 写技能:从 0 到上线(附源码)

摘要: OpenClaw 的核心能力是技能扩展。今天从零开始,带你写一个能用的技能,上线就能跑。完整流程 + 源码分享。
关键词: OpenClaw、Agent 技能、技能开发、AI Agent、教程
标签: #AI Agent #OpenClaw #编程工具 #小白福音 #技能开发


开头钩子

“OpenClaw 很强,但怎么扩展自己的能力?”

“看到一个好想法,但现有技能不支持,怎么办?”

这是很多新手用户都会问的问题。

OpenClaw 的核心竞争力,不是它自带多少功能,而是你可以给它添加任意能力。 这个能力载体,就是"技能"(Skill)。

今天这篇文章,我会从零开始,带你写一个能用的 OpenClaw 技能。不是"Hello World"级别的演示,而是真正能解决实际问题的技能。

学完这篇,你就能:

  • 理解 OpenClaw 技能的基本结构
  • 独立开发一个简单的技能
  • 调试和发布自己的技能
  • 复用社区现有技能

完整源码已上传 GitHub,链接在文末。


一、技能是什么?

1.1 定义

在 OpenClaw 里,技能是一个可复用的能力模块。它告诉 Agent:“遇到这类任务,应该这样做”。

类比一下:

  • VS Code 的"插件"
  • Chrome 的"扩展程序"
  • 手机的"APP"

都是同一个思路:核心平台提供基础能力,具体功能由扩展提供

1.2 技能能做什么?

技能可以做很多事情,比如:

技能类型 功能示例
工具类 天气查询、股票查询、翻译
工作流类 自动发版、日志整理、报告生成
集成类 飞书集成、Jira 集成、GitHub 集成
分析类 代码审查、性能分析、安全扫描
生成类 文档生成、测试用例生成、SQL 生成

理论上,任何能用代码实现的能力,都可以写成技能。

1.3 技能的结构

一个典型的技能包含以下文件:

skill-name/
├── SKILL.md          # 技能说明文件(必须)
├── skill.py          # 技能实现代码(常见)
├── requirements.txt  # Python 依赖(如需要)
├── README.md         # 使用说明(推荐)
└── test/             # 测试文件(推荐)
    └── test_skill.py

核心是 SKILL.md,这是 OpenClaw 识别技能的入口。


二、前置准备

2.1 环境要求

项目 要求 验证命令
OpenClaw 已安装并可用 openclaw --version
Python 3.8+ python3 --version
Git 用于克隆技能 git --version
代码编辑器 VS Code / Cursor 等 -

2.2 确认技能目录

OpenClaw 的技能目录通常在:

~/.openclaw/workspace/skills/

你可以用以下命令确认:

ls ~/.openclaw/workspace/skills/

如果目录不存在,手动创建:

mkdir -p ~/.openclaw/workspace/skills/

2.3 参考现有技能(推荐)

最好的学习方式,是看别人怎么写。OpenClaw 自带一些技能,可以学习参考:

# 查看已安装的技能
ls ~/.openclaw/workspace/skills/

# 查看某个技能的结构
cat ~/.openclaw/workspace/skills/weather/SKILL.md

三、实战:开发一个"股票查询"技能

3.1 需求说明

我们要开发的技能:查询美股实时股价

功能:

  • 输入股票代码(如 AAPL、NVDA)
  • 输出实时价格、涨跌幅、成交量

数据来源: Yahoo Finance(免费、无需 API Key)

预期效果:

用户:查询 NVDA 的股价
Agent:NVDA 当前股价 $125.43,今日 +2.3%,成交量 4500 万股

3.2 第一步:创建技能目录

cd ~/.openclaw/workspace/skills/
mkdir stock-quote
cd stock-quote

3.3 第二步:创建 SKILL.md

SKILL.md 是技能的说明文件,告诉 Agent 这个技能是干什么的、什么时候用、怎么用。

touch SKILL.md

编辑内容:

# stock-quote - 美股实时股价查询

## 描述
查询美股上市公司的实时股价、涨跌幅、成交量等基本信息。

## 触发条件
当用户提到以下关键词时激活此技能:
- "查股价"、"股票价格"、"股价查询"
- 具体股票代码(如"AAPL 多少钱"、"看看 NVDA")
- "股票"、"美股"、"实时行情"

## 能力范围
- ✅ 查询实时股价
- ✅ 查询涨跌幅、成交量
- ✅ 查询市值、市盈率等基本面数据
- ❌ 不提供投资建议
- ❌ 不预测股价走势

## 使用方法
直接询问股票代码即可:
- "查询 AAPL 的股价"
- "NVDA 现在多少钱"
- "看看特斯拉的股票"

## 数据源
Yahoo Finance(免费公开数据)

## 注意事项
- 股价数据有 15 分钟延迟(免费层限制)
- 仅支持美股市场
- 非交易时段返回最新收盘价

关键点:

  • 描述要清晰,让 Agent 知道什么时候该用这个技能
  • 触发条件要具体,包含常见问法
  • 能力范围要明确,什么能做、什么不能做

3.4 第三步:实现核心逻辑

创建 skill.py

touch skill.py

编辑内容:

# stock-quote 技能实现
# 功能:查询美股实时股价

import requests

def get_stock_quote(symbol: str) -> dict:
    """
    获取美股实时股价
    
    Args:
        symbol: 股票代码(如 AAPL、NVDA)
    
    Returns:
        包含股价信息的字典
    """
    # Yahoo Finance API(通过 yfinance 库)
    # 这里用简化的 API 调用示例
    url = f"https://query1.finance.yahoo.com/v8/finance/chart/{symbol}"
    
    params = {
        'interval': '1d',
        'range': '1d'
    }
    
    try:
        response = requests.get(url, params=params, timeout=10)
        response.raise_for_status()
        data = response.json()
        
        # 解析数据
        result = data['chart']['result'][0]
        meta = result['meta']
        quote = meta.get('regularMarketPrice', 0)
        change = meta.get('regularMarketChange', 0)
        change_percent = meta.get('regularMarketChangePercent', 0)
        volume = meta.get('regularMarketVolume', 0)
        market_cap = meta.get('marketCap', 0)
        
        return {
            'symbol': symbol.upper(),
            'price': quote,
            'change': change,
            'change_percent': change_percent,
            'volume': volume,
            'market_cap': market_cap,
            'currency': 'USD',
            'status': 'success'
        }
        
    except Exception as e:
        return {
            'symbol': symbol.upper(),
            'status': 'error',
            'message': str(e)
        }

def format_quote_result(quote_data: dict) -> str:
    """
    格式化股价查询结果
    
    Args:
        quote_data: get_stock_quote 返回的数据
    
    Returns:
        格式化的文本结果
    """
    if quote_data['status'] == 'error':
        return f"❌ 查询失败:{quote_data.get('message', '未知错误')}"
    
    symbol = quote_data['symbol']
    price = quote_data['price']
    change = quote_data['change']
    change_percent = quote_data['change_percent']
    volume = quote_data['volume']
    
    # 格式化涨跌幅(带颜色符号)
    if change >= 0:
        change_str = f"+{change:.2f} (+{change_percent:.2f}%) 📈"
    else:
        change_str = f"{change:.2f} ({change_percent:.2f}%) 📉"
    
    # 格式化成交量
    if volume >= 1000000:
        volume_str = f"{volume / 1000000:.1f}M"
    else:
        volume_str = f"{volume / 1000:.1f}K"
    
    return f"""
📊 **{symbol} 实时行情**

💰 当前股价:${price:.2f}
📈 涨跌:{change_str}
📊 成交量:{volume_str}
💵 货币:USD

*数据来源于 Yahoo Finance,有 15 分钟延迟*
"""

# 主入口函数
def query_stock(symbol: str) -> str:
    """
    查询股价的主入口
    
    Args:
        symbol: 股票代码
    
    Returns:
        格式化后的查询结果
    """
    quote_data = get_stock_quote(symbol)
    return format_quote_result(quote_data)

3.5 第四步:添加依赖(如需要)

如果技能需要第三方库,创建 requirements.txt

touch requirements.txt
echo "requests>=2.28.0" > requirements.txt

安装依赖:

pip3 install -r requirements.txt

3.6 第五步:本地测试

在发布之前,先本地测试技能是否正常工作。

创建测试文件:

mkdir test
cd test
touch test_skill.py

编辑测试代码:

# test_skill.py
import sys
sys.path.insert(0, '..')

from skill import query_stock

# 测试用例
def test_apple():
    result = query_stock('AAPL')
    print("=== 测试 AAPL ===")
    print(result)
    assert 'AAPL' in result
    assert '$' in result
    print("✅ 测试通过\n")

def test_nvidia():
    result = query_stock('NVDA')
    print("=== 测试 NVDA ===")
    print(result)
    assert 'NVDA' in result
    print("✅ 测试通过\n")

def test_invalid():
    result = query_stock('INVALID')
    print("=== 测试无效代码 ===")
    print(result)
    # 无效代码应该返回错误信息
    assert 'error' in result.lower() or '失败' in result
    print("✅ 测试通过\n")

if __name__ == '__main__':
    test_apple()
    test_nvidia()
    test_invalid()
    print("🎉 所有测试通过!")

运行测试:

cd test
python3 test_skill.py

如果测试通过,说明技能核心逻辑正常。


四、调试与优化

4.1 常见问题

问题 1:技能不触发

  • 检查 SKILL.md 的触发条件是否包含用户的问法
  • 尝试在对话中明确提到技能名称

问题 2:API 调用失败

  • 检查网络连接
  • 检查 API 是否需要 Key
  • 添加超时和错误处理

问题 3:返回格式不对

  • 确保返回的是字符串
  • 用 Markdown 格式化提升可读性

4.2 优化建议

  1. 添加缓存:股价数据不需要实时,可以缓存 5 分钟
  2. 添加重试:网络请求失败时自动重试
  3. 添加日志:方便排查问题
  4. 添加单元测试:保证代码质量

五、发布与使用

5.1 发布到本地

技能开发完成后,放在技能目录就能用:

# 确认技能在正确位置
ls ~/.openclaw/workspace/skills/stock-quote/

# 应该看到:
# SKILL.md  skill.py  requirements.txt  test/

5.2 在对话中使用

启动 OpenClaw,直接询问:

用户:查询 NVDA 的股价

Agent: 📊 **NVDA 实时行情**

💰 当前股价:$125.43
📈 涨跌:+2.87 (+2.35%) 📈
📊 成交量:45.2M
💵 货币:USD

*数据来源于 Yahoo Finance,有 15 分钟延迟*

5.3 分享给别人

如果想分享给别人,可以:

  1. 打包成 ZIP

    cd ~/.openclaw/workspace/skills/
    zip -r stock-quote.zip stock-quote/
    
  2. 发布到 GitHub

    cd stock-quote/
    git init
    git add .
    git commit -m "Initial commit"
    git remote add origin <your-repo-url>
    git push -u origin main
    
  3. 提交到 OpenClaw 技能库(如社区支持)


六、复用社区技能

6.1 查找现有技能

在开发新技能之前,先看看社区有没有现成的:

# 查看已安装的技能
ls ~/.openclaw/workspace/skills/

# 查看技能说明
cat ~/.openclaw/workspace/skills/<skill-name>/SKILL.md

6.2 安装社区技能

如果社区有现成技能,可以直接安装:

# 示例(具体命令取决于技能分发方式)
cd ~/.openclaw/workspace/skills/
git clone <skill-repo-url> <skill-name>

6.3 修改现有技能

如果想修改现有技能:

  1. 复制一份到自己的目录
  2. 修改 SKILL.md 和技能名称
  3. 按需修改代码
  4. 测试验证

七、进阶:多文件技能

上面的例子是单文件技能,适合简单功能。复杂技能可以拆分成多个文件:

advanced-skill/
├── SKILL.md              # 技能说明
├── main.py               # 主入口
├── utils/                # 工具函数
│   ├── __init__.py
│   ├── api_client.py     # API 调用
│   └── formatter.py      # 格式化
├── config/               # 配置文件
│   └── settings.py
├── requirements.txt      # 依赖
└── test/                 # 测试
    └── test_main.py

组织原则:

  • 按功能模块拆分文件
  • 工具函数放在 utils 目录
  • 配置文件单独管理
  • 测试代码独立目录

结尾 CTA

以上就是从零开始开发 OpenClaw 技能的完整流程。

技能开发遇到问题?在评论区提问,我会逐一解答。

完整源码已上传 GitHub:

想学更多?


附录:技能开发模板

如果你想快速开始,可以用这个模板:

# <技能名称> - <一句话描述>

## 描述
<详细描述技能功能>

## 触发条件
当用户提到以下关键词时激活:
- <关键词 1>
- <关键词 2>

## 能力范围
- ✅ <能做什么 1>
- ✅ <能做什么 2>
- ❌ <不能做什么 1>
- ❌ <不能做什么 2>

## 使用方法
<使用示例>

## 数据源
<数据来源说明>

## 注意事项
<需要注意的事项>
# <技能名称> 技能实现

def <main_function>(input: str) -> str:
    """
    主入口函数
    
    Args:
        input: 用户输入
    
    Returns:
        格式化后的结果
    """
    # 实现逻辑
    pass
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐