OpenClaw 技能系统完全指南:从零开始创建自定义技能

OpenClaw 技能系统完全指南:从零开始创建自定义技能

摘要:本文详细讲解 OpenClaw 技能系统的架构设计、开发流程和最佳实践。包含技能创建、测试、调试、部署的完整教程,以及 10+ 个实用技能示例,所有代码均可直接使用。

封面图: 技能系统架构图

作者:江神
邮箱: jiangyayun72@gmail.com
发布时间:2026-03-04
阅读时间:25 分钟


一、为什么需要技能系统?

《30 天实战》 中,我记录了搭建 AI 助手"戴蒙"的过程。但原生的 LLM 能力有限,无法:

  • 访问外部 API - 天气、股票、新闻等实时数据
  • 执行代码 - Python、Node.js 脚本运行
  • 操作文件 - 读写、转换、分析文件
  • 控制设备 - 发送消息、管理日程、控制 IoT

技能系统的作用:扩展 AI 能力边界,让 Agent 能够与外部世界交互。

我的技能架构

用户请求 → Agent 识别意图 → 选择技能 → 执行技能 → 返回结果
                    ↓
            技能注册表
                    ↓
        ├─ web_search (网络搜索)
        ├─ image_generate (图片生成)
        ├─ voice_transcribe (语音转写)
        ├─ code_runner (代码执行)
        ├─ file_converter (文件转换)
        └─ ... (更多技能)

二、技能系统架构

2.1 技能目录结构

/root/.openclaw/skills/
├── web_search/
│   ├── SKILL.md          # 技能描述和触发条件
│   ├── skill.py          # 技能实现
│   └── README.md         # 使用说明
├── image-generate/
│   ├── SKILL.md
│   ├── image_generate.py
│   └── README.md
├── voice-transcribe/
│   └── ...
└── ...

2.2 技能元数据(SKILL.md)

每个技能必须包含 SKILL.md 文件,定义技能的触发条件和行为:

---
name: web_search
description: 使用 Brave Search API 搜索互联网
trigger: 用户提到"搜索"、"查找"、"调研"等关键词
---

# Web Search Skill

## 触发条件
- 用户请求搜索互联网
- 用户提到"搜索 XXX"、"查找 XXX"
- 用户需要最新信息

## 执行流程
1. 提取搜索关键词
2. 调用 Brave Search API
3. 解析搜索结果
4. 返回摘要和链接

## 配置
- API Key: BRAVE_API_KEY
- 搜索结果数量:10

2.3 技能执行机制

技能执行分为 4 个阶段:

1. 触发检测  2. 参数提取  3. 技能执行  4. 结果返回

示例流程

用户:"搜索一下 2026 年 AI Agent 框架对比"
  ↓
Agent: 检测到"搜索"关键词 → 触发 web_search 技能
  ↓
参数提取:query="2026 年 AI Agent 框架对比"
  ↓
执行技能:调用 Brave Search API
  ↓
返回结果:搜索摘要 + 链接列表

三、创建第一个技能

3.1 示例:天气查询技能

步骤 1:创建目录

mkdir -p /root/.openclaw/skills/weather-query

步骤 2:创建 SKILL.md

cat > /root/.openclaw/skills/weather-query/SKILL.md << 'EOF'
---
name: weather-query
description: 查询指定城市的天气信息
trigger: 用户提到"天气"、"气温"、"天气预报"等
---

# Weather Query Skill

## 触发条件
- 用户询问天气情况
- 用户提到城市名 + 天气
- 用户需要天气预报

## 执行流程
1. 提取城市名称
2. 调用天气 API
3. 解析天气数据
4. 返回天气信息

## 配置
- API: Open-Meteo (免费,无需 API Key)
- 数据:温度、降水、风速、湿度
EOF

步骤 3:创建技能实现

cat > /root/.openclaw/skills/weather-query/skill.py << 'EOF'
#!/usr/bin/env python3
"""
天气查询技能
使用 Open-Meteo API(免费,无需 API Key)
"""

import requests
from typing import Dict, Optional

# 城市坐标映射(简化版)
CITY_COORDS = {
    "北京": {"lat": 39.9042, "lon": 116.4074},
    "上海": {"lat": 31.2304, "lon": 121.4737},
    "深圳": {"lat": 22.5431, "lon": 114.0579},
    "广州": {"lat": 23.1291, "lon": 113.2644},
}

def get_weather(city: str) -> Dict:
    """获取指定城市的天气信息"""
    if city not in CITY_COORDS:
        return {"error": f"不支持的城市:{city}"}

    coords = CITY_COORDS[city]
    url = "https://api.open-meteo.com/v1/forecast"
    params = {
        "latitude": coords["lat"],
        "longitude": coords["lon"],
        "current_weather": True
    }

    response = requests.get(url, params=params)
    data = response.json()
    current = data.get("current_weather", {})

    return {
        "city": city,
        "temperature": current.get("temperature", "N/A"),
        "windspeed": current.get("windspeed", "N/A"),
        "time": current.get("time", "N/A"),
    }

def execute(query: str) -> str:
    """技能入口"""
    for city in CITY_COORDS.keys():
        if city in query:
            weather = get_weather(city)
            return f"🌤 {weather['city']}天气\n温度:{weather['temperature']}°C"

    return "请提供城市名称"

if __name__ == "__main__":
    print(execute("北京天气怎么样?"))
EOF

步骤 4:测试技能

cd /root/.openclaw/skills/weather-query
python3 skill.py

输出

🌤 北京天气
温度:15°C

四、高级技能开发

4.1 使用外部 API

示例:网络搜索技能

#!/usr/bin/env python3
"""网络搜索技能 - 使用 Brave Search API"""

import os
import requests
from typing import List, Dict

class WebSearchSkill:
    def __init__(self):
        self.api_key = os.getenv("BRAVE_API_KEY")
        self.base_url = "https://api.search.brave.com/res/v1/web/search"

    def search(self, query: str, count: int = 10) -> List[Dict]:
        """执行网络搜索"""
        headers = {
            "Accept": "application/json",
            "X-Subscription-Token": self.api_key
        }
        params = {"q": query, "count": count}

        response = requests.get(self.base_url, headers=headers, params=params)
        data = response.json()

        results = []
        for result in data.get("web", {}).get("results", []):
            results.append({
                "title": result.get("title"),
                "url": result.get("url"),
                "description": result.get("description")
            })

        return results

    def execute(self, query: str) -> str:
        """技能入口"""
        results = self.search(query)
        output = ["🔍 搜索结果:\n"]
        for i, result in enumerate(results, 1):
            output.append(f"{i}. **{result['title']}**")
            output.append(f"   {result['description']}")
            output.append(f"   🔗 {result['url']}\n")

        return "\n".join(output)

# 使用示例
if __name__ == "__main__":
    skill = WebSearchSkill()
    print(skill.execute("2026 AI Agent 框架对比"))

4.2 文件操作技能

示例:Markdown 转 HTML 技能

#!/usr/bin/env python3
"""Markdown 转 HTML 技能"""

import markdown
from pathlib import Path

class MarkdownToHTMLSkill:
    def convert(self, md_file: str, output_file: str = None) -> str:
        """转换 Markdown 为 HTML"""
        md_path = Path(md_file)
        if not md_path.exists():
            return f"❌ 文件不存在:{md_file}"

        with open(md_path, 'r', encoding='utf-8') as f:
            md_content = f.read()

        html_content = markdown.markdown(
            md_content,
            extensions=['extra', 'codehilite', 'toc']
        )

        if output_file:
            with open(output_file, 'w', encoding='utf-8') as f:
                f.write(html_content)
            return f"✅ 已转换:{md_file}{output_file}"

        return html_content

    def execute(self, args: str) -> str:
        """技能入口"""
        parts = args.split()
        if len(parts) < 1:
            return "用法:markdown-to-html <input.md> [output.html]"

        return self.convert(parts[0], parts[1] if len(parts) > 1 else None)

# 使用示例
if __name__ == "__main__":
    skill = MarkdownToHTMLSkill()
    print(skill.execute("README.md output.html"))

4.3 代码执行技能

示例:Python 代码执行技能

#!/usr/bin/env python3
"""Python 代码执行技能"""

import subprocess
import tempfile
import os

class PythonCodeExecutor:
    def __init__(self, timeout: int = 30):
        self.timeout = timeout

    def execute_code(self, code: str) -> dict:
        """执行 Python 代码"""
        with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
            f.write(code)
            temp_file = f.name

        try:
            result = subprocess.run(
                ['python3', temp_file],
                capture_output=True,
                text=True,
                timeout=self.timeout
            )

            return {
                'success': result.returncode == 0,
                'stdout': result.stdout,
                'stderr': result.stderr,
            }
        finally:
            os.unlink(temp_file)

    def execute(self, code: str) -> str:
        """技能入口"""
        result = self.execute_code(code)
        if result['success']:
            return f"✅ 执行成功\n\n输出:\n```\n{result['stdout']}\n```"
        else:
            return f"❌ 执行失败\n\n错误:\n```\n{result['stderr']}\n```"

# 使用示例
if __name__ == "__main__":
    executor = PythonCodeExecutor()
    test_code = """
print("Hello, World!")
for i in range(5):
    print(f"Count: {i}")
"""
    print(executor.execute(test_code))

五、技能注册与调用

5.1 技能注册

openclaw.json 中注册技能:

{
  "skills": {
    "enabled": [
      "web_search",
      "weather-query",
      "image-generate",
      "voice-transcribe",
      "code-runner"
    ],
    "config": {
      "web_search": {
        "api_key": "YOUR_BRAVE_API_KEY",
        "max_results": 10
      },
      "weather-query": {
        "default_city": "北京"
      }
    }
  }
}

5.2 技能调用方式

方式 1:自动触发 - 基于用户意图自动选择技能

方式 2:显式调用 - 用户明确指定技能

方式 3:链式调用 - 多个技能组合使用


六、最佳实践

6.1 技能设计原则

  1. 单一职责 - 每个技能只做一件事
  2. 明确接口 - 输入输出清晰定义
  3. 错误处理 - 优雅处理异常情况
  4. 日志记录 - 详细记录执行过程
  5. 性能优化 - 避免阻塞和超时

6.2 安全注意事项

  1. API Key 管理 - 使用环境变量,不硬编码
  2. 输入验证 - 验证所有用户输入
  3. 权限控制 - 限制技能访问范围
  4. 超时设置 - 防止无限循环
  5. 资源限制 - 限制内存和 CPU 使用

6.3 性能优化

  1. 缓存结果 - 避免重复调用
  2. 异步执行 - 非阻塞 I/O
  3. 批量处理 - 减少 API 调用次数
  4. 连接池 - 复用数据库连接
  5. 懒加载 - 按需加载资源

七、总结

7.1 核心要点

  1. 技能架构 - SKILL.md + 技能实现 + 测试
  2. 开发流程 - 创建→测试→注册→调用
  3. 最佳实践 - 单一职责、错误处理、日志记录
  4. 安全注意 - API Key 管理、输入验证、权限控制

7.2 后续优化方向

  • [ ] 创建更多实用技能
  • [ ] 建立技能商店
  • [ ] 实现技能链式调用
  • [ ] 添加技能性能监控

欢迎交流讨论。如果你在技能开发过程中遇到问题,或者有相关问题,欢迎在评论区留言或私信我。