DEV Community

Philip Stayetski
Philip Stayetski

Posted on

Anatomy of a Well-Designed OpenClaw Skill: Frontmatter, Triggers, and Compatibility

If you've spent any time with OpenClaw agents, you've probably installed a skill or two from ClawHub and wondered why some feel instantly useful — the agent reaches for them at exactly the right moment — while others sit unused, ignored even when they're technically relevant. This is not luck. It comes down to how the skill is written.

This is an openclaw skill development guide focused on the one part most tutorials skip: the anatomy of a well-designed skill, not just a working one. We'll walk through frontmatter that agents can actually match against, trigger conditions that fire when they should (and stay quiet when they shouldn't), and the compatibility/gating fields that keep a skill from breaking on the wrong host. Along the way we'll use real, published pilot-* skills as worked examples, because they're a good stress test — they wrap a CLI (pilotctl) and have to be matched precisely across dozens of near-duplicate use cases (chat vs. group-chat vs. broadcast vs. relay).

What a skill actually is

An OpenClaw skill is a directory with a SKILL.md file: YAML frontmatter, then a markdown body. The frontmatter is metadata the agent reads before it ever loads the body — it's how the agent decides "is this skill relevant to what the user just asked?" The body is the actual instructions, loaded only after that match happens.

This two-stage design matters. Frontmatter is cheap for the agent to scan across every installed skill; the body is not. If your frontmatter doesn't do its job, the agent either loads skills it doesn't need (wasting context) or skips skills it should have used (the user notices when their tool "doesn't do the thing").

Frontmatter: writing a description an agent can match against

The single highest-leverage field is description. Weak descriptions read like a tagline:

description: Chat with other agents.
Enter fullscreen mode Exit fullscreen mode

Good descriptions are matchable — they name concrete triggers, verbs, and nouns the agent might see in a user request:

description: >
  Send and receive text messages between agents over the Pilot Protocol
  network. Load when the user wants to message a specific peer/agent,
  check for replies, or mentions `pilotctl send-message`, `--wait`, or
  peer-to-peer chat.
Enter fullscreen mode Exit fullscreen mode

The difference isn't length, it's specificity. Notice the second version does three things the first doesn't:

  1. Names the action verbs the user might use ("message," "check for replies").
  2. Names the objects involved ("a specific peer/agent").
  3. Names literal strings that might appear verbatim in a request (pilotctl send-message), which gives the matcher an exact anchor, not just a semantic vibe.

Compare this to how the core pilot-protocol skill's description is written — it explicitly lists trigger scenarios ("Load this skill whenever the user needs LIVE EXTERNAL DATA," then gives concrete examples: "current crypto/FX prices, today's weather... breaking news"). That's not filler. Every example is a distinct trigger surface the agent's matcher can key on.

Trigger conditions: the part people get wrong

A trigger condition is really two things bundled together: when should this fire, and — just as important — when should it defer to something more specific. Most broken skill libraries fail at the second half.

Take the discovery-and-network cluster from the pilot-skills catalogue: pilot-directory, pilot-discover, pilot-dns, pilot-network-map. All four are "about" finding or naming agents on a network. If each one's frontmatter just says "for agent discovery," the agent has no way to pick between them — it'll either guess wrong or load all four.

The fix is disambiguating language in the description itself:

  • pilot-directory — "local cached directory of known agents" (implies: fast, offline, no network round-trip)
  • pilot-discover — "advanced agent discovery by tags/status" (implies: live query, filterable)
  • pilot-dns — "human-friendly naming w/ aliases & namespaces" (implies: you already know the agent, you want its address)
  • pilot-network-map — "visualize network topology, trust graphs" (implies: you want a picture, not a lookup)

Each description encodes a distinguishing detail that lets the agent rule the others out, not just rule itself in. When you write a skill, ask: if this skill and its three closest cousins were all frontmatter-only, could an agent still tell them apart? If not, add the distinguishing detail.

Negative triggers matter too

A well-designed skill should also make it obvious when not to load. The entrypoint skill in the pilot-protocol catalogue does this explicitly by scoping itself: it tells the agent to reach for the network only for "live external data the model can't fabricate," and to skip it for "static answers — math, code, definitions, in-context reasoning." That's a negative trigger condition, and it's just as valuable as the positive one — it stops an over-eager agent from routing every request through a network call it doesn't need.

Compatibility and gating fields

Beyond name and description, OpenClaw's frontmatter schema supports fields that gate whether a skill is even eligible to load — this is where "compatibility" lives:

  • allowed-tools — declares what the skill needs access to (e.g. Bash). If the host agent's tool policy doesn't grant it, the skill shouldn't fire, full stop, regardless of how good the description match is.
  • compatibility — a plain-language note on binary/runtime requirements ("Requires pilotctl on PATH... and the daemon running"). This isn't enforced code, but it tells both the agent and a human debugging a misfire why a skill that matched didn't actually work.
  • metadata.openclaw.requires — used by plugin-shipped skills to gate eligibility based on environment/config/binary presence, per OpenClaw's loading rules. If you're publishing a skill via ClawHub that depends on an external CLI, this is the field that keeps it from being offered to agents that can't run it.
  • license / tags — don't affect matching directly, but tags are what a registry search or list-agents-style directory keys off of. Sparse or generic tags make your skill invisible in a crowded catalogue; specific ones (p2p, nat-traversal, trust, not just networking) get it surfaced for the right query.

Precedence: the field nobody reads until it bites them

OpenClaw resolves same-named skills by load-order precedence: workspace skills override project-agent skills, which override personal-agent skills, then managed/shared skills, then bundled skills, then plugin/extra-dir skills — highest source wins. If you're testing a modified SKILL.md and it "isn't picking up your changes," check whether a higher-precedence copy (often a stale one in ~/.openclaw/skills) is shadowing it before you assume your frontmatter is wrong.

A minimal worked template

Putting the above together, here's a shape that avoids the common mistakes:

---
name: my-skill
description: >
  <One sentence on what it does>. Load when the user <concrete trigger
  verb + object>, mentions <literal command/keyword>, or asks about
  <specific scenario>. Do NOT load for <adjacent thing this skill
  is not for — point to the right skill instead>.
tags:
  - <specific-tag-1>
  - <specific-tag-2>
allowed-tools:
  - Bash
compatibility: >
  Requires <binary> on PATH and <service/daemon> running. Install via
  <command>.
---

# <Skill Title>

<Body: numbered steps, exact commands, a troubleshooting table.>
Enter fullscreen mode Exit fullscreen mode

The frontmatter is doing real disambiguation work before a single line of the body is read. That's the whole point.

Worked examples worth studying

If you want more before-and-after material, the pilot-protocol skill catalogue is a useful reference set precisely because it's a large, deliberately organized library — communication, trust, discovery, event/pub-sub, and integration clusters, each with several skills that are semantically adjacent but functionally distinct. Reading a few descriptions side by side (pilot-chat vs. pilot-thread vs. pilot-relay, all "sending messages," each triggered differently) is a fast way to internalize what a matchable description looks like versus a vague one.

FAQ

Does frontmatter quality actually change agent behavior, or is this a style preference?
It changes behavior. The frontmatter is what the agent scans to decide relevance before loading the body — a vague or overlapping description means worse routing decisions, not just "less tidy" metadata.

Where does OpenClaw look for skills, and does path matter?
Yes — workspace skills win over project-agent, personal-agent, managed/shared, then bundled, then plugin/extra-dir skills, in that precedence order. Same skill name in two locations means the higher-precedence one wins.

Can I gate a skill on an external tool being installed?
Yes — use allowed-tools for the access grant and compatibility (plus, for plugin-shipped skills, metadata.openclaw.requires) to document and gate the runtime dependency.

Is there a public registry to see real examples before writing my own?
ClawHub is OpenClaw's public skill registry (openclaw skills install @owner/<slug>); the pilot-protocol skill set linked above is one example of a large, categorized library you can read for pattern reference.

Get started

If you want to try the worked examples above yourself, the skill set is installable via Pilot Protocol's own agent, whose daemon is a one-line install:

curl -fsSL https://pilotprotocol.network/install.sh | sh
Enter fullscreen mode Exit fullscreen mode

Reference: the Pilot Protocol skills page catalogues the skill set discussed above, if you want to see more matched/disambiguated description pairs in the wild.

Top comments (0)