Learn Claude Code
s05

Skills

Planning & Coordination

Load on Demand

234 LOC5 toolsSkillLoader + two-layer injection
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)

Components04s05
Tool loadingCompile-time fixedRuntime dynamic
Tool countAll loadedOn-demand matching
ExtensibilityChange code to add toolsAdd directory to add tools
Token efficiencyFixed overheadOn-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.