Skillet is an HTTP-native, OpenAPI-first framework for packaging and running reusable skills (micro-functions) that Large-Language-Model agents can call over the network.
"Cook up a skill in minutes, serve it over HTTPS, remix it in a workflow."
Current community standard MCP servers are great for quick sandbox demos inside an LLM playground, but painful when you try to ship real-world agent workflows:
| MCP Pain Point | Skillet Solution |
|---|---|
| Default stdio transport; requires local pipes and custom RPC | Pure HTTP + JSON with an auto-generated OpenAPI contract |
| One bespoke server per repo; Docker mandatory | Single-file Skillfile.yaml β deploy to Cloudflare Workers, AWS Lambda or raw FastAPI |
| No discovery or function manifest | Registry + /openapi.json enable automatic client stubs & OpenAI function-calling |
| Heavy cold-start if each agent needs its own container | Skills are tiny (β€ 5 MB) Workers; scale-to-zero is instant |
| Secrets baked into code | Standard .skillet.env + runtime injection |
| Steep learning curve for non-infra devs | pip install fliiq-skillet β skillet new hello_world β done |
- Skilletfile.yaml β€50 lines β declarative inputs/outputs, runtime & entry-point
skillet devβ hot-reload FastAPI stub for local testingskillet deployβ one-command deploy to Workers/Lambda (more targets soon)- Registry β browse, star and import skills; share community "recipes" in the Cookbook
- Cookbook β visual builder that chains skills into agent workflows
pip install fliiq-skillet
skillet new fetch_html --runtime python
cd fetch_html
skillet dev # Swagger UI on http://127.0.0.1:8000The examples/ directory contains reference implementations of Skillet skills:
- anthropic_fetch - Fetches HTML content from URLs. A Skillet-compatible implementation of the Anthropic
fetchMCP. - anthropic_time - Returns the current time in any timezone. A Skillet-compatible implementation of the Anthropic
timeMCP. - anthropic_memory - A stateful skill that provides a simple in-memory key-value store. A Skillet-compatible implementation of the Anthropic
memoryMCP.
Each example includes:
- A complete
Skilletfile.yamlconfiguration - API documentation and usage examples
- An automated
test.shscript to verify functionality
To test any example, you'll need two terminal windows:
- First terminal - Start the server:
cd examples/[example_name] # e.g., anthropic_fetch, anthropic_time, anthropic_memory
pip install -r requirements.txt
uvicorn skillet_runtime:app --reload- Second terminal - Run the tests:
cd examples/[example_name] # same directory as above
./test.shA successful test run will show:
- All test cases executing without errors
- Expected JSON responses for successful operations
- Proper error handling for edge cases
- Server logs in the first terminal showing request handling
For example, a successful time skill test should show:
--- Testing Time Skillet ---
1. Getting current time in UTC (default)...
{"iso_8601":"2025-06-12T04:46:33+00:00", ...}
2. Getting current time in America/New_York...
{"iso_8601":"2025-06-12T00:46:33-04:00", ...}
3. Testing with an invalid timezone...
{"detail":"400: Invalid timezone: 'Mars/Olympus_Mons'..."}
See each example's specific README for detailed API usage instructions and expected responses.
Skillet skills support runtime credential injection for production deployments, enabling frontend applications to securely provide API keys without storing them server-side.
Development: Use .env files
Production: Inject credentials per request
// Frontend app (e.g., Fliiq) injects user's API keys
const response = await fetch('/api/zen_chat/run', {
method: 'POST',
body: JSON.stringify({
skill_input: { prompt: "Hello world" },
credentials: { OPENAI_API_KEY: userApiKey }
})
});Skills provide clear guidance when credentials are missing:
{
"error": "Missing required credential: OPENAI_API_KEY",
"how_to_get": "Get your API key from: https://platform.openai.com/api-keys",
"steps": ["1. Go to platform.openai.com", "2. Create API key", "..."]
}See examples/README.md for detailed credential requirements per skill.
All Skillet skills provide standardized discovery endpoints that enable LLMs and applications to intelligently understand when, how, and why to use each skill. This creates truly adaptive systems that can make smart decisions about skill usage without hardcoded logic.
The inventory endpoint provides rich metadata designed for LLM consumption, helping AI agents understand:
- When to use this skill (use cases, example queries)
- How it fits into workflows (complexity, performance characteristics)
- What it works well with (related skills, typical workflow positions)
# Get skill metadata for LLM decision-making
curl http://localhost:8000/inventoryExample Response:
{
"skill": {
"name": "Zen Chat",
"description": "Simple chat interface with automatic model selection",
"category": "ai_services",
"complexity": "simple",
"use_cases": [
"When user needs conversational AI responses",
"For chat applications and interactive dialogues",
"When you need automatic model selection (OpenAI/Gemini)"
],
"example_queries": [
"Can you help me write an email?",
"What's the weather like?",
"Explain quantum computing simply"
],
"works_well_with": ["content_creation", "customer_support", "education"],
"typical_workflow_position": "conversation",
"tags": ["ai", "chat", "conversation", "llm"],
"supports_credential_injection": true
}
}The schema endpoint provides precise technical details for developers and systems that need to call the skill:
- Exact parameters with types and validation rules
- Response format specification
- Required vs optional fields
- API contract information
# Get technical schema for integration
curl http://localhost:8000/schemaExample Response:
{
"name": "Zen Chat",
"description": "Simple chat interface with automatic model selection",
"version": "1.0.0",
"parameters": {
"type": "object",
"properties": {
"prompt": {
"type": "string",
"description": "User's message or question"
},
"model": {
"type": "string",
"description": "AI model: 'openai', 'gemini', or 'auto'"
}
},
"required": ["prompt"]
},
"output_schema": {
"type": "object",
"properties": {
"response": {"type": "string"},
"model_used": {"type": "string"},
"token_count": {"type": "integer"}
}
},
"endpoint": "/run",
"method": "POST",
"supports_credential_injection": true
}For LLM Applications:
- Smart Skill Selection: LLMs can read inventory to choose the right skill
- Context-Aware Usage: Rich metadata helps LLMs understand when NOT to use a skill
- Dynamic Function Calling: Build OpenAI function definitions from schemas at runtime
- Better User Experience: More intelligent skill routing leads to better results
For Developers:
- Runtime Discovery: No need to hardcode skill APIs or parameters
- Auto-generated Clients: Schema enables automatic client generation
- Version Compatibility: Check schema changes before deploying
- Integration Testing: Validate parameters against schema before calls
LLM Agent Decision Making:
# LLM agent intelligently selects skills based on inventory
def select_skill_for_query(user_query: str, available_skills: list):
for skill in available_skills:
inventory = requests.get(f"{skill['url']}/inventory").json()
# LLM evaluates if skill matches user intent
if matches_user_intent(user_query, inventory['skill']['use_cases']):
return skill
return NoneDynamic OpenAI Function Calling:
# Build function definitions dynamically from schemas
functions = []
for skill_url in discovered_skills:
schema = requests.get(f"{skill_url}/schema").json()
functions.append({
"name": schema["name"].replace(" ", "_").lower(),
"description": schema["description"],
"parameters": schema["parameters"]
})
# Use with OpenAI - no hardcoding required!
response = openai.ChatCompletion.create(
model="gpt-4",
messages=[{"role": "user", "content": user_query}],
functions=functions,
function_call="auto"
)Application Integration:
// Frontend app discovers skills and builds UI dynamically
const skills = await Promise.all(
discoveredSkills.map(async (skillUrl) => {
const [inventory, schema] = await Promise.all([
fetch(`${skillUrl}/inventory`).then(r => r.json()),
fetch(`${skillUrl}/schema`).then(r => r.json())
]);
return {
metadata: inventory.skill,
apiSpec: schema,
url: skillUrl
};
})
);
// Build dynamic UI based on discovered capabilities
skills.forEach(skill => {
if (skill.metadata.category === 'ai_services') {
renderAISkillCard(skill);
}
});All 8 example skills now provide complete discovery endpoints:
β
anthropic_time - /run, /inventory, /schema, /health
β
anthropic_fetch - /run, /inventory, /schema, /health
β
anthropic_memory - /run, /inventory, /schema, /health
β
zen_chat - /run, /chat, /inventory, /schema, /health
β
context7_docs - /run, /docs, /inventory, /schema, /health
β
playwright_navigate - /run, /navigate, /inventory, /schema, /health
β
supabase_execute_sql - /run, /execute_sql, /inventory, /schema, /health
β
minimax_text_to_audio - /run, /text_to_audio, /inventory, /schema, /health
This standardized discovery pattern makes every Skillet skill self-documenting and enables truly intelligent runtime integration. LLMs can discover, understand, and use skills without any hardcoded knowledge - creating adaptive systems that evolve as new skills become available.
The tutorials/ directory contains example applications that demonstrate how to integrate Skillet skills into your own applications. These tutorials show real-world usage patterns and best practices for developers who want to use Skillet skills in their projects.
-
openai_time_demo - Shows how to use OpenAI's GPT models with the Skillet time skill. This tutorial demonstrates:
- Setting up OpenAI function calling with Skillet endpoints
- Making HTTP requests to Skillet services
- Handling responses and errors
- Building an interactive CLI application
-
openai_discovery_demo - Advanced tutorial showing how to build an intelligent LLM agent that dynamically discovers and uses Skillet skills. Features:
- Dynamic skill discovery through the Discovery Service
- Intelligent skill selection based on user queries
- Automatic function definition generation from skill schemas
- Real-time skill catalog updates
-
multi_skill_runtime_demo - Demonstrates the Multi-Skill Runtime Host that consolidates multiple skills into a single service. Features:
- Single service hosting multiple skills (solves the "10+ microservices" problem)
- Preserved individual skill APIs and functionality
- Simplified deployment and management
- Better performance with no network overhead between skills
Each tutorial includes:
- Complete working code with comments
- Clear setup instructions
- Dependencies and environment configuration
- Best practices for production use
- Choose a tutorial that matches your use case
- Follow the README instructions in the tutorial directory
- Use the code as a template for your own application
The tutorials are designed to be minimal yet production-ready examples that you can build upon. They demonstrate how to:
- Make API calls to Skillet skills
- Handle authentication and environment variables
- Process responses and handle errors
- Structure your application code
For example, to try the OpenAI + Skillet time demo:
# First, start the Skillet time service
cd examples/anthropic_time
pip install -r requirements.txt
uvicorn skillet_runtime:app --reload
# In a new terminal, run the OpenAI demo
cd tutorials/openai_time_demo
pip install -r requirements.txt
python main.pyThe Skillet Discovery Service is a lightweight aggregation service that enables LLM applications to dynamically discover and use available skills, rather than hardcoding skill endpoints. This creates truly adaptive AI systems that can grow and evolve as new skills become available.
- π Dynamic Discovery: Automatically finds and catalogs available Skillet skills
- π Intelligent Search: Semantic search across skill names, descriptions, use cases, and tags
- π Rich Metadata: Detailed skill information including categories, complexity levels, and example queries
- β‘ Real-time Updates: Skill catalog updates as services come online or go offline
- π HTTP-First: Simple REST API that any application can use
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
β LLM Agent ββββββ Discovery Service ββββββ Skillet Skills β
β β β β β β
β "What skills β β Polls /inventory β β β’ Time Skill β
β are available?"ββββββ Aggregates data ββββββ β’ Fetch Skill β
β β β Serves catalog β β β’ Memory Skill β
βββββββββββββββββββ ββββββββββββββββββββ β β’ Custom Skills β
βββββββββββββββββββ
- Start your Skillet skills on different ports:
# Terminal 1: Time skill
cd examples/anthropic_time && uvicorn skillet_runtime:app --port 8001
# Terminal 2: Fetch skill
cd examples/anthropic_fetch && uvicorn skillet_runtime:app --port 8002
# Terminal 3: Memory skill
cd examples/anthropic_memory && uvicorn skillet_runtime:app --port 8003- Start the Discovery Service:
# Terminal 4: Discovery service
cd services/discovery
pip install -r requirements.txt
uvicorn main:app --reload --port 8000- Query available skills:
# Get all skills
curl -s http://localhost:8000/skills | jq '.'
# Search for time-related skills
curl -s "http://localhost:8000/search?query=time" | jq '.skills[].skill.name'
# Filter by category
curl -s "http://localhost:8000/search?category=utility" | jq '.'GET /catalog- Complete catalog of all skills (available and unavailable)GET /skills- Only available skills (filtered)GET /search- Search and filter skills by query, category, complexity, tagsPOST /refresh- Manually refresh the skill catalogGET /health- Service health check
Python Integration:
import httpx
async def discover_and_use_skills(user_query: str):
async with httpx.AsyncClient() as client:
# 1. Search for relevant skills
response = await client.get(
"http://localhost:8000/search",
params={"query": user_query}
)
skills = response.json()["skills"]
# 2. Use the most appropriate skill
if skills:
skill = skills[0]
result = await client.post(
skill["skill"]["endpoints"]["run"],
json={"your": "parameters"}
)
return result.json()OpenAI Function Calling:
# Get skills and build function definitions
skills_response = requests.get("http://localhost:8000/skills")
functions = []
for skill in skills_response.json()["skills"]:
schema = requests.get(skill["skill"]["endpoints"]["schema"]).json()
functions.append({
"name": schema["name"],
"description": schema["description"],
"parameters": schema["parameters"]
})
# Use with OpenAI
response = openai.ChatCompletion.create(
model="gpt-4",
messages=[{"role": "user", "content": "What time is it?"}],
functions=functions,
function_call="auto"
)For complete examples, see the Discovery Service documentation and the OpenAI Discovery Demo.
The Skillet Multi-Skill Runtime Host solves the "10+ microservices" problem by consolidating multiple Skillet skills into a single FastAPI service, while preserving all individual skill functionality and APIs.
Before: Microservice Management Complexity
# Managing multiple individual services becomes impractical
Terminal 1: cd examples/anthropic_time && uvicorn skillet_runtime:app --port 8001
Terminal 2: cd examples/anthropic_fetch && uvicorn skillet_runtime:app --port 8002
Terminal 3: cd examples/anthropic_memory && uvicorn skillet_runtime:app --port 8003
# ... repeat for 10+ skillsAfter: Single Consolidated Service
# Single service hosts all skills
Terminal 1: cd services/runtime && python multi_skill_host.py
# All skills available at: http://localhost:8000/skills/{skill_name}/*- π Single Service: Host unlimited skills in one FastAPI application
- π API Preservation: All existing skill endpoints work unchanged
- π¦ Simplified Deployment: One service to deploy, monitor, and scale
- β‘ Better Performance: No network overhead between skills (~10x faster)
- π οΈ Easy Management: Hot-reload skills, unified health checks
- π° Cost Reduction: ~60% reduction in resource usage
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Multi-Skill Runtime Host :8000 β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ β
β β Time Skill β β Fetch Skill β β Memory Skill β β
β β /skills/time/* β β /skills/fetch/* β β/skills/memory/* β β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ β
β β
β Unified: /health, /catalog, /skills, /reload β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- Configure skills in
runtime-config.yaml:
skills:
- name: time_skill
path: ./examples/anthropic_time
mount: time
enabled: true
- name: fetch_skill
path: ./examples/anthropic_fetch
mount: fetch
enabled: true- Start the runtime host:
cd services/runtime
python multi_skill_host.py --config runtime-config.yaml- Use skills exactly as before:
# Individual skill APIs preserved
time_result = requests.post("http://localhost:8000/skills/time/run", json={"timezone": "UTC"})
fetch_result = requests.post("http://localhost:8000/skills/fetch/run", json={"url": "https://example.com"})# Health check for all skills
curl http://localhost:8000/health
# Get unified catalog
curl http://localhost:8000/catalog
# Hot-reload skills (add/remove without restart)
curl -X POST http://localhost:8000/reloadOpenAI Function Calling:
# Get all skills from single endpoint
skills = requests.get("http://localhost:8000/catalog").json()["skills"]
# Build function definitions (same pattern as before)
functions = []
for skill in skills:
schema_url = f"http://localhost:8000{skill['skill']['endpoints']['schema']}"
schema = requests.get(schema_url).json()
functions.append({
"name": schema["name"],
"description": schema["description"],
"parameters": schema["parameters"]
})Discovery Service Integration:
# Update Discovery Service to use consolidated host
skills:
# Instead of multiple services:
# - "http://localhost:8001" # time
# - "http://localhost:8002" # fetch
# - "http://localhost:8003" # memory
# Use single consolidated host:
- "http://localhost:8000/skills/time"
- "http://localhost:8000/skills/fetch"
- "http://localhost:8000/skills/memory"- Phase 1: Deploy consolidated host alongside existing services
- Phase 2: Update clients to use consolidated endpoints
- Phase 3: Shut down individual microservices
- Phase 4: Optimize and scale consolidated host
For complete examples, see the Multi-Skill Runtime documentation and the Multi-Skill Runtime Demo.