Skip to main content

Framework-agnostic skills subsystem for Python AI agents - embed directly or deploy as a service

Project description

open-skills

A framework-agnostic Skills subsystem for Python agents. Build, version, and execute reusable agent capabilities as code bundles — embed directly in your app or deploy as a service.

Inspired by Anthropic's Skills feature for Claude.

Overview

open-skills provides a complete system for managing executable code bundles (skills) that AI agents can discover and invoke. Think of it as a plugin system for LLM applications with version control, auto-discovery, and execution tracking.

Version 0.2.0 introduces library mode — embed open-skills directly into any Python application without running a separate service.

Key Features

Framework-Agnostic — Works with OpenAI, Anthropic, LangChain, LlamaIndex, or custom agents

Two Deployment Modes — Library (embedded) or Service (microservice)

Auto-Discovery — Skills registered from folder structure at startup

Context-Aware Prompts — Automatic skill injection into system prompts

Versioned Bundles — Skills as folders with metadata, scripts, and resources

Embedding-Based Search — Automatic skill selection via vector similarity

Tool Manifest — Standard .well-known/skills.json for any LLM framework

Real-Time Streaming — SSE for execution updates

Artifact Generation — File outputs with S3-compatible storage

Multi-Skill Composition — Chain or parallelize execution

Quick Start

Library Mode (Embed in Your App)

Install:

pip install open-skills

Integrate into FastAPI:

from fastapi import FastAPI
from open_skills import mount_open_skills

app = FastAPI()

# One-line integration
await mount_open_skills(
    app,
    skills_dir="./skills",              # Auto-discover from this folder
    database_url="postgresql+asyncpg://localhost/mydb",
    openai_api_key="sk-...",
)

# Skills are now:
# - Auto-registered from ./skills folder
# - Discoverable at /.well-known/skills.json
# - Executable via /skills/api/runs

Use with any agent framework:

from open_skills import as_agent_tools, to_openai_tool
import openai

# Get available tools
tools = await as_agent_tools(published_only=True)
openai_tools = [to_openai_tool(t) for t in tools]

# Use with OpenAI
client = openai.AsyncOpenAI()
response = await client.chat.completions.create(
    model="gpt-4",
    messages=[{"role": "user", "content": "Summarize this document..."}],
    tools=openai_tools,
)

Service Mode (Microservice)

Run as standalone service:

# Using Docker Compose
docker-compose up -d

# Or directly
python -m open_skills.service.main

Access from any language:

curl http://localhost:8000/.well-known/skills.json  # Discover tools
curl -X POST http://localhost:8000/api/runs \
  -d '{"skill_version_ids": ["..."], "input": {...}}'

Two Ways to Use

Mode Best For Pros Cons
Library Monolithic apps, low latency In-process, zero network overhead Shares resources
Service Microservices, polyglot apps Process isolation, language-agnostic Network overhead

See INTEGRATION_GUIDE.md for complete integration patterns.

Skill Bundle Format

A skill is a directory containing:

my-skill/
├── SKILL.md          # Metadata (YAML frontmatter + description)
├── scripts/
│   └── main.py       # Entrypoint function
├── resources/        # Optional: templates, data files
│   └── template.txt
└── tests/            # Optional: test inputs
    └── sample.json

SKILL.md Example:

---
name: text_summarizer
version: 1.0.0
entrypoint: scripts/main.py
description: Summarizes long text into key points
inputs:
  - type: text
outputs:
  - type: text
tags: [nlp, summarization, text]
---

# Text Summarizer

This skill takes long text and produces a concise summary.

scripts/main.py Example:

async def run(input_payload: dict) -> dict:
    text = input_payload.get("text", "")
    summary = text[:200] + "..."  # Simple truncation

    return {
        "outputs": {"summary": summary},
        "artifacts": []
    }

Common Use Cases

1. Embed in Existing FastAPI App

from fastapi import FastAPI
from open_skills import mount_open_skills

app = FastAPI()

# Your existing routes
@app.get("/")
async def root():
    return {"app": "my-app"}

# Add skills
@app.on_event("startup")
async def startup():
    await mount_open_skills(
        app,
        prefix="/skills",
        skills_dir="./skills",
        auto_register=True,
    )

2. Use with OpenAI Tool Calling

from open_skills import configure, as_agent_tools, to_openai_tool
from open_skills.core.executor import SkillExecutor
from open_skills.core.manager import SkillManager
import openai

# Configure library
configure(database_url="postgresql+asyncpg://...", openai_api_key="sk-...")

# Get tools
tools = await as_agent_tools()
openai_tools = [to_openai_tool(t) for t in tools]

# Call OpenAI
client = openai.AsyncOpenAI()
response = await client.chat.completions.create(
    model="gpt-4",
    messages=[{"role": "user", "content": "Help me summarize this..."}],
    tools=openai_tools,
)

# Execute skill if tool called
if response.choices[0].message.tool_calls:
    for tool_call in response.choices[0].message.tool_calls:
        function_name = tool_call.function.name
        tool = next(t for t in tools if t["name"] == function_name)

        # Execute the skill
        # ... (see examples/openai_agents_sdk_example.py for full example)

3. Context-Aware Prompts (Skill Injection)

from open_skills import configure, inject_skills_context

configure(database_url="postgresql+asyncpg://...", openai_api_key="sk-...")

# Create a context-aware system prompt
base_prompt = "You are a helpful AI assistant."

# Inject available skills into the prompt
system_prompt = await inject_skills_context(
    base_prompt,
    format="detailed"  # or "compact", "numbered"
)

# Now the agent knows what skills are available
agent = Agent(system_prompt=system_prompt)

4. Auto-Discovery from Folder

from open_skills import configure, register_skills_from_folder

configure(database_url="postgresql+asyncpg://...", openai_api_key="sk-...")

# Auto-register all skills in ./skills folder
versions = await register_skills_from_folder(
    "./skills",
    auto_publish=True,
    visibility="org",
)

print(f"Registered {len(versions)} skills")

5. Real-Time Execution Streaming

# Backend (Python)
import httpx

async with httpx.AsyncClient() as client:
    async with client.stream("GET", f"/api/runs/{run_id}/stream") as response:
        async for line in response.aiter_lines():
            # Process Server-Sent Events
            print(line)
// Frontend (JavaScript)
const eventSource = new EventSource(`/api/runs/${runId}/stream`);

eventSource.addEventListener("status", (e) => {
  console.log("Status:", JSON.parse(e.data).status);
});

eventSource.addEventListener("complete", (e) => {
  console.log("Done:", JSON.parse(e.data));
  eventSource.close();
});

Architecture

┌─────────────────────────────────────────────────────────┐
│                    Your Application                     │
├─────────────────────────────────────────────────────────┤
│  Library Mode                 │  Service Mode           │
│  ┌─────────────────────┐      │  ┌──────────────────┐  │
│  │ mount_open_skills() │      │  │ HTTP Client      │  │
│  │  • Auto-register    │      │  │  • REST API      │  │
│  │  • Tool discovery   │      │  │  • Language-     │  │
│  │  • In-process exec  │      │  │    agnostic      │  │
│  └─────────────────────┘      │  └──────────────────┘  │
└─────────────────────────────────────────────────────────┘
                      │
                      ▼
        ┌──────────────────────────┐
        │   open-skills Core       │
        ├──────────────────────────┤
        │  • Skill Manager         │
        │  • Skill Router          │
        │  • Skill Executor        │
        │  • Auto-Discovery        │
        │  • Tool Manifest         │
        └────┬─────────────────┬───┘
             │                 │
             ▼                 ▼
        ┌─────────┐      ┌──────────┐
        │Postgres │      │    S3    │
        │+pgvector│      │Artifacts │
        └─────────┘      └──────────┘

Installation

Prerequisites

  • Python 3.11+
  • PostgreSQL 14+ with pgvector extension
  • OpenAI API key (for embeddings)

Install Package

pip install open-skills

# Or for development
git clone https://github.com/rscheiwe/open-skills.git
cd open-skills
pip install -e ".[dev]"

Database Setup

# Using Docker (recommended)
docker run -d \
  --name openskills-postgres \
  -e POSTGRES_PASSWORD=postgres \
  -e POSTGRES_DB=openskills \
  -p 5432:5432 \
  pgvector/pgvector:pg16

# Run migrations
alembic upgrade head

Configuration

Library Mode

from open_skills import configure

configure(
    database_url="postgresql+asyncpg://localhost/mydb",
    openai_api_key="sk-...",
    storage_root="./skills",
    artifacts_root="./artifacts",
    # Optional S3 configuration
    s3_endpoint="https://s3.amazonaws.com",
    s3_bucket="my-bucket",
)

Service Mode

Create .env file:

POSTGRES_URL=postgresql+asyncpg://user:password@localhost:5432/openskills
OPENAI_API_KEY=sk-...
JWT_SECRET=your-secret-key-here
STORAGE_ROOT=./storage
ARTIFACTS_ROOT=./artifacts

# Optional
S3_ENDPOINT=https://s3.amazonaws.com
S3_BUCKET=open-skills-artifacts
LANGFUSE_API_KEY=  # Telemetry

API Endpoints

When using mount_open_skills() or service mode:

Endpoint Method Description
/.well-known/skills.json GET Tool discovery manifest
/api/health GET Health check
/api/skills GET, POST List/create skills
/api/skills/{id}/versions GET, POST Manage versions
/api/skills/search POST Embedding-based search
/api/runs POST Execute skills
/api/runs/{id} GET Get run details
/api/runs/{id}/stream GET Real-time SSE stream

See INTEGRATION_GUIDE.md for complete API reference.

CLI Tools

# Create a new skill
open-skills init my-skill

# Validate skill bundle
open-skills validate ./my-skill

# Test locally
open-skills run-local ./my-skill input.json

# Publish to service
open-skills publish ./my-skill

# Start service
open-skills serve --port 8000

Examples

Documentation

Framework Compatibility

Open-skills provides tool converters for:

  • OpenAI - Function calling format
  • Anthropic - Tool use format
  • LangChain - Tool format
  • Custom - Generic tool contract
from open_skills import as_agent_tools, to_openai_tool, to_anthropic_tool, to_langchain_tool

tools = await as_agent_tools()

# Convert to framework-specific formats
openai_tools = [to_openai_tool(t) for t in tools]
anthropic_tools = [to_anthropic_tool(t) for t in tools]
langchain_tools = [to_langchain_tool(t) for t in tools]

Development

Run Tests

pytest                    # All tests
pytest -m unit            # Unit tests only
pytest -m integration     # Integration tests
pytest --cov=open_skills  # With coverage

Code Quality

black open_skills tests   # Format
ruff check open_skills    # Lint
mypy open_skills          # Type check

Database Migrations

alembic revision --autogenerate -m "description"  # Create migration
alembic upgrade head                              # Apply
alembic downgrade -1                              # Rollback

Deployment

Docker (Service Mode)

docker build -t open-skills:latest .
docker run -p 8000:8000 --env-file .env open-skills:latest

Kubernetes

kubectl apply -f k8s/

Library Mode (Embedded)

Deploy as part of your application — no separate deployment needed!

See docs/deployment.md for production setup.

Troubleshooting

Skills not appearing in manifest

from open_skills.core.manager import SkillManager

async with db_session() as db:
    manager = SkillManager(db)
    skills = await manager.list_skills()
    print(f"Found {len(skills)} skills")

Database connection issues

# Verify pgvector extension
psql -d openskills -c "\dx"

# Test connection
psql postgresql://postgres:postgres@localhost:5432/openskills

See INTEGRATION_GUIDE.md for more.

Contributing

Contributions welcome! Please read CONTRIBUTING.md for guidelines.

License

MIT License - see LICENSE file for details.

Acknowledgments

Inspired by Anthropic's Skills feature for Claude, designed to work with any LLM framework.


Current Version: 0.2.0 (Framework-Agnostic Release) Status: Production-ready for library mode, service mode, and hybrid deployments

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

open_skills-0.2.0.tar.gz (91.1 kB view details)

Uploaded Source

Built Distribution

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

open_skills-0.2.0-py3-none-any.whl (75.0 kB view details)

Uploaded Python 3

File details

Details for the file open_skills-0.2.0.tar.gz.

File metadata

  • Download URL: open_skills-0.2.0.tar.gz
  • Upload date:
  • Size: 91.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.7

File hashes

Hashes for open_skills-0.2.0.tar.gz
Algorithm Hash digest
SHA256 c0c7432af2ff912ad26caa8a092f2e0ea6c20c038559436d8b38c9aff10b289e
MD5 c954731e556503fd49791f0d20a7fd76
BLAKE2b-256 960a150bfe0a4c2aaf61c9fa8c93f07250dd342ddb0a629fe6dd4c8e1e7819d6

See more details on using hashes here.

File details

Details for the file open_skills-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: open_skills-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 75.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.7

File hashes

Hashes for open_skills-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d13fc9ff0d2eeb8dece2be092f513289bf564e717e387b6463306af47c58fe50
MD5 354f76d78403787cef2bfc6969dc6853
BLAKE2b-256 74023169c06265519743b77e2500a38d32372c320de91974827ff32c2d175d1e

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