Last week I needed my OpenClaw agent to do something it couldn't do out of the box — interact with a custom API I run for my side project. I had two options: ask it to figure it out every time (slow, inconsistent), or build a skill once and let it call that skill reliably.
I chose option two. Thirty minutes later, I had a working skill. Here's exactly what I learned about the structure that makes OpenClaw skills actually work — no fluff, no guessing.
The Problem That Made Me Build a Skill
My OpenClaw agent handles a lot of infrastructure tasks. But I run a small onchain service that requires checking wallet balances, submitting transactions, and monitoring onchain events. Every time I asked the agent to "check my wallet status," it would either hallucinate a response or ask me to run a command manually.
I wanted this:
User: Check my wallet status
Agent: [calls skill] → reads wallet → returns real data
Not this:
User: Check my wallet status
Agent: I don't have access to your wallet...
The gap wasn't capability. It was structured, trusted tool access. Skills are how you close that gap in OpenClaw.
What a Skill Actually Looks Like
An OpenClaw skill lives in a SKILL.md file. That's the whole contract — no config files, no registration commands, no npm install. You write the markdown, OpenClaw reads it, and the agent learns what it can do.
Here's the skeleton I now use for every skill:
---
name: my-skill
description: Use this when the user wants to X.
---
# My Skill
[Detailed description of what this skill does]
## Quick Start
[Example prompts and expected behavior]
## Setup
[Any required configuration]
That looks simple because it is simple. But the description field in the YAML frontmatter is the most important part — it's what the agent uses to decide when to use your skill. Write it as a decision tree: "Use this when the user wants to [X], [Y], or [Z]."
Adding Tools to a Skill
Skills can also expose actual executable tools. Here's the format OpenClaw expects:
## Tools
### my-tool
- description: what this tool does
- args:
- name: arg1
type: string
required: true
- name: arg2
type: number
required: false
- script: |
#!/bin/bash
echo "arg1 is $arg1"
The agent can then call my-tool with the appropriate arguments. The tool execution happens in a sandbox — so whatever script you write, it runs isolated from the rest of the system.
Here's a real example from a wallet-checking skill I built:
## Tools
### check-balance
- description: Check ETH or token balance for a given wallet address
- args:
- name: address
type: string
required: true
- name: token
type: string
required: false
- script: |
#!/bin/bash
ADDRESS="$address"
TOKEN="${token:-ETH}"
curl -s "https://api.example.com/balance/$ADDRESS?token=$TOKEN"
Now when the agent needs to check a balance, it has a trusted tool for it. It doesn't guess. It calls the tool, gets the result, and responds with actual data.
The Three Rules That Actually Matter
After building five or six skills, I noticed a pattern in the ones that worked versus the ones the agent ignored or misused.
Rule 1: description in frontmatter is a decision filter, not a summary.
Write it like: "Use this when the user wants to check their wallet balance, submit a transaction, or view recent onchain activity." Not: "This skill checks wallet balances."
The agent uses that frontmatter description to match user intent. Vague descriptions get ignored or misrouted.
Rule 2: one skill, one domain.
Don't build a mega-skill that does everything. A skill for wallet operations, a separate skill for database queries, a third for notification routing. The agent can combine them. But a single 800-line skill that does twelve unrelated things? The agent will use it wrong more often than right.
Rule 3: test prompts in the Quick Start section.
This one I wish I'd figured out sooner. Add three to five example prompts in the skill file. The agent uses these as reference patterns. When a user asks something similar to those examples — even if the wording is different — the agent can pattern-match to the right skill.
## Quick Start
Check your ETH balance:
What's my ETH balance?
Check a specific token:
Check my USDC balance
What OpenClaw Does With Your Skill
When OpenClaw loads, it indexes every SKILL.md it finds in the configured skills directory. The agent's system prompt gets augmented with the skill descriptions. When a user message matches a skill's description, the agent pulls in the full skill content and uses it to respond or call tools.
There's no hot-reload magic you need to trigger. Drop the file in, the next conversation picks it up. Edit it, same thing — the next conversation reflects the changes.
This simplicity is what makes it work. There's no skill registry to update, no version number to increment, no plugin API to learn. Just markdown with a specific structure.
What I Learned
Building a custom skill turned out to be less about OpenClaw internals and more about articulating what you want the agent to know how to do. The hardest part was writing the description field precisely enough that the agent would correctly route requests to it — and that forced me to actually think about what the skill should and shouldn't handle.
If you're running OpenClaw and you find yourself repeatedly telling your agent "no, not like that, you need to use X instead of Y" — that's a skill waiting to be built. Thirty minutes of structure saves hours of correction.
The skill I built for my wallet API now handles 90% of the onchain queries I used to do manually. The agent doesn't have to guess anymore. It knows exactly where to look.
That's the point of skills. Not more features. More reliable features.
If you want the exact SKILL.md template I use as a starting point, drop a comment and I'll share the repo.
Top comments (0)