Skip to main content

LLM-framework-agnostic skill search library with fast full-text search

Project description

skill-search

LLM-framework-agnostic skill search library.

Parses SKILL.md files in a skills directory, builds a fast full-text search index using tantivy (Rust-based), and provides tool definitions + execution handlers that work with any LLM library (OpenAI SDK, Anthropic SDK, LangChain, LiteLLM, etc.).

日本語 README

Installation

pip install skill-search

Usage

Basic

from skill_search import SkillSearch

# Initialize with skill directories
ss = SkillSearch(skills_dirs=["./skills"])

# Get tool definitions (OpenAI function calling format)
tools = ss.get_tool_definitions()

# Get system prompt with skill listing
system_prompt = ss.get_system_prompt()

# Execute tool calls from LLM
result = ss.call_tool("search_skills", {"query": "API reference", "top_k": 3})

OpenAI SDK

import json
from openai import OpenAI
from skill_search import SkillSearch

client = OpenAI()
ss = SkillSearch(skills_dirs=["./skills"])

messages = [
    {"role": "system", "content": ss.get_system_prompt()},
    {"role": "user", "content": "How do I use the Figma API?"},
]

response = client.chat.completions.create(
    model="gpt-4o",
    messages=messages,
    tools=ss.get_tool_definitions(),
)

# Handle tool calls
for choice in response.choices:
    if choice.message.tool_calls:
        for tc in choice.message.tool_calls:
            result = ss.call_tool(
                tc.function.name,
                json.loads(tc.function.arguments),
            )
            messages.append({"role": "tool", "content": result, "tool_call_id": tc.id})

Anthropic SDK

from anthropic import Anthropic
from skill_search import SkillSearch

client = Anthropic()
ss = SkillSearch(skills_dirs=["./skills"])

# Convert to Anthropic format
tools = [
    {
        "name": t["function"]["name"],
        "description": t["function"]["description"],
        "input_schema": t["function"]["parameters"],
    }
    for t in ss.get_tool_definitions()
]

response = client.messages.create(
    model="claude-sonnet-4-20250514",
    system=ss.get_system_prompt(),
    messages=[{"role": "user", "content": "How do I search in Jira?"}],
    tools=tools,
)

# Handle tool use
for block in response.content:
    if block.type == "tool_use":
        result = ss.call_tool(block.name, block.input)

Available Tools

Tool Description
list_skills List all available skills
read_skill Read full SKILL.md content
search_skills Full-text search (BM25 via tantivy)
read_resource Read supplementary resource files

SKILL.md Format

---
name: my-skill
description: Brief description of the skill
---

# My Skill

## Usage

1. Step 1
2. Step 2

How It Works

  1. Discovery — Recursively scans for SKILL.md files and parses YAML frontmatter
  2. Indexing — Splits documents into heading-level chunks and indexes with tantivy
  3. Search — BM25 scoring returns results ranked by relevance
  4. Tool Executioncall_tool() executes LLM tool calls and returns results as strings

Security

LLM tool calls are treated as untrusted input and protected with defense-in-depth.

Path Traversal Prevention

Layer Location Protection
Discovery discover_resources() Symlinks resolved; paths outside skill directory excluded
Input validation read_resource handler Resource names containing .. are rejected
Path resolution read_resource handler Resolved paths verified to be within skill directory
Whitelist read_resource handler Only pre-discovered resources are accessible

Extension Filter

Only these file extensions are indexed as resources:

.md, .json, .yaml, .yml, .csv, .xml, .txt

Executable files (.py, .sh, .exe, etc.) and binaries are excluded.

Design Principles

  • Read-only — No write or execute capabilities
  • Whitelist-based — Only pre-validated resources are accessible
  • Defense-in-depth — Input validation → path resolution → directory boundary check

Development

uv run pytest tests/ -v

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

skill_search-0.1.0.tar.gz (28.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

skill_search-0.1.0-py3-none-any.whl (12.9 kB view details)

Uploaded Python 3

File details

Details for the file skill_search-0.1.0.tar.gz.

File metadata

  • Download URL: skill_search-0.1.0.tar.gz
  • Upload date:
  • Size: 28.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for skill_search-0.1.0.tar.gz
Algorithm Hash digest
SHA256 6b0c3113a33731cf0ba6cffc49898f169b84959073fb47eb8589a70eb256276d
MD5 f47495ba368a0313f4ae0b0346b38316
BLAKE2b-256 273960782fc9620e7eef3804a791c92ca714909bcfa659b6187fba6a29afd2d2

See more details on using hashes here.

File details

Details for the file skill_search-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: skill_search-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 12.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for skill_search-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 422bd992bae4260ce5d972a0d99bce6753818f757a59d63d1f0cd6dd2f3b7058
MD5 897721f627c7d5cda8747c0a76f9b4a9
BLAKE2b-256 bb1a5c834832ab0ce3f954aa36cd9ded9bbb0296c335af3263ad79b50df14207

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page