Back

07. OpenClaw Skills Development Guide: Build Your First Skill

This guide walks you through building your first OpenClaw Skill. From SKILL.md structure to complete examples, covering skill definition, trigger design, tool integration, and the full testing-to-publishing workflow—helping you add custom capabilities to your AI assistant.

  • “OpenClaw trigger design”
  • “ClawHub skill publishing”

For OpenClaw v2026.2 | This guide assumes you are familiar with basic Markdown and the command line, and want to create custom skills.

TL;DR: Creating a Skill only requires one SKILL.md file. Core fields: name, version, triggers (trigger words), tools (tool list). Place it at ~/.openclaw/workspace/skills/<name>/SKILL.md. Triggers should be specific to avoid conflicts. Publish to ClawHub: openclaw skill publish <name>. Includes security scanning and permission control.

Development Environment Setup

Prerequisites

Requirement Description
OpenClaw Installed and running
Text Editor VS Code or any editor
Basic Markdown SKILL.md uses Markdown format
API Documentation Prepare API docs if integrating external services

Create Skill Directory

# Create skill directory
mkdir -p ~/.openclaw/workspace/skills/weather-api

# Enter directory
cd ~/.openclaw/workspace/skills/weather-api

# Create basic files
touch SKILL.md
touch README.md
touch config.json.example

Directory Structure

weather-api/
├── SKILL.md              # Skill definition (required)
├── README.md             # Documentation (recommended)
├── config.json.example   # Config example (optional)
├── src/                  # Source code (optional)
│   └── index.js
└── package.json          # Dependencies (optional)

SKILL.md Structure Explained

Basic Structure

---
# Frontmatter: metadata
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 Fields

Field Required Description
name Unique skill identifier, lowercase letters and hyphens
version Semantic version number
author Author name or organization
description Brief description (one sentence)
triggers List of trigger words
dependencies ⚠️ Other skills this depends on
tools ⚠️ List of tools provided

Trigger Design

Triggers are how the Agent identifies skills:

triggers:
  - weather
  - 天气
  - forecast
  - 气温
  - temperature
  - rain
  - 下雨
  - umbrella
  - 雨伞

Design Principles:

Principle Description Example
Specificity Avoid overly generic words gmail-sendsend
Multilingual Support multiple languages weather 天气
Scenario-based Include usage scenarios check-weather weather-tomorrow
No Conflicts Check for conflicts with existing skills openclaw skill search weather

Hands-on: Build a Weather Query Skill

Requirements Analysis

We will build a weather query skill with these features:

  1. Query current weather
  2. Query multi-day forecasts
  3. Support city names in multiple languages
  4. Provide clothing suggestions

Complete 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

Tool Implementation (Optional)

If your skill needs to perform specific operations, you can add tool implementations.

Simple Approach: Use Built-in Tools

OpenClaw includes web_search and read tools that can be described directly in 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"

Advanced Approach: Custom Tool Scripts

Create 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;
    
    // Generate suggestion based on conditions
    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 // 8 forecasts per day (every 3 hours)
      }
    });

    const data = response.data;
    
    // Group by day and get daily summary
    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"]
  }
}

Testing Skills

Local Testing

# Validate SKILL.md syntax
openclaw skill validate weather-api

# Example output:
# ✅ Frontmatter valid
# ✅ Triggers defined
# ✅ Description present
# ✅ Tools documented

# Load skill
openclaw skill load weather-api

# Test skill
openclaw agent --message "北京今天天气怎么样"

# You should see weather information

Debug Mode

# Enable debug logs
openclaw gateway --verbose --filter skill:weather-api

# View skill load logs
openclaw logs --skill weather-api

Test Scenarios

Test Scenario Input Expected Output
Chinese city “北京天气” Beijing weather info
English city “Weather in Tokyo” Tokyo weather info
Forecast query “明天会下雨吗” Tomorrow’s weather forecast
Clothing suggestion “今天穿什么” Weather-based suggestions
Error handling “xxx天气” City not found message

Publishing Skills

Pre-publish Checklist

  1. Complete documentation: Ensure README.md is complete
  2. Add examples: Provide usage examples
  3. Thorough testing: Cover various edge cases
  4. Remove sensitive data: Remove API keys, etc.

Publish to GitHub

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

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

# Create release tag
git tag v1.0.0
git push origin v1.0.0

Submit to ClawHub

# Publish to ClawHub
openclaw skill publish weather-api

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

README.md Template

# 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 Tips

Conditional Triggers

Decide whether to trigger based on context:

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

Context Memory

Add context handling in 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

Chained Skills

Collaborate with other skills:

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

Handle errors gracefully:

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

Best Practices

Documentation Standards

Requirement Description
Clear description One-sentence summary of skill functionality
Sufficient examples Cover main usage scenarios
Config instructions Detailed setup steps
Error handling List common errors and solutions
Version updates Maintain CHANGELOG

Security Considerations

## 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 Optimization

## Performance Tips

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

Summary

The core of Skills development:

  • SKILL.md is the soul: Clear definition, accurate description, sufficient examples
  • Triggers are key: Well-designed, conflict-free, scenario coverage
  • Tools are the capability: Complete implementation, error handling, performance optimization
  • Documentation is the bridge: Helps users understand and use your skill

With what you’ve learned in this guide, you now have the fundamentals to create custom skills for OpenClaw.


Key Takeaways:

  • Understood SKILL.md structure and fields
  • Learned trigger design principles
  • Mastered tool implementation methods
  • Learned the testing and publishing workflow
  • Explored advanced tips and best practices

Changelog:

  • 2026-02-26: Initial release, based on OpenClaw v2026.2

Series Navigation: