Skip to content

Skills

Skills give the LLM modular “skills”—tool usage, workflows, best practices, guardrails, and more. Compared to stuffing everything in the prompt, Skills distill durable know-how and load on demand instead of every turn.

ESP-Claw uses Skills to manage context dynamically and extend the Agent—including driving hardware through documented tool flows.

Skills live on disk under /fatfs/skills by default. Use the Web config file manager to add or remove them.

  • Directoryfatfs
    • Directoryskills
      • skills_list.json stores the Skills list and metadata
      • cap_im_qq.md Skill for QQ IM usage
      • cap_lua_run.md Skill for running Lua scripts
      • cap_scheduler.md Skill for the scheduler usage
      • cap_router_mgr.md Skill for the Event Router rule management
      • lua_module_gpio.md Skill for the Lua GPIO module

Unlike Claude Agent Skills, ESP-Claw does not read Skill metadata from Markdown YAML front matter. All metadata belongs in skills_list.json.

skills_list.json format
{
  "skills": <{"id": "string", "file": "string", "summary": "string", "cap_groups"?: "string[]"}[]>
}
{
  "skills": [
    {
      "id": "cap_lua_run",          // <- unique Skill id
      "file": "cap_lua_run.md",     // <- Skill file name
      "summary": "Describes how to correctly use Lua scripts.", // <- Skill summary
      "cap_groups": ["cap_lua"]     // <- optional: capability groups opened when this Skill activates
    },
    ...
  ]
}

id and summary map to the Skill ID and summary shown to the model in the Skills catalog.

cap_groups is optional: a list of capability group ids. When the Skill activates, those groups become visible to the LLM (tools exposed); when the Skill deactivates, they leave that Skill’s visibility set. This binds “how to use tools” with “having the tools” for the same lifecycle so the model cannot call tools without the guide.

Skill files are Markdown. Spell out the skill—usage, workflow, best practices, rules—clearly. Example:

# Weather

Get current weather and forecasts through `cap_cli`. Support weather, forecast, temperature queries.

## When to use
When the user asks about weather, temperature, forecasts.

## How to use
1. Use `cap_cli` to run `time --now` and learn the current date
2. Use `cap_cli` to run `web_search --query "weather in [city] today"`
3. Extract temperature, conditions, and forecast from results
4. Present in a concise, friendly format

## Example
User: "What's the weather in Tokyo?"
-> cap_cli: `time --now`
-> cap_cli: `web_search --query "weather Tokyo today February 2026"`
-> "Tokyo: 8C, partly cloudy. High 12C, low 4C. Light wind from the north."

After activation, the Skill .md is injected into the chat, so write for the LLM, not for human developers skimming a repo.

Strong Skill docs include:

ElementPurpose
Scenario framingStates when to activate so the model can self-select
Invocation rulesParameter constraints, ordering, rate limits
JSON examplesCopy-ready tool payloads—not prose paraphrases
Error playbookFrequent errors and how to recover
Cross-tool notese.g. “Call X first to discover paths, then call this tool”

Here is a full template for a capability-backed Skill:

# My Feature

One sentence describing when this Skill should activate.

## Usage rules

- When calling `my_action`, `param` must be non-empty
- On failure, validate `param`, then retry once
- Never issue more than three calls in a row; wait ≥ 500 ms between attempts

## Example calls

Basic invocation:
```json
{"param": "hello"}
```

With optional fields:
```json
{"param": "hello", "mode": "fast"}
```

## Error handling

- `Error: param is required` — add `param`, then retry
- `Error: invalid state` — device not ready; tell the user to try later

lua_module_* Skills target LLM-authored Lua, not JSON tool calls like cap_* docs. Provide precise API references instead of generic prose.

Lua module Skill docs should cover:

ElementPurpose
Hardware summaryWhat it drives, which pins or buses
Init storyWhether require has side effects, extra setup steps
Full API tableParameters, returns, short Lua snippets per function
Usage rulesRate limits, dependencies (“initialize board_manager first”)
Failure modesCases that raise Lua errors
# myled

Controls a single LED connected to GPIO 2.

## Setup

No explicit init required. The module configures GPIO 2 on first `require`.

## API

### `myled.set(on)`

Turns the LED on or off.

- `on`: boolean

```lua
local myled = require("myled")
myled.set(true)   -- on
myled.set(false)  -- off
```

### `myled.get()` → boolean

Returns the current LED state.

## Rules

- The module only controls GPIO 2; there is no parameter to change the pin.
- Do not call `myled.set` more than once per 50 ms.

The lua_module_display Skill is a good model: it spells out each drawing helper, optional table fields, return values, and constraints such as “text is ASCII-only”—all mandatory context for code-generating models.

Split complex capabilities into multiple Skills that still bind the same cap_groups when scenarios differ:

{
  "skills": [
    {
      "id": "my_feature_basic",
      "file": "my_feature_basic.md",
      "summary": "Basic flows: simple actions",
      "cap_groups": ["cap_my_feature"]
    },
    {
      "id": "my_feature_advanced",
      "file": "my_feature_advanced.md",
      "summary": "Advanced flows: batching and recovery",
      "cap_groups": ["cap_my_feature"]
    }
  ]
}

Simple jobs activate only the Basic Skill to keep context lean; harder jobs pull in Advanced guidance on demand.

Skills usually capture repeatable work or guidance, so after a task you can ask the Agent to summarize and evolve them.

ask "search today's weather in Tokyo for me"
ask "turn the earlier city-weather lookup into a reusable skill"

Context can carry tools, requirements, and extra rules. But repeating every tool’s full manual every turn bloats context, hurts quality, and burns tokens.

Skills progressively disclose capabilities. Initially the model only sees the catalog entries with summaries. When a Skill is needed, the model activates it and receives the full document.

If cap_groups is set, activation also opens the matching capability groups so the LLM can call tools immediately—no separate manual enable. After the task, deactivate_skill drops the Skill and its tool visibility to keep context lean.