Skills

Plugin-namespaced skills

Skills are markdown templates the agent loads on demand. A plugin can ship its own skills under a namespace — they're explicit-load only, so they don't bloat the system prompt, and they travel with your plugin's install/uninstall lifecycle.

What plugin skills are

Skills are markdown files (SKILL.md) that teach the agent how to do something — a workflow recipe, a domain template, a checklist. The agent loads them via the built-in skill_view tool when it decides the instructions are relevant to the current task.

Plugin skills differ from regular skills in two ways:

  • Namespaced — addressed as <plugin>:<name>. So my-plugin's onboard skill becomes my-plugin:onboard.
  • Explicit-load only — they don't appear in the system prompt's <available_skills> index. The agent has to either know the qualified name (e.g. from your plugin's tool description) or list plugin skills to discover them.
Why explicit-load?
The system prompt is cached across turns to keep token costs low. Adding/removing skills changes the prompt prefix and breaks the cache. Plugin skills stay out of the index so installing a plugin doesn't invalidate every other plugin's cached prompt.

Tool vs. skill — when to use which

Both tools and skills extend the agent's capabilities. Picking the right one matters for UX, cost, and reliability.

Use a tool when…Use a skill when…
The action has a deterministic outcome (read DB, call API, spawn process)The output is a generated artifact whose form depends on context (a draft email, a code review, a meeting summary)
You want fast, cheap, deterministic behavior — slash command levelYou want the LLM to reason and adapt the template to the current input
The work happens outside the model — file IO, network, shellThe work happens inside the model — phrasing, structuring, applying a style guide

Many plugins ship both: a tool that fetches structured data, and a skill that templates how to present it.

Authoring SKILL.md

A skill is a single markdown file with optional YAML frontmatter. The frontmatter declares metadata; the body is the prompt-grade instructions the agent will read.

markdown
---
name: customer-onboarding
description: Welcome a new customer based on their plan tier
---

# Customer onboarding flow

When a customer signs up, send them a welcome message that:

1. References their **plan tier** (Starter / Pro / Business)
2. Highlights the top 3 features they get
3. Links to the relevant Quickstart guide
4. Suggests a 15-minute onboarding call for Business+ tiers

## Tone

Warm but professional. Avoid emojis. Sign as "The Acme Team."

## Tier-specific content

### Starter
- Self-serve quickstart link
- Link to community Slack
- No onboarding call offer

### Pro
- Self-serve quickstart link
- Mention email support
- Optional onboarding call offer

### Business
- Personalized onboarding call ask
- Slack channel for direct support
- Dedicated CSM intro

Frontmatter fields:

  • name — short identifier. Falls back to the directory name if omitted.
  • description — one-liner. Used by theskill_view tool when the user runs flowly skills list.
Write for the agent, not the user
Skills are read by the LLM, not displayed verbatim. Write imperatives ("send a message that…"), not user-facing copy ("Welcome to Acme!"). The agent renders the actual user-facing output based on your instructions and the current context.

Registering the skill

Inside register(ctx), point at the SKILL.md file shipped with your plugin:

python
from pathlib import Path

def register(ctx):
    ctx.register_skill(
        name="customer-onboarding",
        path=Path(__file__).parent / "skills" / "customer-onboarding" / "SKILL.md",
        description="Welcome a new customer based on their plan tier",
    )

Recommended directory layout:

text
my-plugin/
├── plugin.yaml
├── __init__.py
└── skills/
    ├── customer-onboarding/
    │   └── SKILL.md
    ├── churn-recovery/
    │   └── SKILL.md
    └── upsell-script/
        └── SKILL.md

One SKILL.md per directory keeps room for asset files (images, examples, sub-templates) alongside it. The directory name doesn't have to match the registered name — the registered name is what shows up in the qualified address.

Register only when path exists
register_skill checks the path at registration time. If SKILL.md is missing, your register(ctx) raises FileNotFoundError, which fails the entire plugin load. Wrap optional skills in a try/except, or guarantee they ship with the plugin.

How the agent loads it

The agent loads a plugin skill the same way it loads any skill — via the skill_view built-in tool — but with the qualified namespace:

text
# In an agent turn
skill_view(name="my-plugin:customer-onboarding")
→ returns the SKILL.md body, which the agent then reads as instructions

For the agent to know your skill exists, you have two options:

  1. Mention it in a tool description. If your plugin also registers a tool, include something like "After successfully running this tool, consider loading my-plugin:customer-onboarding for the response template." The agent picks up the cue.
  2. The agent lists plugin skills. The skills_list built-in tool can include plugin skills when called with include_plugin_skills=true. The agent uses this when explicitly asked "what plugin skills do I have?".

Common patterns

  • Tool + skill pair. Tool fetches data; skill templates the output. Example: crm_fetch_account tool returns raw JSON; crm:account-summary skill says how to present it for QBR slides.
  • Workflow checklist. The skill is a sequenced list the agent walks through in order. Useful for compliance work ("before sending an email externally, check…").
  • Style guide. The skill describes voice, tone, and forbidden phrases. The agent reads it before drafting any user-facing copy in your plugin's domain.
  • Domain glossary. Internal terminology, product names, customer code-names. The agent loads it to ground responses in your team's vocabulary.
Skill skill suggestion
If your plugin's most common use is "agent generates X for me", ship a skill describing what good X looks like. It's the cheapest way to upgrade output quality without prompt engineering inside the tool description.