Lesson 11 of 20

MCP & Agent Skills

Agent Skills Framework

4 min read

As agents gain more capabilities, managing them becomes challenging. A skills framework organizes capabilities into discoverable, self-documenting modules.

The Problem with Flat Tool Lists

# This becomes unmanageable at scale
tools = [
    "search_web", "search_files", "search_database",
    "read_file", "write_file", "delete_file",
    "run_python", "run_bash", "run_javascript",
    "send_email", "send_slack", "send_sms",
    "create_pr", "merge_pr", "review_pr",
    # ... 50 more tools
]

The model sees 60+ tools and wastes tokens deciding which to use.

Skills: Grouped Capabilities

Organize tools into logical skill groups:

skills/
├── web/
│   ├── SKILL.md
│   └── tools: [search, fetch, scrape]
├── filesystem/
│   ├── SKILL.md
│   └── tools: [read, write, list, delete]
├── coding/
│   ├── SKILL.md
│   └── tools: [run_python, run_bash, lint]
└── communication/
    ├── SKILL.md
    └── tools: [email, slack, sms]

The SKILL.md Pattern

Each skill has a manifest describing what it does:

# Filesystem Skill

## Purpose
Read, write, and manage files in the workspace.

## When to Use
- User asks to read or edit files
- Need to save output to disk
- Managing project structure

## When NOT to Use
- Reading from URLs (use web skill)
- Database operations (use database skill)

## Tools
- `read_file`: Read file contents
- `write_file`: Create or overwrite files
- `list_directory`: List files in a directory
- `delete_file`: Remove a file

## Examples
"Read the config file" → read_file("config.json")
"Save this to output.txt" → write_file("output.txt", content)

Progressive Disclosure

Don't load all skills at once. Load based on context:

class SkillManager:
    def __init__(self):
        self.available_skills = self.discover_skills()
        self.active_skills = set()

    def discover_skills(self) -> dict:
        """Find all SKILL.md files."""
        skills = {}
        for path in Path("skills").glob("*/SKILL.md"):
            skill_name = path.parent.name
            skills[skill_name] = self.parse_skill(path)
        return skills

    def get_relevant_skills(self, user_message: str) -> list[str]:
        """Determine which skills might be needed."""
        relevant = []

        # Simple keyword matching (use embeddings for production)
        keywords = {
            "filesystem": ["file", "read", "write", "save", "directory"],
            "web": ["search", "url", "website", "fetch", "http"],
            "coding": ["run", "execute", "python", "script", "code"],
            "communication": ["email", "slack", "send", "message", "notify"]
        }

        message_lower = user_message.lower()
        for skill, words in keywords.items():
            if any(word in message_lower for word in words):
                relevant.append(skill)

        return relevant or ["filesystem"]  # Default skill

    def activate_skills(self, skill_names: list[str]):
        """Load only the needed skills."""
        self.active_skills = set(skill_names)
        return self.get_active_tools()

    def get_active_tools(self) -> list[dict]:
        """Get tool definitions for active skills only."""
        tools = []
        for skill_name in self.active_skills:
            skill = self.available_skills[skill_name]
            tools.extend(skill["tools"])
        return tools

Context-Aware Skill Loading

async def process_message(user_message: str):
    # Step 1: Determine relevant skills
    relevant = skill_manager.get_relevant_skills(user_message)

    # Step 2: Activate only those skills
    tools = skill_manager.activate_skills(relevant)

    # Step 3: Call LLM with focused tool set
    response = await llm.chat(
        messages=[{"role": "user", "content": user_message}],
        tools=tools  # Only 5-10 tools instead of 60
    )

    return response

Benefits

ApproachTools VisibleToken CostDecision Quality
Flat list (60 tools)60HighPoor (overwhelmed)
Skills (3 active)15LowGood (focused)

Skill Composition

Skills can depend on other skills:

# skills/research/SKILL.md
name: research
description: Deep research on topics
depends_on:
  - web        # For searching
  - filesystem # For saving notes
tools:
  - research_topic
  - summarize_sources

Nerd Note: Think of skills like VS Code extensions. Users don't install all 30,000. They pick what they need.

Next: Loading skills dynamically at runtime. :::

Quick check: how does this lesson land for you?

Quiz

Module 3: MCP & Agent Skills

Take Quiz
FREE WEEKLY NEWSLETTER

Stay on the Nerd Track

One email per week — courses, deep dives, tools, and AI experiments.

No spam. Unsubscribe anytime.