Skip to content

How to Write Your Own OpenClaw Skill from Scratch

nacre.sh TeamMay 6, 202611 min read

Step-by-step guide to writing your own OpenClaw skill from scratch. Covers SKILL.md format, Python implementation, tool definitions, testing, and publishing to ClawHub.

write openclaw skill customopenclaw skill developmentSKILL.mdopenclaw development

Writing a custom OpenClaw skill allows you to give your agent capabilities tailored to your specific needs — connecting to internal APIs, automating proprietary workflows, or integrating tools that don't yet have ClawHub skills. This guide covers the complete development process from scratch.

Skill Structure

Create a directory for your skill:

my-skill/
├── SKILL.md          # Manifest and documentation
├── main.py           # Implementation
├── requirements.txt  # Python dependencies
└── tests/
    └── test_main.py  # Optional tests

Writing SKILL.md

---
name: my-weather-skill
version: 1.0.0
author: yourname
description: Get current weather for any location
permissions:
  - network_access
  - read_env:WEATHER_API_KEY
tools:
  - name: get_weather
    description: Get the current weather and forecast for a location
    parameters:
      location:
        type: string
        description: City name or ZIP code
        required: true
      units:
        type: string
        description: Temperature units - celsius or fahrenheit
        default: celsius
        enum: [celsius, fahrenheit]
minimum_openclaw_version: "2.3.0"
---

# My Weather Skill

Provides current weather information using the OpenWeatherMap API.
Requires a free API key from openweathermap.org.

Writing main.py

import os
import httpx
from openclaw.skill import SkillBase, tool

class MyWeatherSkill(SkillBase):
    
    def __init__(self):
        self.api_key = os.environ.get("WEATHER_API_KEY")
        self.base_url = "https://api.openweathermap.org/data/2.5"
    
    @tool(name="get_weather")
    async def get_weather(self, location: str, units: str = "celsius") -> dict:
        """Get current weather for a location."""
        unit_param = "metric" if units == "celsius" else "imperial"
        
        async with httpx.AsyncClient() as client:
            response = await client.get(
                f"{self.base_url}/weather",
                params={
                    "q": location,
                    "appid": self.api_key,
                    "units": unit_param
                }
            )
            response.raise_for_status()
            data = response.json()
        
        return {
            "location": data["name"],
            "temperature": data["main"]["temp"],
            "units": units,
            "description": data["weather"][0]["description"],
            "humidity": data["main"]["humidity"]
        }

def create_skill():
    return MyWeatherSkill()

requirements.txt

httpx>=0.26.0

Testing Your Skill

# Install your skill locally
python -m openclaw skill install /path/to/my-skill

# Test it works
python -m openclaw skill test my-weather-skill

# In a conversation, ask:
# "What's the weather in Tokyo?"

Publishing to ClawHub

  1. Create a GitHub repository for your skill
  2. Register as a ClawHub publisher at clawhub.io/publish
  3. Submit your skill via python -m openclaw skill publish
  4. ClawHub runs automated security scans and human review (1–3 days)
  5. Once approved, your skill is live on ClawHub

Best Practices

  • Handle errors gracefully: Return informative error messages rather than raising exceptions
  • Validate inputs: Check parameters before making API calls
  • Use async: All skill functions should be async def for non-blocking operation
  • Document tool descriptions well: The LLM uses these to decide when to call your tool
  • Keep permissions minimal: Only request what you actually need

Frequently Asked Questions

Can skills maintain state between calls?

Yes. The SkillBase class provides access to persistent storage via self.storage.set(key, value) and self.storage.get(key). State persists across restarts.

Can my skill access other installed skills?

Yes. Use self.skill_manager.call_skill("other-skill", "tool_name", **kwargs) to call another skill's tools from within your skill.

How are skills monetized on ClawHub?

ClawHub supports one-time purchase, subscription, and usage-based pricing. ClawHub takes a percentage (currently 20%) of skill sales. Free skills are always available.

nacre.sh

Run OpenClaw without the server headaches

Dedicated instance, automatic TLS, nightly backups, and 290+ LLM integrations. Live in under 90 seconds from $12/month.

Deploy your agent →

Related posts