SkillsMiddleware(
self,
*,
backend: BackendProtocol,
sources: Sequence[SkillSource],
system_prompt:| Name | Type | Description |
|---|---|---|
backend* | BackendProtocol | Backend instance (e.g. |
sources* | Sequence[SkillSource] | List of skill sources. Each entry is either a bare path (e.g. |
system_prompt | str | None | Default: SKILLS_SYSTEM_PROMPTSystem-prompt fragment template. Must contain
|
tools | Sequence[BaseTool | Callable[..., Any]] | SkillToolResolver | None | Default: None |
| Name | Type |
|---|---|
| backend | BackendProtocol |
| sources | Sequence[SkillSource] |
| system_prompt | str | None |
| tools | Sequence[BaseTool | Callable[..., Any]] | SkillToolResolver | None |
Middleware for loading and exposing agent skills to the system prompt.
Loads skills from backend sources and injects them into the system prompt using progressive disclosure (metadata first, full content on demand).
Skills are loaded in source order with later sources overriding earlier ones.
Skills are loaded once per thread and cached in state. To pick up skills
added, edited, or deleted since then, set skills_metadata to None:
agent.invoke({"messages": messages, "skills_metadata": None}, config)
# or without a run
agent.update_state(config, {"skills_metadata": None})Example:
from deepagents.backends.filesystem import FilesystemBackend
backend = FilesystemBackend(root_dir="/path/to/skills")
middleware = SkillsMiddleware(
backend=backend,
sources=[
"/path/to/skills/user/",
"/path/to/skills/project/",
# Pass a (path, label) tuple to disambiguate sources whose
# leaf directories would otherwise collide
("/home/me/.claude/skills", "User Claude"),
("/repo/.claude/skills", "Project Claude"),
],
)
A skill can list the tools its instructions use, separated by spaces, under
metadata.include_tools in its SKILL.md frontmatter:
metadata:
include_tools: create_customer_request list_customer_requests
Pass those tools as tools, either as a list or as a
SkillToolResolver that looks them up by name. The model sees a skill tool
only after it uses read_file on a skill that lists it, and only while that
read stays in context. Until then, calling the tool fails as an unknown tool.
include_tools can also list a tool passed to the agent rather than to
this middleware. If that tool is deferred
(extras={"defer_loading": True}), reading the skill discloses it
automatically.
create_deep_agent places this middleware for you. When composing
create_agent by hand, include FilesystemMiddleware, whose read_file
the model uses to read skills. Put this middleware after summarization and
any model fallback or routing middleware, so it sees the compacted
conversation and the model actually called, and before prompt caching:
create_agent(
model,
tools=[...],
middleware=[
FilesystemMiddleware(backend=backend),
...,
SummarizationMiddleware(...),
ModelFallbackMiddleware(...),
SkillsMiddleware(backend=backend, sources=["/skills/"], tools=[...]),
AnthropicPromptCachingMiddleware(),
],
)
See constructor for the full argument list.
Tools the model sees only after reading a skill that
lists them in metadata.include_tools.
A list of tools, or a SkillToolResolver that returns the tools
for a name. Plain functions in a list are converted to tools, as
create_agent does.