Skills System Internals: SKILL.md Format, Lazy Loading and Description Trigger Logic
Chapter 17: The Skills System โ SKILL.md Format, Lazy-Loading, and the description Trigger
Chapter Overview
Skills are one of OpenClaw's most original design contributions. If ACP answers the question "how do I call an external expert?", Skills answer the question "how do I inject domain knowledge into an Agent's behavior?". This chapter begins with the core metaphor, then walks through every field in the SKILL.md specification, explains the context-budget rationale behind lazy-loading, and examines how the model uses description to make activation decisions.
17.1 The Core Metaphor: Skills Are Textbooks
The best way to understand Skills is to abandon the "plugin" analogy. A plugin is executable code that extends a program's functional boundaries. Skills are fundamentally different:
Skills are textbooks, not plugins. They tell the Agent "when you encounter this kind of task, here is how you should think and operate" โ not "when the user invokes this command, run this code."
This distinction is critical:
| Dimension | Plugin mindset | Skills mindset |
|---|---|---|
| Execution | Code is called and runs | Guides the Agent's reasoning |
| Extension goal | Extend functionality | Extend knowledge |
| Activation | Explicit command | Model's semantic judgment |
| Stored content | Executable code | Operational guides, workflows, best practices |
| Failure mode | Runtime error | Poor guidance quality |
This metaphor implies that writing a good Skill and writing a good operations manual are fundamentally the same activity. Clear structure, precise description, concrete steps โ these writing principles apply equally to SKILL.md.
17.2 The Complete SKILL.md Field Specification
Every Skill is anchored by a SKILL.md file. The file consists of a YAML frontmatter block and a Markdown body.
Directory Structure
my-skill/
โโโ SKILL.md # Required: the core file
โโโ scripts/ # Optional: helper scripts
โโโ references/ # Optional: on-demand reference documents
โโโ assets/ # Optional: images, data files, etc.
Complete YAML Frontmatter Reference
---
name: my-skill-name # Required
description: | # Required (activation trigger)
Use this Skill when the user needs to do X.
It provides complete guidance for Y and Z.
user-invocable: true # Optional, default: true
disable-model-invocation: false # Optional, default: false
command-dispatch: tool # Optional
command-tool: "tool_name" # Required when command-dispatch is set
command-arg-mode: raw # Optional
metadata:
openclaw:
emoji: "๐ง"
os: darwin
requires:
bins:
- git
- node
anyBins:
- yarn
- npm
env:
- GITHUB_TOKEN
config:
- tools.git.enabled
primaryEnv: node
homepage: https://example.com
install:
- type: brew
pkg: my-tool
---
Field Reference
name (Required)
- Unique identifier for the Skill
- Used for referencing, overriding, and logging
- Use
kebab-case(e.g.,git-commit-helper) - Avoid collisions with existing Skills (override rules apply)
description (Required โ the activation trigger)
This is the most important field in SKILL.md. The model's decision to activate a Skill depends primarily on semantic matching against the description.
# Bad description (too vague)
description: Helps with code-related things
# Good description (precisely describes the trigger scenario)
description: |
Use this Skill when the user needs to create a GitHub Pull Request,
conduct code reviews, manage PR labels or reviewers, or ask about
PR best practices. Provides a complete PR workflow guide.
Description writing principles:
- Clearly state when the Skill should activate (trigger scenarios)
- Briefly state what the Skill provides (value proposition)
- Avoid vague terms ("various", "related", "general-purpose")
- Target 50โ150 characters: too long wastes context, too short reduces matching precision
user-invocable (Optional, default: true)
Controls whether users can invoke the Skill directly via a /skill-name slash command.
user-invocable: false # Only the model can auto-activate; users cannot invoke directly
Use case: background support Skills, auxiliary Skills that should not be manually triggered.
disable-model-invocation (Optional, default: false)
disable-model-invocation: true # Hide this Skill from the model's context entirely
When set to true:
- The Skill does not appear in the model's context (not even as metadata)
- The model will never auto-activate it
- Only accessible through an explicit slash command (
user-invocablemust be true) - Typical use: hiding internal tools, reducing context consumption, preventing accidental activation
command-dispatch (Optional)
command-dispatch: tool
When enabled, a slash command is routed directly to the specified tool, completely bypassing model reasoning. This means zero token consumption and minimal latency.
command-tool (Required when command-dispatch is set)
command-tool: "browser_action" # Tool to invoke when the slash command fires
command-arg-mode (Optional)
command-arg-mode: raw # Pass user-provided arguments verbatim to the tool
Other options:
parsed: parse arguments into structured format (default)raw: raw string, no transformation
17.3 metadata.openclaw Field Reference
metadata.openclaw contains OpenClaw-specific extension metadata controlling the Skill's platform integration behavior.
emoji
metadata:
openclaw:
emoji: "๐"
Icon displayed in ClawHub and the OpenClaw UI. Purely cosmetic; no functional impact.
os (Operating System Filter)
os: darwin # Only available on macOS
os: linux # Only available on Linux
os: win32 # Only available on Windows
# Omit = available on all platforms
When set, OpenClaw will not load this Skill on non-matching OS (not even metadata is injected).
requires (Dependency Gating)
The most complex and important sub-field. See section 17.4 for full coverage.
primaryEnv
primaryEnv: node # node / python / go / rust / java / etc.
Declares the Skill's primary technical environment. Used for ClawHub categorization and search filtering.
homepage
homepage: https://github.com/org/skill-repo
URL of the Skill's documentation or source code.
install (Auto-install Scripts)
install:
- type: brew
pkg: ffmpeg
- type: node
pkg: "@scope/package"
- type: go
pkg: github.com/org/tool@latest
- type: uv
pkg: my-python-tool
- type: download
url: https://releases.example.com/tool-v1.0-darwin-arm64
dest: ~/.local/bin/tool
chmod: "0755"
When a binary listed in requires.bins is missing, OpenClaw can automatically install the dependency using the install configuration.
17.4 requires: Four Types of Dependency Gating
The requires field defines the prerequisites for Skill activation. If conditions are not met, the Skill is not injected into context.
requires.bins (ALL must exist in PATH)
requires:
bins:
- git
- node
- docker
Every listed executable must be present in PATH; otherwise the Skill does not load. Use for Skills with hard binary dependencies.
requires.anyBins (AT LEAST ONE must exist)
requires:
anyBins:
- yarn
- npm
- pnpm
At least one must be present. Use for Skills that support multiple toolchains ("any package manager will work").
requires.env (Environment variables must be set)
requires:
env:
- GITHUB_TOKEN
- OPENAI_API_KEY
All listed environment variables must be set (non-empty). Common for Skills that require API keys.
requires.config (openclaw.json paths must be truthy)
requires:
config:
- tools.git.enabled
- features.experimental.acp
All listed openclaw.json config paths must exist and be truthy. Used for feature-flag control.
Comparison Table
| Type | Logic | Typical Use |
|---|---|---|
bins |
AND (all must exist) | Hard binary dependencies |
anyBins |
OR (at least one) | Multi-toolchain compatibility |
env |
AND (all must be set) | API key gating |
config |
AND (all must be truthy) | Feature flag control |
17.5 Lazy-Loading: Protecting the Context Budget
This is one of the most elegant engineering decisions in the Skills system.
The Problem: Context Budget Scarcity
A typical OpenClaw instance may have dozens or even hundreds of Skills installed. If every Skill's full content were injected into the model's context, it would consume a massive number of tokens โ crowding out genuinely useful content (code, conversation history, task descriptions).
The Solution: Lazy Loading
OpenClaw's loading strategy has two phases:
Phase 1: Metadata injection (always executed)
[Skill list in system prompt]
- git-helper: Use for Git operations (emoji: ๐ฟ, os: any)
- image-lab: Use for image processing (emoji: ๐ผ๏ธ, os: darwin)
- browser: Use for browser interactions (emoji: ๐, os: any)
...
Only injects: name + description + emoji (minimal tokens)
Phase 2: On-demand loading (only when needed)
When the model determines a Skill needs to be activated, OpenClaw reads the full SKILL.md content and injects it into context.
[Model determines git-helper should activate]
โ
OpenClaw reads git-helper/SKILL.md in full
โ
Full guidance content injected into current context
โ
Model continues with complete Skill knowledge
On-Demand Loading of references/ Files
Going further, files in the references/ directory are not injected even as metadata by default. They are only loaded when a Skill is activated and the Skill body explicitly references them.
my-skill/
โโโ SKILL.md โ Phase 1: only name+description injected
โโโ references/
โ โโโ api-spec.md โ Phase 3: loaded only when SKILL.md explicitly requests it
โ โโโ examples.md โ Phase 3: loaded only when SKILL.md explicitly requests it
Reference in SKILL.md body:
## Detailed API Specification
For the full API specification, read {baseDir}/references/api-spec.md
The model will proactively request this file when needed, implementing true Progressive Disclosure.
Quantifying Lazy-Loading Benefits
Assume 50 installed Skills, averaging 2,000 tokens each:
| Loading strategy | Context consumed | Remaining usable context (128k window) |
|---|---|---|
| Full load | 100,000 tokens | 28,000 tokens |
| Lazy load (metadata only) | ~2,500 tokens | ~125,500 tokens |
| Lazy load (after activation) | ~4,500 tokens | ~123,500 tokens |
Lazy loading improves context efficiency by roughly 44x.
17.6 description as a Trigger: The Model's Decision Logic
Understanding how the model decides to activate a Skill is essential for writing high-quality Skills.
The Trigger Decision Flow
User sends a message
โ
OpenClaw injects all Skills' name+description into the system prompt
โ
Model analyzes user intent
โ
Model evaluates semantic relevance for each Skill
โ
Relevance exceeds threshold โ request loading of full Skill content
โ
Loading complete โ model generates response guided by Skill content
The Semantic Matching Mechanism
The model performs semantic similarity judgment, not keyword matching. This means:
# Example 1: Keyword-dependent (not recommended)
description: For git commit and git push operations
# Example 2: Semantic coverage (recommended)
description: |
Use when the user needs to commit code changes, push to a remote
repository, create version tags, or ask about Git workflow best
practices. Covers commit message conventions, branch naming, and
conflict resolution.
Example 2 will also trigger when the user says "help me save these changes" (semantically related), while Example 1 will not.
description Optimization Techniques
Technique 1: Scenario-driven description Don't describe what the Skill is โ describe when the user needs it.
# Wrong approach
description: A collection of Docker container management tools
# Right approach
description: |
Use when the user needs to build Docker images, manage container
lifecycle, troubleshoot container crashes, optimize image size,
or design docker-compose configurations.
Technique 2: Include synonyms and hypernyms
description: |
Handle image and photo tasks: cropping, resizing, format conversion,
batch processing, watermarking, image compression and optimization.
(Applies to pictures / images / photos / screenshots)
Technique 3: Avoid excessive breadth
# Dangerous: too broad โ matches almost any task
description: Help users with various programming tasks
# Appropriate: clear scope boundaries
description: |
Specifically handles Python type annotation tasks: adding type hints,
running mypy type checking, fixing type errors, and understanding
generic syntax.
17.7 Five-Level Loading Priority and Override Rules
When a Skill with the same name exists in multiple locations, priority determines which version is active:
Priority Levels (Highest to Lowest)
1. Workspace-specific Skills
Location: <project-root>/.openclaw/skills/
Note: Project-specific; highest priority; fully overrides same-named global Skills
2. Workspace Agent Skills
Location: <project-root>/.openclaw/agents/<agent-name>/skills/
Note: Skills configured for a specific Agent
3. Shared Agent Profile Skills
Location: ~/.openclaw/profiles/<profile-name>/skills/
Note: Skills in a shared Agent Profile used across projects
4. Global OpenClaw Skills
Location: ~/.openclaw/skills/
Note: User's globally installed Skills (default location for clawhub install)
5. Bundled Skills + Custom Dirs
Location: OpenClaw built-ins + extraSkillDirs in openclaw.json
Note: OpenClaw's baseline Skill set
Override Example
Scenario: User has globally installed git-helper (priority 4)
Project has a custom git-helper at .openclaw/skills/ (priority 1)
Result: The project-level git-helper completely overrides the global one.
Within this project, the project-level version is loaded.
When switching to another project, the global version is loaded.
This design allows teams to customize Skill behavior per project without affecting other projects.
17.8 The {baseDir} Placeholder
{baseDir} is a special runtime placeholder in SKILL.md that is replaced with the absolute path of the Skill's directory when the Skill is activated.
Use Cases
Referencing files in references/:
## API Reference
For the full list of API parameters, see: {baseDir}/references/api-params.md
## Automation Script
The migration automation script is at: {baseDir}/scripts/run-migration.sh
Referencing assets:
## Architecture Diagram
Reference architecture: {baseDir}/assets/architecture.png
Scripts referencing other scripts:
# SKILL.md instructs the model to execute this script
bash {baseDir}/scripts/setup.sh
Why {baseDir} Is Necessary
Because a Skill can be installed in any location (global, project-level, custom directory), its absolute path cannot be determined at authoring time. {baseDir} ensures path references are always correct regardless of where the Skill is installed.
17.9 The Progressive Disclosure Design Philosophy
The entire Skills system embodies a core design principle: Progressive Disclosure.
Three-Layer Disclosure Structure
Layer 1 (always visible): name + description
โ The model knows "this capability exists"
Layer 2 (visible after activation): full SKILL.md body
โ The model knows "how to exercise this capability"
Layer 3 (visible on demand): references/ file content
โ The model gets "specific reference material needed during execution"
Design Intent
The three-layer structure's intent is: consume context only when needed. Most conversations only need Layer 1. Using a Skill consumes Layer 2. Only when deep reference material is truly required does the model consume Layer 3.
This mirrors the lazy-loading principle in software engineering, applied to AI context management.
17.10 Chapter Summary
- Skills are textbooks, not plugins: they guide the Agent's reasoning rather than executing code
- Core SKILL.md fields:
name(unique identity),description(activation trigger),metadata.openclaw(platform integration) - Lazy-loading reduces context consumption from "full load" to "on-demand", improving efficiency ~44x
descriptionis a semantic trigger โ describe "when the user needs this Skill", not what the Skill itself is- Five-level priority allows project-level Skills to override global ones, enabling fine-grained customization
{baseDir}ensures path references remain correct regardless of installation location- Progressive Disclosure's three-layer structure is the core mechanism for context budget protection
The next chapter moves into hands-on practice: complete SKILL.md code examples for all five writing patterns, guiding you through writing high-quality Skills from scratch.