Skip to main content

Overview

Skill registration is the process of making skills available to AI agents through the FastSkill service. Skills can be registered manually through the API or discovered automatically from the filesystem.
Once registered, skills become available for discovery, routing, and execution by AI agents and frameworks.

Skill Definition Format

Before registering a skill, you need to understand the skill definition format. Each skill is defined by a JSON object with specific required and optional fields:

Required Fields

id
string
required
Unique identifier for the skill. Must be alphanumeric with dashes and underscores only. Example: "text-processor", "pdf-extractor-v2".
name
string
required
Human-readable name for the skill. Should be descriptive and user-friendly. Example: "Text Processing Suite", "PDF Document Extractor".
description
string
required
Detailed description of what the skill does and its capabilities. Used for discovery and routing.
version
string
required
Version number following semantic versioning (e.g., “1.0.0”, “2.1.3”). Helps track skill evolution and compatibility.

Optional Fields

author
string
Name or organization of the skill creator. Useful for skill attribution and support.
tags
string
Comma-separated list of tags for categorization. Example: "text,nlp,analysis,extraction".
capabilities
string
Comma-separated list of specific capabilities. Example: "text_extraction,sentiment_analysis,keyword_detection".
skill_file
string
Path to the skill implementation file (relative to storage path). Example: "text-processor/SKILL.md".
enabled
boolean
Whether the skill is enabled for use. Defaults to true. Disabled skills are not available for discovery or execution.
execution_timeout
integer
Maximum execution time in seconds for this skill. Overrides the global default.
memory_limit_mb
integer
Memory limit in MB for skill execution. Overrides the global default.
dependencies
array
List of dependencies required by the skill. Example: ["serde", "tokio", "reqwest"].
metadata
object
Additional metadata as key-value pairs. Useful for custom extensions.

Manual Registration

Rust API

1

Create skill definition

use fastskill::{SkillDefinition, SkillId};

let mut skill = SkillDefinition::new(
    SkillId::new("text-processor".to_string())?,
    "Text Processing Suite".to_string(),
    "Comprehensive text processing capabilities including extraction, analysis, and transformation".to_string(),
    "1.0.0".to_string(),
);

skill.author = Some("FastSkill Team".to_string());
skill.tags = vec![
    "text".to_string(),
    "nlp".to_string(),
    "analysis".to_string(),
    "extraction".to_string(),
    "transformation".to_string(),
];
skill.capabilities = vec![
    "text_extraction".to_string(),
    "text_analysis".to_string(),
    "sentiment_analysis".to_string(),
    "keyword_extraction".to_string(),
    "text_transformation".to_string(),
];
skill.skill_file = std::path::PathBuf::from("text-processor/SKILL.md");
skill.enabled = true;
skill.timeout = Some(30);
skill.dependencies = Some(vec![
    "nltk".to_string(),
    "spacy".to_string(),
]);
2

Register the skill

use fastskill::{FastSkillService, ServiceConfig};
use std::path::PathBuf;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = ServiceConfig {
        skill_storage_path: PathBuf::from("./skills"),
        ..Default::default()
    };

    let mut service = FastSkillService::new(config).await?;
    service.initialize().await?;

    // Register the skill (using skill from previous step)
    let skill_id = service.skill_manager().register_skill(skill).await?;
    println!("✅ Skill registered with ID: {}", skill_id);

    // Verify registration
    let skills = service.skill_manager().list_skills(None).await?;
    println!("📋 Total skills: {}", skills.len());

    service.shutdown().await?;
    Ok(())
}
3

Update existing skill

use fastskill::{FastSkillService, ServiceConfig, SkillId, SkillUpdate};
use std::path::PathBuf;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = ServiceConfig {
        skill_storage_path: PathBuf::from("./skills"),
        ..Default::default()
    };

    let mut service = FastSkillService::new(config).await?;
    service.initialize().await?;

    let skill_id = SkillId::new("text-processor".to_string())?;

    // Update skill definition
    let updates = SkillUpdate {
        name: Some("Advanced Text Processing Suite".to_string()),
        description: Some("Enhanced text processing with AI-powered analysis".to_string()),
        version: Some("1.1.0".to_string()),
        tags: Some(vec![
            "text".to_string(),
            "nlp".to_string(),
            "analysis".to_string(),
            "ai".to_string(),
        ]),
        capabilities: Some(vec![
            "text_extraction".to_string(),
            "text_analysis".to_string(),
            "ai_analysis".to_string(),
        ]),
        ..Default::default()
    };

    // Update the skill
    service.skill_manager()
        .update_skill(&skill_id, updates)
        .await?;

    println!("✅ Skill updated successfully");

    service.shutdown().await?;
    Ok(())
}

REST API

# Register a skill via REST API
curl -X POST http://localhost:8080/api/skills \
  -H "Content-Type: application/json" \
  -d '{
    "id": "text-processor",
    "name": "Text Processing Suite",
    "description": "Comprehensive text processing capabilities",
    "version": "1.0.0",
    "tags": "text,nlp,analysis",
    "capabilities": "text_extraction,text_analysis",
    "enabled": true
  }'

Auto-Discovery

FastSkill can automatically discover and register skills from the filesystem:

Directory Structure

Organize your skills in a directory structure like this:
skills/
├── text-processor/
│   ├── SKILL.md            # Skill definition (Claude Code format)
│   ├── script.sh           # Implementation script (optional)
│   └── README.md           # Documentation
├── data-analyzer/
│   ├── SKILL.md
│   └── README.md
└── web-scraper/
    ├── SKILL.json
    ├── scraper.py
    └── config.yaml

Enable Auto-Discovery

1

Configure auto-discovery

// Auto-discovery happens automatically when service initializes
// Skills are discovered from the skill_storage_path directory
// The service scans for SKILL.md files during initialization

Batch Operations

Register multiple skills efficiently:

Rust Batch Registration

use fastskill::{FastSkillService, ServiceConfig, SkillDefinition, SkillId};
use std::path::PathBuf;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = ServiceConfig {
        skill_storage_path: PathBuf::from("./skills"),
        ..Default::default()
    };

    let mut service = FastSkillService::new(config).await?;
    service.initialize().await?;

    // Define multiple skills
    let skills_to_register = vec![
        SkillDefinition::new(
            SkillId::new("text-extractor".to_string())?,
            "Text Extractor".to_string(),
            "Extract text from various document formats".to_string(),
            "1.0.0".to_string(),
        ),
        SkillDefinition::new(
            SkillId::new("data-validator".to_string())?,
            "Data Validator".to_string(),
            "Validate and clean data structures".to_string(),
            "1.0.0".to_string(),
        ),
        SkillDefinition::new(
            SkillId::new("file-organizer".to_string())?,
            "File Organizer".to_string(),
            "Organize files by type and content".to_string(),
            "1.0.0".to_string(),
        ),
    ];

    // Register all skills
    let mut registered_ids = Vec::new();
    for skill in skills_to_register {
        match service.skill_manager().register_skill(skill).await {
            Ok(skill_id) => {
                registered_ids.push(skill_id.clone());
                println!("✅ Registered: {}", skill_id);
            }
            Err(e) => {
                eprintln!("❌ Failed to register skill: {}", e);
            }
        }
    }

    println!("\n🎯 Successfully registered {} skills", registered_ids.len());
    
    service.shutdown().await?;
    Ok(())
}

Batch Update

use fastskill::{FastSkillService, ServiceConfig, SkillId, SkillUpdate};
use std::path::PathBuf;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = ServiceConfig {
        skill_storage_path: PathBuf::from("./skills"),
        ..Default::default()
    };

    let mut service = FastSkillService::new(config).await?;
    service.initialize().await?;

    // Define updates for multiple skills
    let updates = vec![
        (
            SkillId::new("text-extractor".to_string())?,
            SkillUpdate {
                version: Some("1.0.1".to_string()),
                timeout: Some(60),
                ..Default::default()
            },
        ),
        (
            SkillId::new("file-organizer".to_string())?,
            SkillUpdate {
                version: Some("1.0.1".to_string()),
                timeout: Some(60),
                ..Default::default()
            },
        ),
    ];

    for (skill_id, update_data) in updates {
        match service.skill_manager().update_skill(&skill_id, update_data).await {
            Ok(_) => println!("✅ Updated {}", skill_id),
            Err(e) => eprintln!("❌ Failed to update {}: {}", skill_id, e),
        }
    }

    service.shutdown().await?;
    Ok(())
}

Validation

FastSkill validates skill definitions before registration:
1

Manual validation

use fastskill::{FastSkillService, ServiceConfig, SkillDefinition, SkillId};
use std::path::PathBuf;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = ServiceConfig {
        skill_storage_path: PathBuf::from("./skills"),
        ..Default::default()
    };

    let mut service = FastSkillService::new(config).await?;
    service.initialize().await?;

    // Create skill definition
    let skill = SkillDefinition::new(
        SkillId::new("my-skill".to_string())?,
        "My Skill".to_string(),
        "A test skill".to_string(),
        "1.0.0".to_string(),
    );

    // Validation happens automatically during registration
    // Register the skill (will validate internally)
    match service.skill_manager().register_skill(skill).await {
        Ok(skill_id) => {
            println!("✅ Skill definition is valid");
            println!("✅ Registered: {}", skill_id);
        }
        Err(e) => {
            eprintln!("❌ Validation/registration failed: {}", e);
            // Fix the issues before registering
        }
    }

    service.shutdown().await?;
    Ok(())
}
2

Batch validation

use fastskill::{FastSkillService, ServiceConfig, SkillDefinition, SkillId};
use std::path::PathBuf;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = ServiceConfig {
        skill_storage_path: PathBuf::from("./skills"),
        ..Default::default()
    };

    let mut service = FastSkillService::new(config).await?;
    service.initialize().await?;

    // Define skills to validate and register
    let skills_to_validate = vec![
        SkillDefinition::new(
            SkillId::new("skill1".to_string())?,
            "Skill 1".to_string(),
            "First skill".to_string(),
            "1.0.0".to_string(),
        ),
        SkillDefinition::new(
            SkillId::new("skill2".to_string())?,
            "Skill 2".to_string(),
            "Second skill".to_string(),
            "1.0.0".to_string(),
        ),
    ];

    let mut valid_count = 0;
    let mut invalid_count = 0;

    for skill in skills_to_validate {
        match service.skill_manager().register_skill(skill).await {
            Ok(_) => {
                valid_count += 1;
            }
            Err(_) => {
                invalid_count += 1;
            }
        }
    }

    println!("✅ Valid skills: {}", valid_count);
    println!("❌ Invalid skills: {}", invalid_count);

    service.shutdown().await?;
    Ok(())
}

CLI Registration

Use the FastSkill CLI for command-line registration:
# Register a skill from JSON file
fastskill register ./skills/text-processor/skill.json

# Register from directory (auto-discovery)
fastskill register --auto ./skills/

# Register with validation
fastskill register --validate ./skill.json

# Batch register multiple files
fastskill register ./skills/**/*.json

Best Practices

1

Use descriptive identifiers

Choose skill IDs that are descriptive and likely to be unique. Include version numbers for skill variants.
2

Provide comprehensive metadata

Include detailed descriptions, relevant tags, and specific capabilities to improve discoverability.
3

Version properly

Use semantic versioning and update versions when making breaking changes or adding new features.
4

Validate before registration

Always validate skill definitions before registering them to catch issues early.
5

Use auto-discovery for development

Enable auto-discovery during development for faster iteration, but use manual registration in production.

Troubleshooting

Duplicate ID: Each skill must have a unique ID. Check if a skill with the same ID already exists.
# Check existing skills
existing_skills = await service.list_skills()
existing_ids = [s['id'] for s in existing_skills]
Invalid format: Ensure all required fields are present and have the correct types.
# Use validation before registration
validate_skill_definition(skill_data)
File not found: If using skill_file, ensure the path exists relative to the storage directory.
Pattern matching: Auto-discovery uses glob patterns. Ensure your files match the configured patterns.
Permission denied: Check that FastSkill has read permissions for skill directories.
Debug discovery: Enable debug logging to see which files are being discovered and why others are skipped.
Batch size: For large numbers of skills, use batch operations instead of individual registrations.
Validation timing: Consider validating skills offline before registration in production environments.
Skill registration is the foundation of FastSkill’s functionality. Take time to understand the skill definition format and validation requirements to avoid common issues.