Skip to main content

Skills Discovery

Agent Skills provides comprehensive discovery mechanisms for AI agents to find and use relevant skills.

The Discovery Challenge

When you have many skills available, agents need efficient ways to:

  • Find relevant skills - Without loading all skill content upfront
  • Understand capabilities - Know what each skill can do
  • Choose the right skill - Select the best skill for the task

Discovery Methods

Directory-Based Discovery

The SkillsManager discovers skills from directories:

from agent_skills import SkillsManager

manager = SkillsManager("./skills")

# Discover all skills in the directory
skills = manager.discover()

for skill in skills:
print(f"{skill.name}: {skill.description}")
print(f" Tags: {skill.metadata.tags}")
print(f" Status: {skill.status}")

Supported Formats

The manager discovers skills in multiple formats:

FormatExtensionDescription
Python*.pyPython files with async functions
SKILL.md*.skill.mdMarkdown with YAML frontmatter

Directory Structure

skills/
├── data/
│ ├── csv_processor.py
│ ├── json_processor.py
│ └── transform.py
├── files/
│ ├── backup.py
│ └── search.py
└── utilities/
├── validation.skill.md
└── logging.skill.md

All nested directories are scanned recursively.

Search skills by natural language query:

matches = manager.search("data processing")

for match in matches:
print(f"{match.skill.name} (score: {match.score:.2f})")
print(f" {match.skill.description}")

Search Parameters

matches = manager.search(
query="file operations", # Natural language query
tags=["files"], # Filter by tags
limit=10, # Maximum results
)

Search Results

class SkillSearchResult:
skill: Skill # The matched skill
score: float # Relevance score (0-1)
matched_on: list[str] # Fields that matched (name, description, tags, content)

What Gets Searched

The search looks at:

  • Skill name - Exact and partial matches
  • Description - Semantic matching
  • Tags - Category filtering
  • Content - Full-text search in skill body

Agent Discovery via Toolset

When using AgentSkillsToolset, agents have discovery tools:

list_skills

Lists all available skills with summaries:

# Agent calls: list_skills()
# Returns:
[
{
"name": "data-analyzer",
"description": "Analyzes datasets and provides insights",
"tags": ["data", "analysis"],
"scripts": ["analyze", "summarize"],
"resources": ["reference"]
},
{
"name": "file-processor",
"description": "Process files in batches",
"tags": ["files", "batch"],
"scripts": ["process", "validate"],
"resources": []
}
]

load_skill

Get full details for a specific skill:

# Agent calls: load_skill(skill_name="data-analyzer")
# Returns:
{
"name": "data-analyzer",
"description": "Analyzes datasets and provides insights",
"content": "# Data Analyzer\n\nUse this skill to analyze...",
"scripts": [
{"name": "analyze", "description": "Analyze a data file"},
{"name": "summarize", "description": "Summarize analysis results"}
],
"resources": [
{"name": "reference", "description": "Reference documentation"}
],
"tags": ["data", "analysis"],
"allowed_tools": ["filesystem__read_file"],
"version": "1.0.0"
}

Filtering and Sorting

Filter by Tags

# Get skills with specific tags
data_skills = manager.list(tags=["data"])
file_skills = manager.list(tags=["files", "processing"])

Filter by Status

from agent_skills import SkillStatus

# Only active skills
active = manager.list(status=SkillStatus.ACTIVE)

# Only draft skills
drafts = manager.list(status=SkillStatus.DRAFT)

Filter by Tools

Find skills that use specific MCP tools:

# Skills that use filesystem tools
fs_skills = [
s for s in manager.list()
if any("filesystem" in t for t in s.metadata.allowed_tools)
]

Skill Metadata

SKILL.md Metadata

Skills in SKILL.md format include rich metadata:

---
name: data-analyzer
description: Analyzes datasets and provides insights
version: 1.2.0
author: Team Data
tags:
- data
- analysis
- csv
allowed-tools:
- filesystem__read_file
- filesystem__write_file
context: sandbox
user-invocable: true
hooks:
before-invoke: "echo 'Starting analysis...'"
after-invoke: "echo 'Analysis complete!'"
---

# Data Analyzer

Instructions for using this skill...

Python File Metadata

Python skills use docstrings and type hints:

# skills/data_analyzer.py
"""Data Analyzer - Analyzes datasets and provides insights.

Tags: data, analysis, csv
Tools: filesystem__read_file, filesystem__write_file
Version: 1.2.0
Author: Team Data
"""

async def analyze(path: str, format: str = "csv") -> dict:
"""Analyze a data file.

Args:
path: Path to the file to analyze.
format: File format (csv, json, tsv).

Returns:
Analysis results with row count, column info, etc.
"""
...

Discovery Best Practices

1. Use Descriptive Names

# Good: Clear, searchable names
"csv-data-analyzer"
"file-backup-manager"
"json-schema-validator"

# Avoid: Vague names
"processor"
"helper"
"utils"

2. Write Good Descriptions

# Good: Explains what, when, and how
description="Analyzes CSV files to extract statistics, find patterns, and identify data quality issues. Use for data exploration before processing."

# Avoid: Too brief
description="Analyzes files"

3. Use Tags Consistently

Establish a tagging convention:

# Category tags
tags=["data", "files", "web", "database"]

# Action tags
tags=["analysis", "processing", "validation", "transformation"]

# Format tags
tags=["csv", "json", "xml", "yaml"]

4. Document Tool Dependencies

# List the tools your skill needs
allowed_tools=[
"filesystem__read_file",
"filesystem__write_file",
"filesystem__list_directory",
]

5. Version Your Skills

version="1.2.0"  # Major.Minor.Patch

Programmatic Discovery

Custom Discovery Logic

from pathlib import Path
from agent_skills import Skill

def discover_custom(directory: str) -> list[Skill]:
"""Custom skill discovery logic."""
skills = []

for path in Path(directory).rglob("*.skill.md"):
content = path.read_text()
skill = Skill.from_skill_md(content)

# Custom filtering
if skill.status == SkillStatus.ACTIVE:
skills.append(skill)

return skills

Registry Pattern

For large skill collections, use a registry:

from agent_skills import SkillsManager

class SkillRegistry:
"""Central registry for skill discovery."""

def __init__(self):
self.managers: dict[str, SkillsManager] = {}

def register(self, namespace: str, path: str):
"""Register a skill namespace."""
self.managers[namespace] = SkillsManager(path)

def discover_all(self) -> dict[str, list[Skill]]:
"""Discover skills from all namespaces."""
return {
ns: mgr.discover()
for ns, mgr in self.managers.items()
}

def search(self, query: str) -> list[SkillSearchResult]:
"""Search across all namespaces."""
results = []
for mgr in self.managers.values():
results.extend(mgr.search(query))
return sorted(results, key=lambda r: r.score, reverse=True)

# Usage
registry = SkillRegistry()
registry.register("core", "./skills/core")
registry.register("data", "./skills/data")
registry.register("shared", "/shared/skills")

all_skills = registry.discover_all()
matches = registry.search("file processing")