Metadata for a skill per Agent Skills specification (https://agentskills.io/specification).
Skills middleware for loading and exposing agent skills to the system prompt.
This module implements Anthropic's agent skills pattern with progressive disclosure, loading skills from backend storage via configurable sources.
Skills are loaded from one or more sources - paths in a backend where skills are organized. Sources are loaded in order, with later sources overriding earlier ones when skills have the same name (last one wins). This enables layering: base -> user -> project -> team skills.
The middleware uses backend APIs exclusively (no direct filesystem access), making it portable across different storage backends (filesystem, state, remote storage, etc.).
For StateBackend (ephemeral/in-memory):
SkillsMiddleware(backend=StateBackend(), ...)
Each skill is a directory containing a SKILL.md file with YAML frontmatter:
/skills/user/web-research/
├── SKILL.md # Required: YAML frontmatter + markdown instructions
└── helper.py # Optional: supporting files
SKILL.md format:
---
name: web-research
description: Structured approach to conducting thorough web research
license: MIT
---
# Web Research Skill
## When to Use
- User asks you to research a topic
...
Parsed from YAML frontmatter per Agent Skills specification:
name: Skill identifier (max 64 chars, lowercase alphanumeric and hyphens)description: What the skill does (max 1024 chars)path: Backend path to the SKILL.md filelicense, compatibility, metadata, allowed_toolsSources point to skill directories in the backend. Each source is either a bare
path or a (path, label) tuple. With a bare path the label is derived from the
last path component capitalized (e.g., /skills/user/ -> User), with two
special cases: built_in_skills collapses to Built-in, and a literal skills
leaf climbs one level so ~/.claude/skills renders as Claude rather than the
duplicative Skills Skills. Pass an explicit tuple to disambiguate sources
whose leaf directories would collide (e.g. user- vs project-scoped
.claude/skills).
Example sources:
[
"/skills/user/",
"/skills/project/",
("/home/me/.claude/skills", "User Claude"),
("/repo/.claude/skills", "Project Claude"),
]
All paths use POSIX conventions (forward slashes) via PurePosixPath:
from deepagents.backends.state import StateBackend
from deepagents.middleware.skills import SkillsMiddleware
middleware = SkillsMiddleware(
backend=my_backend,
sources=[
"/skills/base/",
"/skills/user/",
"/skills/project/",
("/repo/.claude/skills", "Project Claude"),
],
)