Skills
Planning & CoordinationLoad on Demand
Inject knowledge via tool_result when needed, not upfront in the system prompt
s01 > s02 > s03 > s04 > [ s05 ] s06 > s07 > s08 > s09 > s10 > s11 > s12
"Don't show the model 100 tools, load 10 on demand" -- dynamic skill discovery, loading by scenario.
Harness layer: Tools & Execution -- tool count management, preventing tool definitions from flooding context.
Problem
s02 added 4 tools, s03 added 1, s04 added 1. As the system evolves, tool count can reach 30-50. Problems: token waste (~150-300 tokens per tool × 50 = 15K tokens for definitions alone), increased wrong-tool selection probability, irrelevant tool noise.
Solution
skills/
├── coding/ # manifest.yaml + handler.py
├── testing/
└── deploy/
Loader matches skills to query keywords, loads tools dynamically.
Core Concepts
Skill Structure
skills/skill_name/
├── manifest.yaml # name, description, triggers
└── handler.py # register_tools() -> list[dict]
Dynamic Loading
class SkillLoader:
def match(self, query: str) -> list[dict]:
"""Return tools from skills matching the query."""
matched_tools = []
for name, skill in self.skills.items():
if any(t in query.lower() for t in skill["triggers"]):
tools = self._load_tools(skill["handler"])
matched_tools.extend(tools)
return matched_tools
Key Code
loader = SkillLoader("./skills")
dynamic_tools = loader.match(query)
all_tools = BASE_TOOLS + dynamic_tools
# Use dynamic tool set in the loop
response = client.messages.create(model=MODEL, system=SYSTEM, messages=messages, tools=all_tools)
What's New (s04 → s05)
| Component | s04 | s05 |
|---|---|---|
| Tool loading | Compile-time fixed | Runtime dynamic |
| Tool count | All loaded | On-demand matching |
| Extensibility | Change code to add tools | Add directory to add tools |
| Token efficiency | Fixed overhead | On-demand overhead |
Deep Dive: Design Decisions
Q1: Keyword matching too simple — why not semantic search?
Trade-off: keywords (70-80% accuracy, <1ms, no deps) vs embedding search (90-95%, 50-200ms, needs embedding model) vs LLM selection (95%+, 500ms+, extra API call). s05 is a teaching simplification. Claude Code uses layered strategy: rule-based filtering then model-based selection.
Q2: What if too many skills match?
Priority + cap: sort by priority, limit to MAX_DYNAMIC_TOOLS = 10. Directly relates to s15's context budget — tools get 10% allocation.
Q3: How do Skills relate to MCP Servers?
Skills are local, in-process tool extensions. MCP Servers are remote, inter-process via JSON-RPC. MCP is the "standardized remote version" of Skills.
Q4: Tool definitions: system prompt or tools parameter?
Must use tools parameter. Claude API gives special treatment: schema validation, KV-cache friendly placement, structured stop_reason = "tool_use" with ToolUseBlock.
Q5: How to safely execute loaded handler.py?
Teaching version uses importlib.import_module(). Production needs: signature verification, sandboxed execution, timeout controls.
Try It
cd learn-claude-code
python agents/s05_skill_loading.py
Recommended prompts:
"Write a Python test for the calculator module"— triggers testing skill"Deploy the app to production"— triggers deploy skill"Refactor utils.py"— uses base tools only
References
- Claude Code: Skill System — Anthropic Docs. Claude Code's skill/command loading system, s05 is its simplified teaching version.
- MCP: Tool Discovery — MCP Spec. Dynamic tool discovery protocol, s05 is MCP's local predecessor.
- Building Effective Agents — Anthropic, Dec 2025. Tool selection challenges: more tools = harder selection. s05's on-demand loading is the countermeasure.
- Agentic Coding Trends 2026 — Anthropic, Mar 2026. "Tool ecosystem explosion" — MCP-driven exponential tool growth makes dynamic loading essential.