Skip to main content
The Skills Service provides programmatic access to manage skills and tool sets in the Kubiya platform. Skills are collections of capabilities and tools that can be assigned to agents, enabling them to perform specific tasks and operations.
For conceptual information about skills and how they’re used in agents, see Skills Core Concepts.

Overview

The Skills Service enables you to:
  • List available skills with pagination support
  • Get skill details including capabilities, tools, and configurations
  • Create custom skills with specific tool sets and capabilities
  • Update skill configurations for existing skills
  • Delete skills when no longer needed
  • Associate skills with entities (agents, teams, etc.)
  • Validate skill configurations before deployment

Quick Start

from kubiya import ControlPlaneClient

# Initialize client
client = ControlPlaneClient(api_key="your-api-key")

# List all available skills
skills = client.skills.list()
for skill in skills:
    print(f"Skill: {skill['name']} - Category: {skill.get('category', 'N/A')}")

# Get specific skill details
skill = client.skills.get("skill-uuid")
print(f"Tools: {skill.get('tools', [])}")

List Skills

List all available skills with pagination support.

Basic Listing

# List all skills (first 100)
skills = client.skills.list()

for skill in skills:
    print(f"""
    Name: {skill['name']}
    Category: {skill.get('category', 'N/A')}
    Description: {skill.get('description', 'N/A')}
    Tools: {len(skill.get('tools', []))} tools
    """)

Paginated Listing

# List skills with pagination
skip = 0
limit = 20

while True:
    skills = client.skills.list(skip=skip, limit=limit)

    if not skills:
        break

    for skill in skills:
        print(f"Skill: {skill['name']}")

    skip += limit

List All Skills

def list_all_skills():
    """Get all skills across all pages"""
    all_skills = []
    skip = 0
    limit = 100

    while True:
        skills = client.skills.list(skip=skip, limit=limit)

        if not skills:
            break

        all_skills.extend(skills)
        skip += limit

    return all_skills

# Usage
all_skills = list_all_skills()
print(f"Total skills: {len(all_skills)}")

Filter Skills by Category

def filter_skills_by_category(category: str):
    """Filter skills by category"""
    all_skills = client.skills.list(limit=1000)  # Get all skills

    return [s for s in all_skills if s.get('category') == category]

# Usage
cloud_skills = filter_skills_by_category("Cloud")
print(f"Cloud skills: {len(cloud_skills)}")

devops_skills = filter_skills_by_category("DevOps")
print(f"DevOps skills: {len(devops_skills)}")

Get Skill Details

Retrieve detailed information about a specific skill.

By Skill ID

# Get skill by UUID
skill = client.skills.get("skill-uuid-here")

print(f"Skill: {skill['name']}")
print(f"Description: {skill.get('description', 'N/A')}")
print(f"Category: {skill.get('category', 'N/A')}")
print(f"Tools: {skill.get('tools', [])}")
print(f"Capabilities: {skill.get('capabilities', [])}")

Extract Skill Information

def get_skill_info(skill_id: str):
    """Get comprehensive skill information"""
    try:
        skill = client.skills.get(skill_id)

        info = {
            "id": skill.get('uuid'),
            "name": skill['name'],
            "description": skill.get('description'),
            "category": skill.get('category'),
            "tools": skill.get('tools', []),
            "capabilities": skill.get('capabilities', []),
            "required_integrations": skill.get('required_integrations', []),
            "configuration": skill.get('configuration', {}),
            "enabled": skill.get('enabled', True)
        }

        return info
    except Exception as e:
        print(f"Failed to get skill info: {e}")
        return None

# Usage
info = get_skill_info("skill-uuid")
if info:
    print(f"Skill: {info['name']}")
    print(f"Tools: {len(info['tools'])}")
    print(f"Capabilities: {info['capabilities']}")

Find Skill by Name

def find_skill_by_name(name: str):
    """Find a skill by name"""
    all_skills = client.skills.list(limit=1000)

    for skill in all_skills:
        if skill['name'].lower() == name.lower():
            return skill

    return None

# Usage
kubernetes_skill = find_skill_by_name("kubernetes")
if kubernetes_skill:
    print(f"Found skill: {kubernetes_skill['uuid']}")
    skill_details = client.skills.get(kubernetes_skill['uuid'])
    print(f"Tools: {skill_details.get('tools', [])}")

Create Custom Skill

Create a new custom skill with specific tools and capabilities.

Basic Creation

# Create a custom skill
skill_data = {
    "name": "custom-database-admin",
    "description": "Database administration tools",
    "category": "Database",
    "tools": [
        {
            "name": "query_database",
            "description": "Execute database queries",
            "type": "shell"
        },
        {
            "name": "backup_database",
            "description": "Create database backups",
            "type": "shell"
        }
    ],
    "capabilities": ["database_query", "database_backup"],
    "enabled": True
}

created_skill = client.skills.create(skill_data)
print(f"Created skill: {created_skill['uuid']}")
print(f"Name: {created_skill['name']}")

Create with Integrations

# Create skill with required integrations
skill_data = {
    "name": "aws-infrastructure",
    "description": "AWS infrastructure management",
    "category": "Cloud",
    "tools": [
        {
            "name": "describe_instances",
            "description": "List EC2 instances",
            "type": "shell",
            "command": "aws ec2 describe-instances"
        },
        {
            "name": "list_s3_buckets",
            "description": "List S3 buckets",
            "type": "shell",
            "command": "aws s3 ls"
        }
    ],
    "required_integrations": ["AWS"],
    "capabilities": ["cloud_management", "infrastructure_automation"],
    "configuration": {
        "region": "us-east-1",
        "output_format": "json"
    }
}

created_skill = client.skills.create(skill_data)
print(f"Created AWS skill: {created_skill['uuid']}")

Create with Validation

from kubiya.resources.exceptions import SkillError

def create_skill_safe(skill_data: dict):
    """Create skill with pre-validation"""
    try:
        # Validate configuration first
        validation = client.skills.validate(skill_data)

        if not validation.get('valid'):
            return {
                "success": False,
                "errors": validation.get('errors', [])
            }

        # Create skill
        skill = client.skills.create(skill_data)

        return {
            "success": True,
            "skill_id": skill['uuid'],
            "skill": skill
        }
    except SkillError as e:
        return {
            "success": False,
            "errors": [str(e)]
        }

# Usage
skill_data = {
    "name": "custom-monitoring",
    "description": "System monitoring tools",
    "category": "Monitoring",
    "tools": [{"name": "check_health", "type": "shell"}]
}

result = create_skill_safe(skill_data)
if result['success']:
    print(f"✅ Created skill: {result['skill_id']}")
else:
    print(f"❌ Creation failed: {result['errors']}")

Update Skill

Update an existing skill configuration.

Basic Update

# Update skill settings
skill_id = "skill-uuid-here"

update_data = {
    "description": "Updated description",
    "enabled": True,
    "tools": [
        {
            "name": "new_tool",
            "description": "A new tool",
            "type": "shell"
        }
    ]
}

updated_skill = client.skills.update(skill_id, update_data)
print(f"Updated skill: {updated_skill['name']}")
print(f"Description: {updated_skill['description']}")

Add Tools to Skill

def add_tools_to_skill(skill_id: str, new_tools: list):
    """Add tools to an existing skill"""
    # Get current skill
    skill = client.skills.get(skill_id)

    # Get current tools
    current_tools = skill.get('tools', [])

    # Add new tools
    updated_tools = current_tools + new_tools

    # Update skill
    update_data = {"tools": updated_tools}
    updated_skill = client.skills.update(skill_id, update_data)

    return updated_skill

# Usage
new_tools = [
    {
        "name": "analyze_logs",
        "description": "Analyze system logs",
        "type": "python"
    }
]

updated = add_tools_to_skill("skill-uuid", new_tools)
print(f"Updated skill with {len(updated['tools'])} tools")

Enable/Disable Skill

def toggle_skill(skill_id: str, enabled: bool):
    """Enable or disable a skill"""
    update_data = {"enabled": enabled}
    updated_skill = client.skills.update(skill_id, update_data)

    status = "enabled" if enabled else "disabled"
    print(f"Skill {skill_id} is now {status}")

    return updated_skill

# Usage
toggle_skill("skill-uuid", False)  # Disable
toggle_skill("skill-uuid", True)   # Enable

Delete Skill

Delete a custom skill.
Deleting a skill affects any agents or entities using it. Ensure no active agents depend on the skill before deletion.
# Delete skill
skill_id = "skill-uuid-to-delete"

result = client.skills.delete(skill_id)
print(f"Deletion result: {result}")

Delete with Safety Check

def delete_skill_safe(skill_id: str):
    """Delete skill with confirmation"""
    try:
        # Get skill details first
        skill = client.skills.get(skill_id)

        print(f"About to delete skill: {skill['name']}")
        print(f"Category: {skill.get('category')}")

        # Perform deletion
        result = client.skills.delete(skill_id)

        return {
            "success": True,
            "message": f"Deleted skill: {skill['name']}",
            "result": result
        }
    except SkillError as e:
        return {
            "success": False,
            "message": str(e)
        }

# Usage
result = delete_skill_safe("skill-uuid")
if result['success']:
    print(f"✅ {result['message']}")
else:
    print(f"❌ Deletion failed: {result['message']}")

Associate Skills with Entities

Associate skills with agents, teams, or other entities.

Associate Skills with Agent

# Associate skills with an agent
agent_id = "agent-uuid"
skill_ids = ["skill-uuid-1", "skill-uuid-2", "skill-uuid-3"]

result = client.skills.associate(agent_id, skill_ids)
print(f"Association result: {result}")

Bulk Association

def associate_skills_bulk(entity_id: str, skill_names: list):
    """Associate skills by name"""
    # Find skill IDs by name
    all_skills = client.skills.list(limit=1000)

    skill_ids = []
    for name in skill_names:
        for skill in all_skills:
            if skill['name'].lower() == name.lower():
                skill_ids.append(skill['uuid'])
                break

    if len(skill_ids) != len(skill_names):
        print(f"Warning: Only found {len(skill_ids)} of {len(skill_names)} skills")

    # Associate skills
    result = client.skills.associate(entity_id, skill_ids)

    return result

# Usage
skill_names = ["kubernetes", "terraform", "aws"]
result = associate_skills_bulk("agent-uuid", skill_names)
print(f"Associated {len(skill_names)} skills")

Replace Skills for Entity

def replace_entity_skills(entity_id: str, new_skill_ids: list):
    """Replace all skills for an entity"""
    # Associate new skills (this replaces existing associations)
    result = client.skills.associate(entity_id, new_skill_ids)

    print(f"Replaced skills for entity {entity_id}")
    print(f"New skill count: {len(new_skill_ids)}")

    return result

# Usage
new_skills = ["skill-uuid-1", "skill-uuid-2"]
replace_entity_skills("agent-uuid", new_skills)

Validate Skill Configuration

Validate a skill configuration before creation or update.

Basic Validation

# Validate skill configuration
skill_config = {
    "name": "test-skill",
    "description": "Test skill for validation",
    "category": "Testing",
    "tools": [
        {
            "name": "test_tool",
            "description": "A test tool",
            "type": "shell"
        }
    ],
    "capabilities": ["testing"]
}

validation_result = client.skills.validate(skill_config)

if validation_result.get('valid'):
    print("✅ Configuration is valid!")
else:
    print("❌ Configuration is invalid:")
    for error in validation_result.get('errors', []):
        print(f"  - {error}")

Validate Before Creation

def create_skill_with_validation(skill_data: dict):
    """Create skill with automatic validation"""
    # Validate first
    validation = client.skills.validate(skill_data)

    if not validation.get('valid'):
        return {
            "success": False,
            "message": "Validation failed",
            "errors": validation.get('errors', [])
        }

    # Create skill
    try:
        skill = client.skills.create(skill_data)
        return {
            "success": True,
            "message": "Skill created successfully",
            "skill_id": skill['uuid'],
            "skill": skill
        }
    except SkillError as e:
        return {
            "success": False,
            "message": "Creation failed",
            "errors": [str(e)]
        }

# Usage
skill_data = {
    "name": "monitoring-alerts",
    "category": "Monitoring",
    "tools": [{"name": "send_alert", "type": "shell"}]
}

result = create_skill_with_validation(skill_data)
if result['success']:
    print(f"✅ {result['message']}: {result['skill_id']}")
else:
    print(f"❌ {result['message']}")
    for error in result['errors']:
        print(f"  - {error}")

Practical Examples

1. Skill Discovery System

def discover_skills(requirements: dict):
    """Discover skills matching requirements"""
    all_skills = client.skills.list(limit=1000)

    required_capabilities = set(requirements.get('capabilities', []))
    required_category = requirements.get('category')

    matching_skills = []

    for skill in all_skills:
        skill_capabilities = set(skill.get('capabilities', []))
        skill_category = skill.get('category')

        # Check category match
        if required_category and skill_category != required_category:
            continue

        # Check capabilities match
        if required_capabilities and not required_capabilities.issubset(skill_capabilities):
            continue

        # Calculate match score
        match_score = len(required_capabilities & skill_capabilities)

        matching_skills.append({
            "skill": skill,
            "match_score": match_score
        })

    # Sort by match score
    matching_skills.sort(key=lambda x: x['match_score'], reverse=True)

    return matching_skills

# Usage
requirements = {
    "capabilities": ["cloud_management", "automation"],
    "category": "Cloud"
}

matches = discover_skills(requirements)
print(f"Found {len(matches)} matching skills:")
for match in matches[:5]:  # Top 5
    skill = match['skill']
    print(f"  - {skill['name']} (score: {match['match_score']})")

2. Skill Audit Report

def generate_skill_audit():
    """Generate audit report of all skills"""
    all_skills = client.skills.list(limit=1000)

    audit = {
        "total_skills": len(all_skills),
        "enabled": 0,
        "disabled": 0,
        "by_category": {},
        "tool_count": 0,
        "skills_without_description": []
    }

    for skill in all_skills:
        # Count enabled/disabled
        if skill.get('enabled', True):
            audit['enabled'] += 1
        else:
            audit['disabled'] += 1

        # Count by category
        category = skill.get('category', 'Uncategorized')
        audit['by_category'][category] = audit['by_category'].get(category, 0) + 1

        # Count tools
        audit['tool_count'] += len(skill.get('tools', []))

        # Track skills without description
        if not skill.get('description'):
            audit['skills_without_description'].append(skill['name'])

    return audit

# Usage
audit = generate_skill_audit()
print(f"Skill Audit Report:")
print(f"  Total Skills: {audit['total_skills']}")
print(f"  Enabled: {audit['enabled']}")
print(f"  Disabled: {audit['disabled']}")
print(f"  Total Tools: {audit['tool_count']}")
print(f"\nBy Category:")
for category, count in audit['by_category'].items():
    print(f"  {category}: {count}")

3. Skill Configuration Manager

class SkillConfigManager:
    """Helper class for managing skill configurations"""

    def __init__(self, client):
        self.client = client

    def create_from_template(self, template_name: str, custom_config: dict):
        """Create skill from template"""
        templates = {
            "monitoring": {
                "category": "Monitoring",
                "capabilities": ["monitoring", "alerting"],
                "tools": [
                    {"name": "check_status", "type": "shell"},
                    {"name": "send_alert", "type": "shell"}
                ]
            },
            "deployment": {
                "category": "DevOps",
                "capabilities": ["deployment", "automation"],
                "tools": [
                    {"name": "deploy_app", "type": "shell"},
                    {"name": "rollback", "type": "shell"}
                ]
            }
        }

        if template_name not in templates:
            raise ValueError(f"Unknown template: {template_name}")

        # Merge template with custom config
        skill_config = {**templates[template_name], **custom_config}

        # Validate
        validation = self.client.skills.validate(skill_config)
        if not validation.get('valid'):
            raise ValueError(f"Invalid configuration: {validation.get('errors')}")

        # Create skill
        skill = self.client.skills.create(skill_config)
        return skill

    def clone_skill(self, source_skill_id: str, new_name: str):
        """Clone an existing skill"""
        # Get source skill
        source = self.client.skills.get(source_skill_id)

        # Create new skill config
        new_config = {
            "name": new_name,
            "description": f"Cloned from {source['name']}",
            "category": source.get('category'),
            "tools": source.get('tools', []),
            "capabilities": source.get('capabilities', []),
            "configuration": source.get('configuration', {})
        }

        # Create new skill
        skill = self.client.skills.create(new_config)
        return skill

# Usage
manager = SkillConfigManager(client)

# Create from template
new_skill = manager.create_from_template("monitoring", {
    "name": "production-monitoring",
    "description": "Production environment monitoring"
})
print(f"Created from template: {new_skill['uuid']}")

# Clone existing skill
cloned = manager.clone_skill("existing-skill-uuid", "cloned-skill-name")
print(f"Cloned skill: {cloned['uuid']}")

4. Skill Dependencies Validator

def validate_skill_dependencies(skill_config: dict):
    """Validate that all required integrations are available"""
    required_integrations = skill_config.get('required_integrations', [])

    if not required_integrations:
        return {"valid": True, "message": "No dependencies required"}

    # Get available integrations
    available_integrations = client.integrations.list()
    available_names = [i['name'] for i in available_integrations]

    missing = []
    for required in required_integrations:
        if required not in available_names:
            missing.append(required)

    if missing:
        return {
            "valid": False,
            "message": "Missing required integrations",
            "missing": missing
        }

    return {
        "valid": True,
        "message": "All dependencies available",
        "required": required_integrations
    }

# Usage
skill_config = {
    "name": "aws-ops",
    "required_integrations": ["AWS", "Slack"]
}

deps_check = validate_skill_dependencies(skill_config)
if deps_check['valid']:
    print(f"✅ {deps_check['message']}")
else:
    print(f"❌ {deps_check['message']}")
    print(f"Missing: {deps_check['missing']}")

Error Handling

from kubiya.resources.exceptions import SkillError

try:
    # Try to get a skill
    skill = client.skills.get("non-existent-skill")
except SkillError as e:
    print(f"Skill error: {e}")
    # Handle error - maybe list all skills instead
    print("Available skills:")
    skills = client.skills.list(limit=10)
    for skill in skills:
        print(f"  - {skill['name']}")

# Create with error handling
try:
    skill_data = {
        "name": "test-skill",
        "category": "Testing"
    }
    skill = client.skills.create(skill_data)
    print(f"Created skill: {skill['uuid']}")
except SkillError as e:
    print(f"Creation failed: {e}")

# Validate with error handling
try:
    validation = client.skills.validate(skill_data)
    if not validation.get('valid'):
        print(f"Validation errors: {validation.get('errors')}")
except SkillError as e:
    print(f"Validation error: {e}")

Best Practices

1. Always Validate Before Creating

# Always validate skill configuration before creating
def create_skill_safely(skill_data: dict):
    """Create skill with validation"""
    # Validate first
    validation = client.skills.validate(skill_data)

    if not validation.get('valid'):
        raise ValueError(f"Invalid skill configuration: {validation.get('errors')}")

    # Create skill
    skill = client.skills.create(skill_data)
    return skill

# Usage
skill_data = {
    "name": "my-skill",
    "category": "Custom",
    "tools": [{"name": "tool1", "type": "shell"}]
}

try:
    skill = create_skill_safely(skill_data)
    print(f"✅ Created skill: {skill['uuid']}")
except ValueError as e:
    print(f"❌ {e}")

2. Cache Skill Information

# Cache skills to reduce API calls
class SkillCache:
    def __init__(self, client):
        self.client = client
        self._skills_cache = None
        self._skill_details_cache = {}

    def get_all_skills(self, force_refresh=False):
        """Get cached skills"""
        if self._skills_cache is None or force_refresh:
            self._skills_cache = self.client.skills.list(limit=1000)
        return self._skills_cache

    def get_skill(self, skill_id: str, force_refresh=False):
        """Get cached skill details"""
        if skill_id not in self._skill_details_cache or force_refresh:
            self._skill_details_cache[skill_id] = self.client.skills.get(skill_id)
        return self._skill_details_cache[skill_id]

    def invalidate_cache(self):
        """Clear the cache"""
        self._skills_cache = None
        self._skill_details_cache = {}

# Usage
cache = SkillCache(client)
skills = cache.get_all_skills()  # API call
skills_again = cache.get_all_skills()  # From cache

3. Use Descriptive Names and Categories

# Good - descriptive names
skill_data = {
    "name": "aws-ec2-management",
    "description": "Manage AWS EC2 instances including start, stop, and monitoring",
    "category": "Cloud/AWS",
    "tools": [...]
}

# Bad - vague names
skill_data = {
    "name": "skill1",
    "description": "Does stuff",
    "category": "Other",
    "tools": [...]
}

4. Document Tool Configurations

# Include clear descriptions for all tools
skill_data = {
    "name": "database-admin",
    "category": "Database",
    "tools": [
        {
            "name": "query_database",
            "description": "Execute SQL queries against the database",
            "type": "shell",
            "command": "psql -c \"{{query}}\"",
            "parameters": [
                {
                    "name": "query",
                    "description": "SQL query to execute",
                    "required": True
                }
            ]
        }
    ]
}

API Reference

Methods

MethodDescriptionParameters
list(skip, limit)List all skillsskip: Records to skip, limit: Max records
get(skill_id)Get specific skillskill_id: Skill UUID
create(skill_data)Create custom skillskill_data: Skill configuration dictionary
update(skill_id, skill_data)Update skillskill_id: UUID, skill_data: Updates
delete(skill_id)Delete skillskill_id: Skill UUID
associate(entity_id, skill_ids)Associate skills with entityentity_id: Entity UUID, skill_ids: List of skill UUIDs
validate(skill_config)Validate skill configurationskill_config: Configuration dictionary

Skill Object Structure

{
    "uuid": "string",                    # Unique identifier
    "name": "string",                    # Skill name
    "description": "string",             # Skill description
    "category": "string",                # Category (e.g., "Cloud", "DevOps")
    "tools": [                           # List of tools
        {
            "name": "string",
            "description": "string",
            "type": "string",            # Tool type (shell, python, etc.)
            "command": "string",         # Command to execute
            "parameters": [dict]         # Tool parameters
        }
    ],
    "capabilities": ["string"],          # List of capabilities
    "required_integrations": ["string"], # Required integrations
    "configuration": dict,               # Skill configuration
    "enabled": bool,                     # Whether skill is enabled
    "created_at": "string",              # Creation timestamp
    "updated_at": "string"               # Last update timestamp
}

Validation Result Object Structure

{
    "valid": bool,                       # Whether configuration is valid
    "errors": ["string"],                # List of validation errors
    "warnings": ["string"],              # List of validation warnings
    "validated_config": dict             # Validated configuration
}

Next Steps