返回

07. OpenClaw Skills 開發入門:打造你的第一個技能

本文手把手教你開發第一個 OpenClaw Skill。從 SKILL.md 結構解析到完整範例,涵蓋技能定義、觸發詞設計、工具整合、測試發布全流程,幫助你為 AI 助手新增自訂能力。

適用於 OpenClaw v2026.2 | 本文假設你熟悉基本 Markdown 和命令列,想建立自訂技能。

TL;DR: 建立 Skill 只需一個 SKILL.md 檔案。核心欄位:nameversiontriggers(觸發詞)、tools(工具列表)。放在 ~/.openclaw/workspace/skills/<name>/SKILL.md。觸發詞要具體避免衝突。發布到 ClawHub:openclaw skill publish <name>。包含安全掃描和權限控制。

開發環境準備

前置要求

要求 說明
OpenClaw 已安裝並執行
文字編輯器 VS Code 或任意編輯器
基礎 Markdown SKILL.md 使用 Markdown 格式
API 文件 如需整合外部服務,準備 API 文件

建立技能目錄

# 建立技能目錄
mkdir -p ~/.openclaw/workspace/skills/weather-api

# 進入目錄
cd ~/.openclaw/workspace/skills/weather-api

# 建立基本檔案
touch SKILL.md
touch README.md
touch config.json.example

目錄結構

weather-api/
├── SKILL.md              # 技能定義(必需)
├── README.md             # 說明文件(推薦)
├── config.json.example   # 設定範例(可選)
├── src/                  # 原始碼(可選)
│   └── index.js
└── package.json          # 相依套件聲明(可選)

SKILL.md 結構詳解

基本結構

---
# Frontmatter:中繼資料
name: skill-name
version: 1.0.0
author: your-name
description: Brief description
triggers:
  - trigger-1
  - trigger-2
dependencies: []
tools: []
---

# Skill Title

Detailed description...

## Features
## Setup
## Usage Examples
## Configuration
## Notes

Frontmatter 欄位

欄位 必需 說明
name 技能唯一識別碼,小寫字母和連字號
version 語意化版本號
author 作者名稱或組織
description 簡短描述(一句話)
triggers 觸發詞列表
dependencies ⚠️ 相依的其他技能
tools ⚠️ 提供的工具列表

觸發詞設計

觸發詞是 Agent 識別技能的關鍵:

triggers:
  - weather
  - 天氣
  - forecast
  - 氣溫
  - temperature
  - rain
  - 下雨
  - umbrella
  - 雨傘

設計原則

原則 說明 範例
具體性 避免過於通用的詞 gmail-sendsend
多語言 支援中英文 weather 天氣
場景化 包含使用場景 check-weather weather-tomorrow
無衝突 檢查與現有技能衝突 openclaw skill search weather

實戰:開發天氣查詢技能

需求分析

我們要開發一個天氣查詢技能,功能包括:

  1. 查詢當前天氣
  2. 查詢未來幾天預報
  3. 支援中英文城市名
  4. 提供穿搭建議

完整 SKILL.md

---
name: weather-api
version: 1.0.0
author: your-name
description: Query weather information from OpenWeatherMap API
triggers:
  - weather
  - 天氣
  - forecast
  - 預報
  - temperature
  - 氣溫
  - rain
  - 下雨
  - umbrella
  - 雨傘
dependencies: []
tools:
  - weather_current
  - weather_forecast
---

# Weather API Skill

Query weather information for any city worldwide. Provides current weather and forecasts with practical suggestions.

## Features

- **Current Weather**: Get real-time weather conditions
- **Forecast**: 5-day weather forecast
- **Multi-language**: Support for city names in multiple languages
- **Smart Suggestions**: Clothing and activity recommendations

## Setup

### 1. Get API Key

1. Visit [OpenWeatherMap](https://openweathermap.org/api)
2. Sign up for a free account
3. Generate an API key

### 2. Configure the Skill

Set the environment variable:

\`\`\`bash
export OPENWEATHER_API_KEY="your-api-key-here"
\`\`\`

Or add to your OpenClaw config:

\`\`\`json
{
  "skills": {
    "weather-api": {
      "apiKey": "your-api-key-here",
      "units": "metric",
      "lang": "zh_cn"
    }
  }
}
\`\`\`

## Usage Examples

### Current Weather

User: "北京今天天氣怎麼樣"
User: "What's the weather in Tokyo"
User: "Check weather for Shanghai"

Action:
1. Parse city name from user message
2. Call weather_current tool with city parameter
3. Format and return weather information

### Weather Forecast

User: "明天會下雨嗎"
User: "3天天氣預報 for New York"
User: "週末天氣怎麼樣"

Action:
1. Parse city name and days from user message
2. Call weather_forecast tool
3. Format forecast data into readable summary

### Smart Suggestions

User: "今天需要帶傘嗎"
User: "穿什麼衣服合適"
User: "適合戶外運動嗎"

Action:
1. Get current weather
2. Analyze conditions (rain, temperature, UV)
3. Provide practical suggestions

## Tools

### weather_current

Get current weather for a city.

**Parameters:**
- `city` (string, required): City name, can be in any language
- `units` (string, optional): "metric", "imperial", or "kelvin". Default: "metric"
- `lang` (string, optional): Language code. Default: "zh_cn"

**Returns:**
\`\`\`json
{
  "city": "Beijing",
  "country": "CN",
  "temperature": 25,
  "feels_like": 27,
  "humidity": 65,
  "wind_speed": 12,
  "condition": "Partly cloudy",
  "icon": "02d",
  "suggestion": "Light jacket recommended, no rain expected"
}
\`\`\`

### weather_forecast

Get weather forecast for up to 5 days.

**Parameters:**
- `city` (string, required): City name
- `days` (number, optional): Number of days (1-5). Default: 3
- `units` (string, optional): Temperature units

**Returns:**
\`\`\`json
{
  "city": "Beijing",
  "forecast": [
    {
      "date": "2026-02-27",
      "temp_high": 28,
      "temp_low": 18,
      "condition": "Sunny",
      "rain_chance": 0
    },
    ...
  ]
}
\`\`\`

## Configuration Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `apiKey` | string | - | OpenWeatherMap API key |
| `units` | string | "metric" | Temperature units |
| `lang` | string | "zh_cn" | Language for descriptions |
| `cache_ttl` | number | 600 | Cache duration in seconds |

## Error Handling

The skill handles common errors:

- **City not found**: Suggests similar city names
- **API key invalid**: Prompts user to check configuration
- **Rate limit**: Queues request and retries
- **Network error**: Falls back to cached data if available

## Notes

- Free tier allows 1000 requests/day
- City names support Chinese: "北京", "上海", "廣州"
- Results are cached for 10 minutes by default
- Consider upgrading to paid tier for more frequent updates

工具實作(可選)

如果你的技能需要執行具體操作,可以新增工具實作。

簡單方式:使用內建工具

OpenClaw 內建了 web_searchread 工具,可以直接在 SKILL.md 中描述如何使用:

## Implementation Notes

To get weather data:

1. Use `web_search` tool to find weather API
2. Use `read` tool to fetch JSON response
3. Parse and format the data

Example search query: "weather API Beijing current temperature"

進階方式:自訂工具腳本

建立 src/index.js

// src/index.js
const axios = require('axios');

const OPENWEATHER_BASE_URL = 'https://api.openweathermap.org/data/2.5';

async function weather_current({ city, units = 'metric', lang = 'zh_cn' }, config) {
  const apiKey = config.apiKey || process.env.OPENWEATHER_API_KEY;
  
  if (!apiKey) {
    throw new Error('OpenWeatherMap API key not configured');
  }

  try {
    const response = await axios.get(`${OPENWEATHER_BASE_URL}/weather`, {
      params: {
        q: city,
        appid: apiKey,
        units,
        lang
      }
    });

    const data = response.data;
    
    let suggestion = '';
    if (data.rain || data.weather[0].main === 'Rain') {
      suggestion = 'Bring an umbrella, rain expected';
    } else if (data.main.temp < 15) {
      suggestion = 'Wear warm clothing, temperature is low';
    } else if (data.main.temp > 30) {
      suggestion = 'Stay hydrated, high temperature';
    } else {
      suggestion = 'Pleasant weather, enjoy your day';
    }

    return {
      city: data.name,
      country: data.sys.country,
      temperature: data.main.temp,
      feels_like: data.main.feels_like,
      humidity: data.main.humidity,
      wind_speed: data.wind.speed,
      condition: data.weather[0].description,
      icon: data.weather[0].icon,
      suggestion
    };
  } catch (error) {
    if (error.response?.status === 404) {
      throw new Error(`City "${city}" not found. Please check the spelling.`);
    }
    throw error;
  }
}

async function weather_forecast({ city, days = 3, units = 'metric' }, config) {
  const apiKey = config.apiKey || process.env.OPENWEATHER_API_KEY;
  
  if (!apiKey) {
    throw new Error('OpenWeatherMap API key not configured');
  }

  try {
    const response = await axios.get(`${OPENWEATHER_BASE_URL}/forecast`, {
      params: {
        q: city,
        appid: apiKey,
        units,
        cnt: days * 8
      }
    });

    const data = response.data;
    
    const dailyForecasts = {};
    data.list.forEach(item => {
      const date = item.dt_txt.split(' ')[0];
      if (!dailyForecasts[date]) {
        dailyForecasts[date] = {
          temp_high: item.main.temp_max,
          temp_low: item.main.temp_min,
          conditions: [item.weather[0].main],
          rain_chance: item.pop * 100
        };
      } else {
        dailyForecasts[date].temp_high = Math.max(dailyForecasts[date].temp_high, item.main.temp_max);
        dailyForecasts[date].temp_low = Math.min(dailyForecasts[date].temp_low, item.main.temp_min);
        if (!dailyForecasts[date].conditions.includes(item.weather[0].main)) {
          dailyForecasts[date].conditions.push(item.weather[0].main);
        }
        dailyForecasts[date].rain_chance = Math.max(dailyForecasts[date].rain_chance, item.pop * 100);
      }
    });

    return {
      city: data.city.name,
      forecast: Object.entries(dailyForecasts)
        .slice(0, days)
        .map(([date, info]) => ({
          date,
          temp_high: Math.round(info.temp_high),
          temp_low: Math.round(info.temp_low),
          condition: info.conditions.join('/'),
          rain_chance: Math.round(info.rain_chance)
        }))
    };
  } catch (error) {
    if (error.response?.status === 404) {
      throw new Error(`City "${city}" not found. Please check the spelling.`);
    }
    throw error;
  }
}

module.exports = {
  weather_current,
  weather_forecast
};

package.json

{
  "name": "weather-api",
  "version": "1.0.0",
  "description": "Weather API skill for OpenClaw",
  "main": "src/index.js",
  "dependencies": {
    "axios": "^1.6.0"
  },
  "openclaw": {
    "skill": "weather-api",
    "tools": ["weather_current", "weather_forecast"]
  }
}

測試技能

本地測試

# 驗證 SKILL.md 語法
openclaw skill validate weather-api

# 輸出範例:
# ✅ Frontmatter valid
# ✅ Triggers defined
# ✅ Description present
# ✅ Tools documented

# 載入技能
openclaw skill load weather-api

# 測試技能
openclaw agent --message "北京今天天氣怎麼樣"

# 應該看到天氣資訊

除錯模式

# 啟用除錯日誌
openclaw gateway --verbose --filter skill:weather-api

# 查看技能載入日誌
openclaw logs --skill weather-api

測試場景

測試場景 輸入 預期輸出
中文城市 “北京天氣” 北京天氣資訊
英文城市 “Weather in Tokyo” 東京天氣資訊
預報查詢 “明天會下雨嗎” 明天天氣預報
穿搭建議 “今天穿什麼” 基於天氣的建議
錯誤處理 “xxx天氣” 城市未找到提示

發布技能

準備發布

  1. 完善文件:確保 README.md 完整
  2. 新增範例:提供使用範例
  3. 測試充分:涵蓋各種邊界情況
  4. 清理敏感資訊:移除 API Key 等

發布到 GitHub

# 初始化 Git
git init
git add .
git commit -m "Initial release of weather-api skill"

# 推送到 GitHub
git remote add origin https://github.com/your-username/weather-api.git
git push -u origin main

# 建立發布標籤
git tag v1.0.0
git push origin v1.0.0

提交到 ClawHub

# 發布到 ClawHub
openclaw skill publish weather-api

# 輸出範例:
# Validating skill...
# ✅ Validation passed
# Publishing to ClawHub...
# ✅ Published successfully!
# 
# Your skill is now available at:
# https://clawhub.com/skills/weather-api

README.md 範本

# Weather API Skill for OpenClaw

Query weather information from OpenWeatherMap API.

## Features

- Current weather conditions
- 5-day weather forecast
- Multi-language city support
- Smart clothing suggestions

## Installation

\`\`\`bash
openclaw skill install weather-api
\`\`\`

## Configuration

Set your OpenWeatherMap API key:

\`\`\`bash
export OPENWEATHER_API_KEY="your-api-key"
\`\`\`

Or in OpenClaw config:

\`\`\`json
{
  "skills": {
    "weather-api": {
      "apiKey": "your-api-key"
    }
  }
}
\`\`\`

## Usage

Just ask about the weather:

- "北京今天天氣怎麼樣"
- "What's the weather in Tokyo"
- "明天會下雨嗎"
- "今天需要帶傘嗎"

## Requirements

- OpenWeatherMap API key (free tier: 1000 requests/day)
- Internet connection

## License

MIT

進階技巧

條件觸發

根據上下文決定是否觸發:

## Advanced Triggers

This skill is triggered when:
1. User mentions weather-related keywords
2. User asks about temperature or conditions
3. User needs outdoor activity suggestions

Not triggered when:
- Weather is mentioned metaphorically ("I'm under the weather")
- User is asking about CPU temperature or other technical metrics

上下文記憶

在 SKILL.md 中新增上下文處理:

## Context Handling

When user asks "What about tomorrow?" after a weather query:
1. Check previous context for city name
2. Use the same city for forecast query

When user asks "And in Shanghai?" after querying another city:
1. Parse the new city name
2. Compare weather between both cities

鏈式技能

與其他技能協作:

## Skill Integration

This skill works well with:
- **calendar**: Suggest events based on weather
- **travel**: Provide weather for travel destinations
- **clothing**: Recommend outfits based on temperature

Example workflow:
User: "Planning a trip to Tokyo next week"
1. Travel skill: Parse destination and dates
2. Weather skill: Get Tokyo forecast
3. Calendar skill: Check existing events
4. Combined response: Trip summary with weather

錯誤恢復

優雅處理錯誤:

## Error Recovery

When API fails:
1. Check cache for recent data
2. Inform user about the issue
3. Offer alternatives:
   - "I couldn't get live weather data. Want me to try again?"
   - "The weather service is temporarily unavailable. Would you like a general forecast?"

When city not found:
1. Suggest similar city names
2. Ask for clarification
3. Use geolocation if available

最佳實務

文件規範

要求 說明
描述清晰 一句話說明技能功能
範例充分 涵蓋主要使用場景
設定說明 詳細說明設定步驟
錯誤處理 列出常見錯誤和解決方案
版本更新 維護 CHANGELOG

安全考量

## Security Notes

- Never hardcode API keys in SKILL.md
- Use environment variables or config files
- Validate and sanitize user input
- Rate limit API calls
- Log errors without exposing sensitive data

效能最佳化

## Performance Tips

- Cache API responses (10-minute default)
- Use async operations for multiple requests
- Minimize tool calls by batching
- Use compressed responses when available

小結

Skills 開發的核心是:

  • SKILL.md 是靈魂:定義清晰、描述準確、範例充分
  • 觸發詞是關鍵:設計合理、避免衝突、涵蓋場景
  • 工具是能力:實作完整、錯誤處理、效能最佳化
  • 文件是橋樑:幫助使用者理解和使用你的技能

透過本篇的學習,你已經掌握了 Skills 開發的基礎知識,可以開始為 OpenClaw 建立自訂技能了。


本篇小結

  • 理解了 SKILL.md 的結構和欄位
  • 學會了觸發詞設計原則
  • 掌握了工具實作方法
  • 了解了測試和發布流程
  • 學習了進階技巧和最佳實務

更新記錄

  • 2026-02-26:初版發布,基於 OpenClaw v2026.2

系列導航