Skip to main content

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.

Skill Capability Gates allow you to declare tool, server, and environment variable requirements in your skills and enforce them at runtime with configurable strictness levels.

Quick Start

1

Simple Agent with Skill Requirements

from praisonaiagents import Agent

agent = Agent(
    name="PDF Assistant",
    instructions="Process PDFs for the user",
    skills=["./skills/pdf-processor"]  # skill declares requires_tools
)

agent.start("Extract text from invoice.pdf")
# → if requires_tools are missing, skill is degraded/unavailable based on enforcement level
2

Skill with Capability Requirements

Create a SKILL.md with requirements:
---
name: pdf-processor
description: Extract text and OCR from PDF documents
requires_tools: [pdf_read, ocr_extract]
requires_servers: ["mcp:filesystem"]
requires_env: [OPENAI_API_KEY]
---

# PDF Processing Instructions
When asked to process a PDF, call pdf_read first, then ocr_extract for image pages.

How It Works

ComponentPurpose
SkillRequirementsParsed requirements from frontmatter
CapabilityValidatorValidates skills against available capabilities
ValidationResultPer-skill validation status and details
EnforcementLevelControls strictness of requirement checking

Frontmatter Reference

All frontmatter keys are optional and backward-compatible. Existing skills without requirements are unaffected.
Frontmatter KeyAliasesTypeMaps to
requires_toolsrequires-toolslist[str] or stringSkillRequirements.tools
requires_serversrequires-serverslist[str] or stringSkillRequirements.servers
requires_envrequires-envlist[str] or stringSkillRequirements.env_vars
allowed-toolslist[str] or stringAlso appended to tools (backward compat)
openclawdictSkillRequirements.openclaw_hints (passthrough)
String forms are normalized — both requires_tools: "pdf_read, ocr_extract" and requires_tools: "pdf_read ocr_extract" work.

Skill States

StateMeaningBehavior
ACTIVEAll requirements satisfiedSkill fully available
DEGRADEDSome requirements missing (env vars)Skill available with warnings
UNAVAILABLECritical requirements missing (tools/servers)Under strict mode, excluded from picker
UNKNOWNNot yet validatedInitial state before validation

Enforcement Levels

LevelValueBehaviorLogging
DISABLED"disabled"No enforcement (legacy behavior)None
TELEMETRY"telemetry"Log-only, no blockingDebug/warn
WARN"warn"Default — surface warnings, allow activationWarning
STRICT"strict"Hard fail — skills in UNAVAILABLE state excluded from system promptError

Configuration

Environment Variable

# Set enforcement level (case-insensitive)
export SKILL_CAPABILITY_ENFORCEMENT=strict

# Accepted values
SKILL_CAPABILITY_ENFORCEMENT=disabled  # or 'off'
SKILL_CAPABILITY_ENFORCEMENT=telemetry # or 'log'
SKILL_CAPABILITY_ENFORCEMENT=warn      # or 'warning' (default)
SKILL_CAPABILITY_ENFORCEMENT=strict    # or 'hard', 'fail'

Programmatic Configuration

from praisonaiagents.skills import SkillManager, EnforcementLevel

# Default (uses environment or 'warn')
manager = SkillManager()

# Explicit enforcement level
manager = SkillManager(enforcement_level=EnforcementLevel.STRICT)

Diagnostics from Code

Basic Validation

from praisonaiagents.skills import SkillManager

manager = SkillManager()
manager.discover(["./skills"])

# Validate specific skill
result = manager.validate_skill_capabilities("pdf-processor")
print(f"State: {result.state.value}")
print(f"Missing tools: {result.missing_tools}")
print(f"Missing servers: {result.missing_servers}")

Full Diagnostics

# Get diagnostics for all skills
diagnostics = manager.get_skills_diagnostics()

for name, result in diagnostics.items():
    print(f"{name}: {result.state.value}")
    if result.warnings:
        print(f"  Warnings: {result.warnings}")
    if result.errors:
        print(f"  Errors: {result.errors}")

Filter Skills by State

from praisonaiagents.skills import SkillState

# Get only active skills
active_skills = manager.get_available_skills_by_state(SkillState.ACTIVE)

# Get degraded skills
degraded_skills = manager.get_available_skills_by_state(SkillState.DEGRADED)

CLI Diagnostics

Basic Skills Check

praisonai doctor skills                  # Basic skills health check
praisonai doctor skills --deep           # Deeper probes
praisonai doctor skills --json           # JSON output

Detailed Requirements Check

praisonai doctor skills --requirements   # Show detailed per-skill diagnostics
Sample output structure:
{
  "total_skills": 5,
  "active": 3,
  "degraded": 1,
  "unavailable": 1,
  "enforcement_level": "warn",
  "sample_issues": [
    "pdf-processor: Missing required tools: pdf_read",
    "email-sender: Missing required environment variables: SMTP_PASSWORD"
  ]
}

Common Patterns

Soft-warn in Dev, Strict in Prod

import os

# Production configuration
if os.getenv('ENV') == 'production':
    os.environ['SKILL_CAPABILITY_ENFORCEMENT'] = 'strict'
else:
    os.environ['SKILL_CAPABILITY_ENFORCEMENT'] = 'warn'

from praisonaiagents import Agent
agent = Agent(skills=["./skills"])

Add Tool Requirement to Existing Skill

---
name: existing-skill
description: Existing skill functionality
# Add new requirement
requires_tools: [new_required_tool]
---

Filter to Active-Only Skills for System Prompt

from praisonaiagents.skills import SkillManager, EnforcementLevel

# Strict mode automatically filters system prompt
manager = SkillManager(enforcement_level=EnforcementLevel.STRICT)
manager.discover()

# Only active skills included in prompt
prompt_xml = manager.to_prompt()

Best Practices

Use the new requires_tools frontmatter key for better validation:
# Preferred (new)
requires_tools: [pdf_read, ocr_extract]

# Still supported (legacy)
allowed-tools: [pdf_read, ocr_extract]
Minimize environment variable dependencies:
# Prefer tool-level authentication
requires_tools: [authenticated_api_client]

# Avoid if possible
requires_env: [API_KEY, SECRET_TOKEN]
Configure appropriate enforcement levels:
# Development
SKILL_CAPABILITY_ENFORCEMENT=warn

# Production
SKILL_CAPABILITY_ENFORCEMENT=strict
Validation results are automatically cached for performance:
manager = SkillManager()

# First call validates and caches
result1 = manager.validate_skill_capabilities("skill-name")

# Second call uses cache
result2 = manager.validate_skill_capabilities("skill-name")

# Force refresh
result3 = manager.validate_skill_capabilities("skill-name", force_refresh=True)

# Clear all caches
manager.clear()

Agent Skills

Learn about the Agent Skills system and how to create skills

Hermes/OpenClaw Import

Import skills from Hermes and OpenClaw with capability requirements

Skill Management

Manage skills programmatically with the SkillManager API

Doctor CLI

Use the doctor command to diagnose skill capability issues