Overview
Hot reloading allows you to update skills at runtime without restarting the FastSkill service. This feature is essential for development workflows where you need to iterate quickly on skill implementations.
Hot reloading is primarily intended for development environments. Consider disabling it in production for better performance and security.
How Hot Reloading Works
Configuration
Enable Hot Reloading
from fastskill import ServiceConfig
from pathlib import Path
config = ServiceConfig(
enable_hot_reload = True ,
watch_paths = [
Path( "./skills" ), # Main skills directory
Path( "./custom-skills" ), # Custom skills
Path( "../shared-skills" ), # Shared skills
Path( "./experimental-skills" ) # Experimental features
],
hot_reload_config = {
"debounce_seconds" : 1 , # Wait 1s after changes
"max_watch_depth" : 5 , # Max directory depth
"ignore_patterns" : [ ".git" , "__pycache__" , "*.tmp" ],
"include_patterns" : [ "*.py" , "*.json" , "*.md" , "*.yaml" ]
}
)
File Watching
Configure which files and directories to watch:
# Watch specific file types
config = ServiceConfig(
enable_hot_reload = True ,
watch_paths = [Path( "./skills" )],
watch_patterns = {
"include" : [ "*.py" , "*.json" , "*.yaml" , "*.md" ],
"exclude" : [ ".git" , "__pycache__" , "*.pyc" , ".DS_Store" ],
"recursive" : True ,
"follow_symlinks" : False
}
)
Development Workflow
1. Setup Hot Reloading
async def setup_development ():
"""Setup development environment with hot reloading."""
# Configure for development
config = ServiceConfig(
skill_storage_path = Path( "./skills" ),
enable_hot_reload = True ,
watch_paths = [Path( "./skills" )],
log_level = "DEBUG" ,
enable_audit_logging = True ,
cache = CacheConfig(
cache_ttl_seconds = 60 # Short cache for development
)
)
# Initialize service
service = FastSkillService(config)
await service.initialize()
print ( "π₯ Hot reloading enabled!" )
print ( "π Watching directories: ./skills" )
print ( "π Edit skills and see changes automatically" )
# Keep service running
try :
while True :
await asyncio.sleep( 1 )
except KeyboardInterrupt :
await service.shutdown()
print ( " \n π Development session ended" )
2. Create and Update Skills
# Example: Create a simple skill
skill_definition = {
"id" : "hello-world" ,
"name" : "Hello World" ,
"description" : "A simple hello world skill" ,
"version" : "1.0.0" ,
"tags" : "demo,hello" ,
"capabilities" : "text_generation" ,
"skill_file" : "hello_skill.py" ,
"enabled" : True
}
# Create implementation file
with open ( "skills/hello_skill.py" , "w" ) as f:
f.write( '''
async def say_hello(name: str = "World") -> dict:
"""Say hello to someone."""
return {
"success": True,
"message": f"Hello, {name} !",
"timestamp": "2024-01-15T10:30:00Z"
}
''' )
# Register skill
await service.register_skill(skill_definition)
# Test the skill
result = await service.tool_service.execute_tool(
"hello-world" ,
"say_hello" ,
{ "name" : "Developer" }
)
print ( f "Result: { result } " )
3. Live Updates
# Edit the skill file and see changes immediately
# skills/hello_skill.py - updated version
with open ( "skills/hello_skill.py" , "w" ) as f:
f.write( '''
async def say_hello(name: str = "World") -> dict:
"""Say hello with enthusiasm!"""
return {
"success": True,
"message": f"Hello, {name} ! π",
"timestamp": "2024-01-15T10:30:00Z",
"enhanced": True # New feature!
}
async def say_goodbye(name: str = "World") -> dict:
"""Say goodbye to someone."""
return {
"success": True,
"message": f"Goodbye, {name} ! π",
"timestamp": "2024-01-15T10:30:00Z"
}
''' )
# The skill is automatically reloaded!
# New tools and updated functionality are available immediately
result1 = await service.tool_service.execute_tool(
"hello-world" ,
"say_hello" ,
{ "name" : "Developer" }
)
result2 = await service.tool_service.execute_tool(
"hello-world" ,
"say_goodbye" , # New tool!
{ "name" : "Developer" }
)
Event Handling
Subscribe to hot reload events:
async def handle_reload_events ():
"""Handle hot reload events."""
def on_skill_reloaded ( event ):
print ( f "π Skill reloaded: { event[ 'skill_id' ] } " )
print ( f " Version: { event[ 'new_version' ] } " )
print ( f " Changes: { event[ 'changes' ] } " )
def on_reload_error ( event ):
print ( f "β Reload error: { event[ 'skill_id' ] } " )
print ( f " Error: { event[ 'error' ] } " )
print ( f " File: { event[ 'file_path' ] } " )
def on_validation_error ( event ):
print ( f "β οΈ Validation error: { event[ 'skill_id' ] } " )
for error in event[ 'validation_errors' ]:
print ( f " { error[ 'field' ] } : { error[ 'message' ] } " )
# Subscribe to events
service.subscribe( "skill.reloaded" , on_skill_reloaded)
service.subscribe( "skill.reload_error" , on_reload_error)
service.subscribe( "skill.validation_error" , on_validation_error)
# Events are triggered automatically when files change
Monitoring Hot Reloading
async def monitor_hot_reload ():
"""Monitor hot reload performance."""
metrics = await service.get_hot_reload_metrics()
print ( "π Hot Reload Metrics:" )
print ( f " Files watched: { metrics[ 'files_watched' ] } " )
print ( f " Reloads performed: { metrics[ 'reloads_performed' ] } " )
print ( f " Average reload time: { metrics[ 'avg_reload_time_ms' ] :.2f} ms" )
print ( f " Errors: { metrics[ 'reload_errors' ] } " )
print ( f " Cache hit rate: { metrics[ 'cache_hit_rate' ] :.1%} " )
# Recent reloads
recent = metrics[ 'recent_reloads' ]
print ( f " \n β° Recent reloads:" )
for reload_event in recent[ - 5 :]: # Last 5 reloads
print ( f " { reload_event[ 'timestamp' ] } : { reload_event[ 'skill_id' ] } ( { reload_event[ 'duration_ms' ] } ms)" )
Debug Mode
Enable debug mode for detailed hot reload information:
# Enable debug logging for hot reload
export FASTSKILL_LOG_LEVEL = DEBUG
fastskill serve --hot-reload --debug
# Monitor file changes in real-time
fastskill serve --hot-reload --watch-verbose
Production Considerations
Disable in Production
# Production configuration - hot reload disabled
config = ServiceConfig(
enable_hot_reload = False , # Disable for security and performance
log_level = "INFO" , # Reduce verbosity
enable_audit_logging = True # Keep audit trail
)
Conditional Reloading
Enable hot reloading only for specific skills or environments:
config = ServiceConfig(
enable_hot_reload = True ,
hot_reload_config = {
"allowed_skills" : [ "dev-*" , "test-*" ], # Only reload dev/test skills
"require_auth" : True , # Require authentication
"max_reload_rate" : 10 , # Max reloads per minute
"enable_validation" : True # Validate before reload
}
)
File Change Detection
Supported File Types
Hot reloading monitors these file types by default:
Extension Purpose Reload Trigger .pyPython implementation Function signature or behavior changes .jsonSkill definitions Metadata or configuration changes .yamlConfiguration files Settings or parameter changes .mdDocumentation Help text or description updates
Change Detection Rules
# Configure change detection
config = ServiceConfig(
enable_hot_reload = True ,
hot_reload_config = {
"change_detection" : {
"function_signature_only" : False , # Reload on any code change
"ignore_comments" : True , # Don't reload for comment changes
"ignore_whitespace" : True , # Don't reload for formatting changes
"require_restart" : [ "dependencies" , "execution_timeout" ] # Require restart for these
}
}
)
IDE Integration
# VS Code extension integration
class FastSkillExtension :
"""VS Code extension for FastSkill development."""
def on_file_saved ( self , file_path : str ):
"""Called when a skill file is saved."""
if self .is_skill_file(file_path):
# Trigger validation
validation_result = self .validate_skill_file(file_path)
if validation_result[ "valid" ]:
# Show success notification
self .show_notification( "β
Skill updated successfully" )
else :
# Show validation errors
self .show_errors(validation_result[ "errors" ])
def on_hot_reload_event ( self , event : dict ):
"""Handle hot reload events."""
if event[ "type" ] == "skill_reloaded" :
self .update_problems_view(event[ "skill_id" ], [])
self .refresh_skill_tree()
elif event[ "type" ] == "reload_error" :
self .update_problems_view(event[ "skill_id" ], [event[ "error" ]])
Live Testing
# Integration with pytest-watch
async def live_testing_integration ():
"""Integrate hot reloading with live testing."""
import subprocess
import time
def run_tests ():
"""Run tests when skills change."""
result = subprocess.run(
[ "pytest" , "tests/" , "-v" , "--tb=short" ],
capture_output = True ,
text = True
)
if result.returncode == 0 :
print ( "β
All tests passed" )
else :
print ( "β Tests failed:" )
print (result.stdout)
print (result.stderr)
def on_skill_changed ( event ):
"""Run tests when skills change."""
print ( f "π Skill changed: { event[ 'skill_id' ] } " )
print ( "π§ͺ Running tests..." )
# Debounce test runs
time.sleep( 2 ) # Wait for any additional changes
run_tests()
# Subscribe to skill changes
service.subscribe( "skill.reloaded" , on_skill_changed)
service.subscribe( "skill.registered" , on_skill_changed)
Troubleshooting
Check configuration : Ensure hot reload is enabled and watch paths are correct.# Verify configuration
config = service.get_config()
print ( f "Hot reload enabled: { config.enable_hot_reload } " )
print ( f "Watch paths: { config.watch_paths } " )
File permissions : Ensure FastSkill has read permissions for watched directories.# Fix permissions
chmod 755 ./skills/
chmod 644 ./skills/ * .py
Optimize watch paths : Limit the number of directories and files being watched.config = ServiceConfig(
watch_paths = [Path( "./skills" )], # Single directory
hot_reload_config = {
"include_patterns" : [ "*.py" , "*.json" ] # Only essential files
}
)
Increase debounce time : Add delay to batch multiple file changes.config = ServiceConfig(
hot_reload_config = { "debounce_seconds" : 2 }
)
Validation Errors on Reload
Check file syntax : Ensure updated files have valid syntax before saving.# Validate Python files
python -m py_compile skills/skill.py
# Validate JSON files
python -c "import json; json.load(open('skill.json'))"
Review error logs : Check service logs for detailed validation error information.fastskill logs --level DEBUG --follow
Best Practices
Use development-only skills
Create separate skills for development with βdev-β prefix to avoid affecting production.
Test thoroughly
Run comprehensive tests after hot reload to ensure functionality still works.
Monitor performance
Keep an eye on reload times and memory usage during development.
Version control integration
Ensure hot reload changes are properly tracked in version control.
Disable in production
Always disable hot reload in production environments for security and performance.
Hot reloading dramatically improves development experience by eliminating the need to restart services. Use it during development but disable it in production environments.