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

Approach Tools Visible Token Cost Decision Quality
Flat list (60 tools) 60 High Poor (overwhelmed)
Skills (3 active) 15 Low Good (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. :::

Quiz

Module 3: MCP & Agent Skills

Take Quiz