8 minutes read

Modern AI agents are capable, but they aren’t experts at everything out of the box. You could stuff brand guidelines and team policies into a system prompt, but that bloats every conversation and doesn’t scale across tasks.

Agent skills solve this problem with a lightweight, open format that packages specialized knowledge and workflows into reusable folders. Originally developed by Anthropic and released as an open standard, the format has since been adopted by many agentic tools and clients. In this topic, we'll explore what skills are, how they're organized, and how to write ones that agents can actually find and use.

What are agent skills?

A skill is simply a folder containing a SKILL.md file, along with any optional supporting materials. Think of it as a self-contained playbook: it tells the agent what a task involves, when to reach for the skill, and how to carry it out step by step.

The key idea behind skills is progressive disclosure. Rather than load everything into the context window at once, agents pull the information in tiers:

  • At startup, the agent reads only the name and description of each available skill — roughly 100 tokens each. This is just enough to decide when a skill might be relevant.

  • When a user's request matches a description, the agent loads the full SKILL.md body into context and follows its instructions.

  • Only if the task requires them does the agent open supporting files, such as references or scripts.

This layered approach keeps the context window lean.

Skills directory structure

At a minimum, a skill is a directory named after the skill, containing a single SKILL.md file. As tasks grow more complex, you can add optional subdirectories to hold related resources:

skill-name/
├── SKILL.md        # Required: metadata + core instructions
├── scripts/        # Optional: executable code (Python, Bash, etc.)
├── references/     # Optional: supplementary docs, schemas, cheatsheets
└── assets/         # Optional: templates, static files, sample data

Each optional directory has a distinct role:

  • scripts/ holds executable code — small command-line utilities the agent can run instead of reasoning through a task manually.

  • references/ contains knowledge the agent reads into its context only when needed: API guides, policy documents, worked examples, or data schemas.

  • assets/ stores static files used in the output, such as document templates, brand files, or diagrams.

You aren't limited to these three names, but following the convention makes your skill easier for others to understand. Skill folders are typically stored in these locations: .cursor/skills/, .claude/skills/, .codex/skills/, .agent/skills/ and .junie/skills/ directory. The folders can be project- or user-scoped.

A closer look at SKILL.md

The SKILL.md file has two parts: YAML frontmatter enclosed in --- markers, followed by a Markdown body with the instructions. Here’s a minimal example:

---
name: code-reviewer
description: Reviews code for bugs, security issues, and style violations. Use when the user asks to review code, check a pull request, or find problems in a file.
---

# Code Reviewer

When reviewing code, work through the following steps:

1. Read the target file or diff in full before commenting.
2. Flag bugs and security issues first, then style concerns.
3. Reference the checklist in `references/checklist.md` for project conventions.
4. Summarize findings grouped by severity.

Only two frontmatter fields are required. The name field must contain only lowercase letters, numbers, and hyphens (1–64 characters, no consecutive hyphens). Additionally, it must exactly match the parent folder name. A skill named code-reviewer has to live in code-reviewer/SKILL.md.

The description is the single most important field because it is one of the only things the agent sees before activating the skill. Therefore, it must state both what the skill does and when to use it. A vague description means the skill never triggers; an overly broad one means it fires when it shouldn't.

You can also have additional fields in the front matter, but these are not required: license, compatibility indicating environment requirements, metadata for arbitrary information, and allowed-tools.

The Markdown body is where you place the actual procedure. This section should be focused; roughly around 500 lines is a good rule of thumb. For lengthy details, you can offload them into references/ files that the agent loads only when required.

Scripts

Sometimes a task is deterministic and better handled by code than by reasoning. Extracting text from a PDF, validating a JSON payload, or generating a file from a template are all things a small script can do reliably every time. That's where the scripts/ directory comes in.

The recommended pattern is to design scripts as tiny command-line interfaces (CLIs). Your SKILL.md then simply instructs the agent to invoke them:

## Extracting form fields

To read the fillable fields from a PDF, run the bundled script:

    python scripts/extract_fields.py <path-to-pdf>

The script prints a JSON list of field names. Use these names when filling the form.

This keeps the agent's context clean — it doesn't need to hold the script's internals in memory, only the knowledge that the tool exists and how to call it. It also makes results reproducible, since executing code doesn't drift the way generated reasoning can.

Best practices

Once a SKILL.md is loaded, its contents share the context window with the ongoing conversation and other active skills. Keep it brief. Focus strictly on information the agent wouldn't know without the skill, such as project-specific conventions, rather than general programming knowledge:

<!-- Too verbose — the agent already knows how to write generic error handling -->
## API Requests

When making requests to our internal API, network issues or timeouts can sometimes occur.
You should handle errors appropriately and make sure to implement retry logic just in case.

<!-- Better — provides the exact project pattern and concrete edge cases -->
## API Requests

Wrap all internal API calls with the `@retry` decorator from the `utils.network` module. 
This automatically handles our standard HTTP 429 rate limits.

```python
from utils.network import retry
import httpx

@retry(max_attempts=3)
def fetch_user_data(user_id: str):
    return httpx.get(f"<https://api.internal/users/{user_id}>")

The description field drives discovery. Test it by running both prompts that should trigger the skill and those that shouldn't. Then, refine the text until the agent activates it accurately. A description that only says what the skill does, without saying when to reach for it, leaves the agent guessing:

# Too vague — no cue about when this applies, so it rarely triggers
description: Helps with database work.

# Better — states the task and the triggering conditions
description: Generates and reviews Alembic migrations for our Postgres schema. Use when the user adds a model, alters a column, or asks to create a migration.

When a workflow has multiple valid approaches, provide a clear default path. Offering options without a recommendation leads the agent to waste time guessing and trying different methods before one succeeds.

<!-- No default — the agent has to pick, and may try several before one works -->
## Running tests

You can run the suite with pytest, tox, nox, or the Makefile target.

<!-- Better — names the default and reserves the alternative for a specific case -->
## Running tests

Run `pytest -q` from the project root. Use `tox` only when you need to check
compatibility across multiple Python versions.

Keep the high-level steps and tool commands in SKILL.md, but push lengthy materials like database schemas, API specs, or brand guidelines into the references/ directory. The agent will only pay the token cost to read those files when the task actually requires them.

<!-- Inlined — a 300-line schema sits in context on every activation -->
## Order events

The order event payload has the following fields:
- order_id (string, UUID) ...
- customer (object) ...
  ... 300 more lines ...

<!-- Better — a pointer the agent follows only when it needs the detail -->
## Order events

Order events follow the schema in `references/order-event.schema.json`.
Read it before constructing or validating a payload.

The most reliable way to write a skill is to complete the task with an agent first. Run through the scenario using the models you plan to deploy, note where you have to manually correct the agent's behavior, and add those specific corrections directly into the skill instructions.

Conclusion

Agent skills are an elegant answer to a practical problem: how to give agents specialized expertise without overwhelming their context. At their core, they're just folders with a SKILL.md file, optionally accompanied by scripts/, references/, and assets/. The YAML frontmatter — especially the description — controls discovery, while the Markdown body and supporting files deliver the how-to. By writing concise, specific skills and leaning on progressive disclosure, you can extend an agent's capabilities in a way that's reusable, portable, and easy to maintain across the growing ecosystem of tools that support the format.

4 learners liked this piece of theory. 2 didn't like it. What about you?
Report a typo