Recipe: Skills Auto-Injection¶
Goal¶
Automatically detect a skills MCP server and inject a skills catalog into the system prompt so the LLM knows which skills are available without an explicit tool call.
Prerequisites¶
- A skills MCP server that exposes
list_skillsandload_skilltools —doc-processing-std-tools0.2 or later (0.6.0 at the time of writing; its documentation is at https://doc-processing-std-tools.vercel.app/, the server at servers/skills and its verified toolkit versions at compatibility), or any server with the same contract. The server's name does not matter. DPTTOOLS_SKILLS_DIRset where the server runs, pointing at your skills directory: the server reads it, not the toolkit. For an in-process server that is this process's environment (an.envfile works); for anmcp_command/mcp_scriptserver it goes in the config'senv, because a subprocess does not inherit this process's variables (see Skills directory)
Basic usage¶
from doc_processing_toolkit import Agent
agent = Agent(
model="claude-sonnet-5",
instructions="You are a helpful assistant.",
tools=[
{
"type": "mcp_script",
"path": "skills_server.py",
"name": "skills-tools",
"env": {"DPTTOOLS_SKILLS_DIR": "/path/to/.agent_skills"},
}
],
)
result = await agent.run("What skills do you have available?")
print(result.output)
Skills auto-injection is enabled by default (auto_inject_skills=True). The agent detects the skills server, calls list_skills, and appends a catalog to the system prompt automatically. Every way of attaching the server works — an in-process FastMCP object, an mcp_command / mcp_script config, a pre-built session — since 0.5.3; before it, only a pre-built session whose name contained skill did (see the version note).
Expected system prompt output¶
When skills are detected, the system prompt is augmented with:
## Available Agent Skills
The following skills provide specialized instructions for specific tasks. When a
task matches a skill's description, load its full instructions before proceeding.
How to load a skill:
- Preferred: call the `load_skill` tool with the skill's name. The tool result
is wrapped in <skill_content>...</skill_content> tags and includes a list of
bundled resources (under <skill_resources>) and the skill's directory path.
Use the directory path to resolve any relative references inside the skill.
- Alternative: if you have a file-read tool, you may directly read the SKILL.md
at the listed `path`. Relative references inside the SKILL.md resolve
against the parent directory of that path.
<available_skills>
<skill name="my-data-analysis" path="/path/to/.agent_skills/my-data-analysis/SKILL.md">Analyzes CSV/Excel data and produces summary reports with charts.</skill>
<skill name="code-review" path="/path/to/.agent_skills/code-review/SKILL.md">Reviews code for bugs, security issues, and style violations.</skill>
</available_skills>
The LLM sees this catalog and can call load_skill to load full instructions for any skill it wants to use. The path attribute lets the model resolve relative resource references inside the SKILL.md without an extra tool call; it is supplied by doc-processing-std-tools 0.2+, which is the floor this feature is written against (exercised against 0.6.0 — see Skills). An older payload simply omits it.
Token-saving optimization
When the skills directory is empty, three "activation" tools (load_skill, load_skill_resource, execute_skill_script) are hidden from the LLM-visible tool list to save tokens per turn. Two tools intentionally stay advertised so the model can bootstrap from an empty state: list_skills (re-poll for skills added mid-session) and create_skill (create the first skill in the directory). The check is re-evaluated on every run().
Disabling auto-injection¶
agent = Agent(
model="claude-sonnet-5",
instructions="Discover skills yourself.",
auto_inject_skills=False,
tools=[
{
"type": "mcp_script",
"path": "skills_server.py",
"name": "skills-tools",
"env": {"DPTTOOLS_SKILLS_DIR": "/path/to/.agent_skills"},
}
],
)
from doc_processing_toolkit import Agent
agent = (
Agent.builder()
.model("claude-sonnet-5")
.auto_inject_skills(False)
.build()
)
model: claude-sonnet-5
auto_inject_skills: false
tools:
- type: mcp_script
path: skills_server.py
name: skills-tools
env:
DPTTOOLS_SKILLS_DIR: /path/to/.agent_skills
When disabled, the LLM must discover skills by explicitly calling list_skills.
Session usage¶
Skills metadata is fetched on every run() call, so skills added mid-session are picked up automatically:
async with agent.session() as session:
# Skills catalog injected on first run
await session.run("What skills are available?")
# If new skills are added to the skills directory between runs,
# they appear in the next run's system prompt
await session.run("Are there any new skills?")
Troubleshooting¶
Skills injection silently does nothing (no error) when any of these conditions apply:
| Condition | Reason |
|---|---|
auto_inject_skills=False |
Feature explicitly disabled |
| No skills server detected | No server exposes both list_skills and load_skill (the server's name does not matter since 0.5.3) |
The instructions already contain <available_skills> |
The app supplies its own catalog; for that agent the toolkit calls nothing, injects nothing and hides nothing, and logs one INFO line per run |
| The server's skills directory is unset, missing or empty | DPTTOOLS_SKILLS_DIR is read by the server, in its own process — for a subprocess server it must be passed in the config's env. std-tools then returns an empty catalog with a note (see its configuration page), which is the next row |
list_skills returns empty array |
No skills available — load_skill, load_skill_resource, and execute_skill_script are hidden from the LLM to save tokens; list_skills and create_skill stay advertised so the model can re-poll or bootstrap the directory |
list_skills call fails, or returns something other than the JSON the concept page shows |
Agent logs one WARNING naming the server and continues normally; the activation tools stay advertised (since 0.5.3 — a failed or malformed reply is not an empty catalog) |
list_skills returns a diagnostics array |
Each entry is logged as WARNING skills: ... — diagnostics never enter the system prompt |
Tip
Enable debug logging to see detection and fetch details when troubleshooting skills injection issues.
Related¶
- Skills Auto-Injection Concept — detection logic, prompt format, and configuration details
- Tools — supported tool formats
- Local MCP Tools — mounting MCP servers