Skip to content
Subscribe

Building Custom Skills for OpenClaw

Skills are OpenClaw’s extension system. They’re the difference between an agent that “can use tools” and an agent that “knows how to book a meeting room” or “knows how to send an iMessage.” Skills package up context, scripts, and templates into reusable, shareable units.

If you find yourself pasting the same instructions to an agent repeatedly, that’s a skill waiting to be written.

A skill is a directory containing:

  1. SKILL.md — The instruction manual the agent reads before executing the skill
  2. Scripts — Helper programs the agent can run
  3. Templates — Output formats, config stubs, and reusable content
  4. Tests — Verification that the skill still works

When an agent encounters a task that matches a skill’s description, it reads SKILL.md and follows its instructions — using the scripts and templates packaged inside.

  • Directoryskills/
    • Directorytanner-rooms/
      • SKILL.md ← Agent reads this first
      • Directoryscripts/
        • reserve.py ← Booking automation
        • list-available.py ← Check availability
      • Directorytemplates/
        • confirmation.md ← Response format
      • Directorytests/
        • test-reserve.sh ← Verify it still works
      • README.md ← Human documentation

You could paste instructions directly into your agent prompt every time. Skills are better because:

They’re reusable. Write once, use in any agent. Your coding agent, your research agent, your CEO agent — all can use the same Slack skill without duplicating config.

They’re testable. A skill with a tests/ directory can be regression-tested. If an API changes, your test catches it before your agent silently fails.

They’re shareable. Push a skill to ClaWHub and other users can openclaw skill install slack-curator. No copy-pasting prompt engineering.

They’re maintainable. When Slack changes their API, you update one SKILL.md and one script — not every agent prompt that uses Slack.

SKILL.md is the heart of the skill. It’s what the agent actually reads and follows. Write it like you’re briefing a smart intern who’s never used this tool before.

A good SKILL.md has five sections:

# skill-name — Short description
## What This Skill Does
One paragraph. What problem does it solve? When should the agent
use it vs. something else?
## Prerequisites
- What needs to be installed
- What credentials need to be set
- What config files need to exist
## How to Use It
### Common Task 1
Step-by-step instructions. Include actual commands.
Reference scripts with relative paths: `./scripts/reserve.py`
Include expected output so the agent knows success.
### Common Task 2
...
## Script Reference
| Script | Purpose | Usage |
|--------|---------|-------|
| `scripts/reserve.py` | Book a room | `python3 scripts/reserve.py --room 210 --time 14:00 --duration 60` |
| `scripts/list-available.py` | Check availability | `python3 scripts/list-available.py --date 2026-03-27` |
## Error Handling
| Error | Cause | Fix |
|-------|-------|-----|
| `401 Unauthorized` | Session expired | Run `python3 scripts/login.py` first |
| `Room not available` | Already booked | Try adjacent time slots |
## Examples
Include 2-3 complete examples with full commands and expected output.
Real examples are worth more than abstract documentation.

Tutorial: Build a “GitHub Issues” Skill

Section titled “Tutorial: Build a “GitHub Issues” Skill”

Let’s build a real skill from scratch. This skill lets any agent read GitHub issues, comment on them, and close them.

  1. Create the skill directory

    Terminal window
    mkdir -p ~/clawd/skills/github-issues/scripts
    mkdir -p ~/clawd/skills/github-issues/templates
    mkdir -p ~/clawd/skills/github-issues/tests
  2. Write the main script

    ~/clawd/skills/github-issues/scripts/list-issues.sh:

    #!/bin/bash
    # list-issues.sh — List open GitHub issues for a repo
    # Usage: ./list-issues.sh owner/repo [--label bug] [--limit 10]
    REPO="${1:?Usage: list-issues.sh owner/repo}"
    LABEL="${3:-}" # Optional --label flag
    LIMIT="${5:-20}"
    if [ -z "$GITHUB_TOKEN" ]; then
    echo "Error: GITHUB_TOKEN not set in environment" >&2
    exit 1
    fi
    LABEL_FILTER=""
    if [ -n "$LABEL" ]; then
    LABEL_FILTER="&labels=${LABEL}"
    fi
    curl -s \
    -H "Authorization: token $GITHUB_TOKEN" \
    -H "Accept: application/vnd.github.v3+json" \
    "https://api.github.com/repos/${REPO}/issues?state=open&per_page=${LIMIT}${LABEL_FILTER}" \
    | jq '.[] | {number: .number, title: .title, labels: [.labels[].name], created_at: .created_at}'
    Terminal window
    chmod +x ~/clawd/skills/github-issues/scripts/list-issues.sh
  3. Write a comment script

    ~/clawd/skills/github-issues/scripts/comment.sh:

    #!/bin/bash
    # comment.sh — Add a comment to a GitHub issue
    # Usage: ./comment.sh owner/repo issue_number "Your comment text"
    REPO="${1:?Usage: comment.sh owner/repo issue_number comment}"
    ISSUE="${2:?Missing issue number}"
    COMMENT="${3:?Missing comment text}"
    curl -s -X POST \
    -H "Authorization: token $GITHUB_TOKEN" \
    -H "Accept: application/vnd.github.v3+json" \
    "https://api.github.com/repos/${REPO}/issues/${ISSUE}/comments" \
    -d "{\"body\": \"$COMMENT\"}" \
    | jq '{id: .id, html_url: .html_url}'
  4. Create a response template

    ~/clawd/skills/github-issues/templates/issue-summary.md:

    ## GitHub Issues Summary: {{REPO}}
    **Checked:** {{DATE}}
    **Open issues:** {{COUNT}}
    {{#each issues}}
    ### #{{number}}: {{title}}
    - **Labels:** {{labels}}
    - **Opened:** {{created_at}}
    - **Link:** https://github.com/{{../repo}}/issues/{{number}}
    {{/each}}
  5. Write the SKILL.md

    ~/clawd/skills/github-issues/SKILL.md:

    # github-issues — Read and manage GitHub issues
    ## What This Skill Does
    Lets agents read open GitHub issues, post comments, and close
    issues via the GitHub API. Use this when asked to:
    - Check what issues are open on a repo
    - Summarize or triage issues
    - Comment on an issue with a response or fix
    - Close resolved issues
    ## Prerequisites
    - `gh` CLI installed: `brew install gh` then `gh auth login`
    - OR GITHUB_TOKEN set in environment (from ~/.openclaw/.env)
    - `jq` installed: `brew install jq`
    ## How to Use It
    ### List open issues
    ```bash
    # All open issues
    bash ./scripts/list-issues.sh owner/repo
    # Filter by label
    bash ./scripts/list-issues.sh owner/repo --label bug --limit 5
    Terminal window
    bash ./scripts/comment.sh owner/repo 42 "Investigated this. The fix is in PR #43."

    Check issues using gh CLI (preferred when available)

    Section titled “Check issues using gh CLI (preferred when available)”
    Terminal window
    gh issue list --repo owner/repo --state open --limit 10
    gh issue view 42 --repo owner/repo
    gh issue comment 42 --body "Fixed in latest commit"
    ScriptPurposeKey Args
    scripts/list-issues.shList open issuesowner/repo [--label X] [--limit N]
    scripts/comment.shPost a commentowner/repo issue_number "text"
    ErrorCauseFix
    401 UnauthorizedBad tokenRe-run gh auth login
    404 Not FoundRepo doesn’t exist or no accessCheck repo name and permissions
    jq: command not foundjq not installedbrew install jq

    List top 5 bugs:

    Terminal window
    bash ./scripts/list-issues.sh facebook/react --label bug --limit 5

    Comment and close:

    Terminal window
    bash ./scripts/comment.sh myorg/myrepo 17 "Resolved in v2.3.1"
    gh issue close 17 --repo myorg/myrepo
  6. Write a test

    ~/clawd/skills/github-issues/tests/test-list.sh:

    #!/bin/bash
    # Tests that list-issues.sh returns valid JSON
    echo "Testing github-issues skill..."
    # Should return JSON array
    RESULT=$(bash scripts/list-issues.sh octocat/Hello-World --limit 2 2>&1)
    if echo "$RESULT" | jq -e '.' > /dev/null 2>&1; then
    echo "✓ list-issues returns valid JSON"
    else
    echo "✗ list-issues failed: $RESULT"
    exit 1
    fi
    echo "All tests passed."
  7. Register the skill with OpenClaw

    Add to ~/clawd/openclaw.json:

    {
    "skills": {
    "github-issues": {
    "path": "~/clawd/skills/github-issues",
    "description": "Read and manage GitHub issues",
    "triggers": ["github issues", "open issues", "check issues", "repo issues"]
    }
    }
    }

Before trusting a skill in production, test it:

Terminal window
cd ~/clawd/skills/github-issues
# Test the scripts directly
bash tests/test-list.sh
# Test via agent
openclaw chat main
> Use the github-issues skill to list the top 5 open issues in torvalds/linux

Watch for these failure modes:

  • Credential errors: Is GITHUB_TOKEN in your env? Does ~/.openclaw/.env export it?
  • Path errors: Scripts reference ./scripts/ — always run from skill root or use absolute paths
  • API changes: Check the script output against current API docs if something breaks

Some patterns show up in almost every skill:

Credential check at top of every script:

Terminal window
if [ -z "$GITHUB_TOKEN" ]; then
echo "Error: GITHUB_TOKEN not set. Add to ~/.openclaw/.env" >&2
exit 1
fi

Structured JSON output (agents parse this reliably):

Terminal window
# Prefer structured output over human-readable
echo '{"status": "success", "room": "210", "time": "14:00", "confirmation": "R-7821"}'

Retry logic for flaky APIs:

import time, requests
def with_retry(fn, retries=3, delay=2):
for i in range(retries):
try:
return fn()
except requests.HTTPError as e:
if e.response.status_code == 429:
time.sleep(delay * (i + 1))
else:
raise
raise Exception(f"Failed after {retries} retries")

When your skill is solid, share it:

Terminal window
# Package the skill
openclaw skill pack github-issues --version 1.0.0
# Publish to ClaWHub (requires account)
openclaw skill publish github-issues
# Others install with:
openclaw skill install your-username/github-issues

Good skills to publish:

  • Anything that requires non-obvious credential setup
  • Tools with complex APIs that take time to figure out
  • Workflow automations others likely need (booking systems, CRMs, etc.)
FilePurposeRequired?
SKILL.mdAgent instruction manual✅ Yes
scripts/Executable helpersRecommended
templates/Output formatsOptional
tests/Regression testsStrongly recommended
README.mdHuman documentationOptional (for sharing)

About the author: JD Davenport builds AI agent systems at OpenClaw. Follow on LinkedIn for updates on building AI agents for business.