Documentation Index
Fetch the complete documentation index at: https://docs.praison.ai/llms.txt
Use this file to discover all available pages before exploring further.
Agent Skills
Agent Skills is an open standard for extending AI agent capabilities with specialized knowledge and workflows. PraisonAI Agents fully supports the Agent Skills specification, enabling agents to load and use modular capabilities through SKILL.md files.
Overview
Skills provide a way to give agents specialized knowledge and instructions without bloating the main system prompt. They use progressive disclosure to efficiently manage context:
- Level 1 - Metadata (~100 tokens): Name and description loaded at startup
- Level 2 - Instructions (<5000 tokens): Full SKILL.md body loaded when activated
- Level 3 - Resources (as needed): Scripts, references, and assets loaded on demand
Quick Start
Using Skills with an Agent
from praisonaiagents import Agent
# Create an agent with specific skills
agent = Agent(
name="PDF Assistant",
instructions="You are a helpful assistant.",
skills=["./skills/pdf-processing"], # Direct skill paths
)
# Or discover skills from directories
agent = Agent(
name="Multi-Skill Agent",
instructions="You are a versatile assistant.",
skills_dirs=["./skills"], # Scan for skill subdirectories
)
Using SkillManager Directly
from praisonaiagents import SkillManager
# Create a skill manager
manager = SkillManager()
# Discover skills from directories
manager.discover(["./skills"])
# Generate prompt XML for system prompt injection
prompt_xml = manager.to_prompt()
print(prompt_xml)
Each skill is a directory containing a SKILL.md file with YAML frontmatter:
---
name: pdf-processing
description: Process and extract information from PDF documents. Use this skill when the user asks to read, analyze, or extract data from PDF files.
license: Apache-2.0
compatibility: Works with PraisonAI Agents
metadata:
author: your-org
version: "1.0"
allowed-tools: Read Write # Optional: space-delimited tool list
---
# PDF Processing Skill
## Overview
This skill enables agents to process PDF documents...
## Instructions
1. First, verify the PDF file exists
2. Use appropriate tools to read the PDF content
3. Extract text while preserving structure
Required Fields
| Field | Description | Constraints |
|---|
name | Skill identifier | 1-64 chars, lowercase, hyphens only |
description | What the skill does and when to use it | 1-1024 chars |
Optional Fields
| Field | Description |
|---|
license | License for the skill (e.g., Apache-2.0, MIT) |
compatibility | Compatibility information (max 500 chars) |
metadata | Key-value pairs for custom properties |
allowed-tools | Space-delimited list of tools the skill requires |
Directory Structure
my-skill/
├── SKILL.md # Required: Skill definition
├── scripts/ # Optional: Executable code
├── references/ # Optional: Additional documentation
└── assets/ # Optional: Templates, data files
Skill Discovery Locations
PraisonAI searches for skills in these locations (in order of precedence):
- Project:
./.praison/skills/ or ./.claude/skills/
- User:
~/.praisonai/skills/
- System:
/etc/praison/skills/
CLI Commands
List Available Skills
praisonai skills list
praisonai skills list --dirs ./my-skills ./other-skills
Validate a Skill
praisonai skills validate --path ./my-skill
Create a New Skill
praisonai skills create --name my-new-skill --description "A custom skill"
Generate Prompt XML
praisonai skills prompt --dirs ./skills
API Reference
SkillManager
The main class for managing skills.
from praisonaiagents import SkillManager
manager = SkillManager()
# Discover skills
count = manager.discover(["./skills"], include_defaults=True)
# Add a single skill
skill = manager.add_skill("./path/to/skill")
# Get a skill by name
skill = manager.get_skill("pdf-processing")
# Activate a skill (load instructions)
manager.activate_by_name("pdf-processing")
# Get instructions
instructions = manager.get_instructions("pdf-processing")
# Generate prompt XML
prompt = manager.to_prompt()
SkillLoader
For progressive loading of skills.
from praisonaiagents.skills import SkillLoader
loader = SkillLoader()
# Level 1: Load metadata only
skill = loader.load_metadata("./my-skill")
# Level 2: Activate (load instructions)
loader.activate(skill)
print(skill.instructions)
# Level 3: Load resources
scripts = loader.load_scripts(skill)
references = loader.load_references(skill)
assets = loader.load_assets(skill)
Validation
from praisonaiagents.skills import validate, validate_metadata
# Validate a skill directory
errors = validate("./my-skill")
if errors:
for error in errors:
print(f"Error: {error}")
else:
print("Skill is valid!")
# Validate metadata dict
errors = validate_metadata({"name": "test", "description": "Test skill"})
Compatibility
PraisonAI’s Agent Skills implementation follows the open standard, ensuring compatibility with:
- Claude Code (
.claude/skills/)
- GitHub Copilot (
.github/skills/)
- Cursor (Agent Skills support)
- OpenAI Codex CLI
PraisonAI supports both .praison/skills/ and .claude/skills/ for maximum compatibility.
Agent Skills are designed for zero performance impact when not in use:
- Lazy Loading: Skills are only loaded when explicitly accessed
- No Auto-discovery: Discovery runs only when requested
- Minimal Memory: Skills not in use consume no memory
- Progressive Disclosure: Only load what’s needed
Direct API Integration Examples
OpenAI API (gpt-4o-mini)
Complete flat file implementation showing how skills work with OpenAI’s API:
"""
Agent Skills with OpenAI API using gpt-4o-mini.
Flat file code - no functions or classes.
"""
import os
from pathlib import Path
import yaml
from openai import OpenAI
# Initialize OpenAI client
client = OpenAI()
# Step 1: Discover skills from a directory
skill_dirs = ["./.praison/skills"]
skills = []
for dir_path in skill_dirs:
dir_path = Path(dir_path).expanduser()
if not dir_path.exists():
continue
for skill_path in dir_path.iterdir():
if not skill_path.is_dir():
continue
skill_md = skill_path / "SKILL.md"
if skill_md.exists():
content = skill_md.read_text()
# Extract frontmatter
if content.startswith("---"):
parts = content.split("---", 2)
frontmatter = yaml.safe_load(parts[1])
instructions = parts[2].strip()
skills.append({
"name": frontmatter["name"],
"description": frontmatter["description"],
"instructions": instructions
})
print(f"Discovered {len(skills)} skills")
# Step 2: Generate XML for system prompt
xml_parts = ["<available_skills>"]
for skill in skills:
xml_parts.append(f""" <skill>
<name>{skill['name']}</name>
<description>{skill['description']}</description>
</skill>""")
xml_parts.append("</available_skills>")
skills_xml = "\n".join(xml_parts)
# Step 3: Create system prompt with skills
system_prompt = f"""You are a helpful AI assistant.
{skills_xml}
When a request matches a skill, respond with: "Using [skill-name] skill"
"""
# Step 4: Make API call with gpt-4o-mini
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": "Extract text from document.pdf"}
]
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages
)
assistant_msg = response.choices[0].message.content
print(f"Assistant: {assistant_msg}")
messages.append({"role": "assistant", "content": assistant_msg})
# Step 5: If skill mentioned, activate it
activated = False
for skill in skills:
if skill["name"] in assistant_msg.lower():
print(f"Activating {skill['name']} skill")
messages.append({
"role": "user",
"content": f"<skill_context>\n{skill['instructions']}\n</skill_context>"
})
activated = True
break
# Step 6: Continue conversation with skill context
if activated:
messages.append({"role": "user", "content": "Now help me with this task"})
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages
)
print(f"Assistant: {response.choices[0].message.content}")
# Show token usage
print(f"Total tokens: {response.usage.total_tokens}")
Anthropic Claude API
Complete flat file implementation showing how skills work with Claude:
"""
Agent Skills with Anthropic Claude API.
Flat file code using Claude Sonnet 4.
"""
import os
from pathlib import Path
import yaml
from anthropic import Anthropic
# Initialize Anthropic client
client = Anthropic()
# Step 1: Discover skills from directory
skill_dirs = ["./.praison/skills"]
skills = []
for dir_path in skill_dirs:
dir_path = Path(dir_path).expanduser()
if not dir_path.exists():
continue
for skill_path in dir_path.iterdir():
if not skill_path.is_dir():
continue
skill_md = skill_path / "SKILL.md"
if skill_md.exists():
content = skill_md.read_text()
# Extract frontmatter
if content.startswith("---"):
parts = content.split("---", 2)
frontmatter = yaml.safe_load(parts[1])
instructions = parts[2].strip()
skills.append({
"name": frontmatter["name"],
"description": frontmatter["description"],
"instructions": instructions
})
print(f"Discovered {len(skills)} skills")
# Step 2: Generate XML for system prompt
xml_parts = ["<available_skills>"]
for skill in skills:
xml_parts.append(f""" <skill>
<name>{skill['name']}</name>
<description>{skill['description']}</description>
</skill>""")
xml_parts.append("</available_skills>")
skills_xml = "\n".join(xml_parts)
# Step 3: Create system prompt with skills
system_prompt = f"""You are a helpful AI assistant.
{skills_xml}
When a request matches a skill, respond with: "Using [skill-name] skill"
"""
# Step 4: Make API call with Claude
messages = [
{"role": "user", "content": "Extract text from document.pdf"}
]
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
system=system_prompt,
messages=messages
)
assistant_msg = response.content[0].text
print(f"Assistant: {assistant_msg}")
messages.append({"role": "assistant", "content": assistant_msg})
# Step 5: If skill mentioned, activate it
activated = False
for skill in skills:
if skill["name"] in assistant_msg.lower():
print(f"Activating {skill['name']} skill")
messages.append({
"role": "user",
"content": f"<skill_context>\n{skill['instructions']}\n</skill_context>"
})
activated = True
break
# Step 6: Continue conversation with skill context
if activated:
messages.append({"role": "user", "content": "Now help me with this task"})
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
system=system_prompt,
messages=messages
)
print(f"Assistant: {response.content[0].text}")
# Show token usage
print(f"Total tokens: {response.usage.input_tokens + response.usage.output_tokens}")
Key Differences Between OpenAI and Claude
| Aspect | OpenAI | Claude |
|---|
| System Prompt | Message with role: "system" | Separate system parameter |
| Response Access | response.choices[0].message.content | response.content[0].text |
| Token Usage | response.usage.total_tokens | response.usage.input_tokens + output_tokens |
| Max Tokens | Optional | Required parameter |
Examples
See the examples/skills/ directory for complete examples:
basic_skill_usage.py - Basic skill discovery and usage
custom_skill_example.py - Creating custom skills programmatically
pdf-processing/ - Example skill directory
Managing Skills at Runtime
Agents can now create, edit, and manage their own skills dynamically through the self-improving skills system. This enables agents to learn from interactions and build persistent knowledge.
from praisonaiagents import Agent
# Agent with skill management capabilities
agent = Agent(
name="Learning Assistant",
instructions="Learn from user interactions and create skills for future use.",
tools=["skill_manage", "skills_list", "skill_view"]
)
# Agent can now call:
# skill_manage(action="create", name="user-preference", content="Remember user likes...")
# skill_manage(action="edit", name="user-preference", content="Updated preferences...")
# skills_list() - to see all available skills
# skill_view("user-preference") - to examine skill details
Runtime Skill Operations
| Tool | Purpose | When to Use |
|---|
skill_manage | Create, edit, patch, or delete skills | When learning new patterns or procedures |
skills_list | List all available skills | To review existing capabilities |
skill_view | View detailed skill content | To understand specific skill instructions |
For complete details on runtime skill management, see the dedicated Self-Improving Skills documentation.
Compliance Verification
✅ FULLY COMPLIANT with agentskills.io Specification
PraisonAI’s Agent Skills implementation is fully compliant with the official agentskills.io specification.
Core Requirements
| Requirement | Spec | PraisonAI Implementation | Status |
|---|
| SKILL.md file | Required in skill directory | find_skill_md() in parser.py | ✅ |
| YAML frontmatter | Must start with --- | parse_frontmatter() validates this | ✅ |
name field | Required, max 64 chars, lowercase, hyphens only | _validate_name() enforces all rules | ✅ |
description field | Required, max 1024 chars | _validate_description() enforces | ✅ |
license field | Optional | Supported in SkillProperties | ✅ |
compatibility field | Optional, max 500 chars | _validate_compatibility() enforces | ✅ |
metadata field | Optional key-value map | Supported in SkillProperties | ✅ |
allowed-tools field | Optional, experimental | Supported as allowed_tools | ✅ |
| Directory name match | Must match name field | _validate_name() checks this | ✅ |
| No consecutive hyphens | -- not allowed | Validated in _validate_name() | ✅ |
| No leading/trailing hyphens | Cannot start/end with - | Validated in _validate_name() | ✅ |
✅ Progressive Disclosure (3-Level Loading)
| Level | Spec | PraisonAI Implementation | Status |
|---|
| Level 1: Metadata | ~100 tokens at startup | SkillMetadata with name, description, location | ✅ |
| Level 2: Instructions | <5k tokens when triggered | SkillLoader.activate() loads SKILL.md body | ✅ |
| Level 3: Resources | As needed | load_scripts(), load_references(), load_assets() | ✅ |
✅ XML Prompt Generation
The spec requires this format for Claude models:
<available_skills>
<skill>
<name>pdf-processing</name>
<description>...</description>
<location>/path/to/SKILL.md</location>
</skill>
</available_skills>
PraisonAI generates exactly this format in prompt.py:
def format_skill_for_prompt(skill: SkillMetadata) -> str:
return f""" <skill>
<name>{name}</name>
<description>{description}</description>
<location>{location}</location>
</skill>"""
✅ Skill Discovery
| Feature | Spec | PraisonAI | Status |
|---|
| Project-level | ./.praison/skills/ or ./.claude/skills/ | Both supported | ✅ |
| User-level | ~/.praisonai/skills/ | Supported | ✅ |
| System-level | /etc/praison/skills/ | Supported | ✅ |
| Custom directories | User-specified | discover_skills(skill_dirs) | ✅ |
✅ Directory Structure Support
skill-name/
├── SKILL.md # Required ✅
├── scripts/ # Optional ✅
├── references/ # Optional ✅
└── assets/ # Optional ✅
✅ Agent Integration
Agent class accepts skills and skills_dirs parameters
- Lazy loading via
skill_manager property (zero performance impact)
get_skills_prompt() returns XML for system prompt injection
✅ CLI Commands
| Command | Purpose | Status |
|---|
praisonai skills list | List available skills | ✅ |
praisonai skills validate --path | Validate skill directory | ✅ |
praisonai skills create --name | Create skill from template | ✅ |
praisonai skills prompt | Generate XML prompt | ✅ |
✅ Test Coverage
7 comprehensive test files covering all components:
test_parser.py - Frontmatter parsing
test_validator.py - All validation rules
test_discovery.py - Skill discovery
test_loader.py - Progressive loading
test_manager.py - SkillManager
test_prompt.py - XML generation
test_models.py - Data models
🔍 Implementation Details
Files Verified:
praisonaiagents/skills/:
__init__.py - Lazy loading exports
models.py - SkillProperties, SkillMetadata
parser.py - Frontmatter parsing
validator.py - All validation rules per spec
discovery.py - Directory scanning
loader.py - Progressive disclosure (3 levels)
prompt.py - XML generation
manager.py - SkillManager class
praisonai/cli/features/:
skills.py - CLI handler with list/validate/create/prompt commands
Minor Observations (No Changes Required)
-
Allowed fields validation: PraisonAI rejects unexpected fields in frontmatter, which is stricter than the spec (spec allows arbitrary fields in
metadata). This is actually better for catching errors.
-
Case-insensitive SKILL.md: PraisonAI accepts both
SKILL.md and skill.md, which is more flexible than the spec.
-
HTML escaping: XML output properly escapes special characters via
html.escape().
✅ Conclusion
PraisonAI’s Agent Skills implementation is fully compliant with the agentskills.io specification.
The implementation correctly follows:
- ✅ SKILL.md format with YAML frontmatter
- ✅ All field validation rules (name, description, compatibility limits)
- ✅ Progressive disclosure (3-level loading)
- ✅ XML prompt generation format
- ✅ Skill discovery from standard directories
- ✅ Zero performance impact when skills not used (lazy loading)
- ✅ CLI tools for skill management
No changes are required. The implementation aligns with the open Agent Skills standard as documented at agentskills.io.