Skills
The Agents SDK includes a powerful, modular skills system that allows you to add capabilities to your agents with simple one-liner calls and configurable parameters.
The skills system provides one-liner integration with agent.add_skill("skill_name")
and configurable parameters via agent.add_skill("skill_name", {"param": "value"})
.
Skills are automatically discovered when dropped in the directory, with built-in dependency validation for packages and environment variables. The modular architecture ensures skills are self-contained and reusable, while the extensible design makes it easy to create custom skills with parameters. You can also tune performance by configuring skills for speed versus comprehensiveness.
Skills System
The Skills System allows you to extend your agents with powerful capabilities using simple one-liner calls. Skills are modular, reusable components that can be easily added to any agent and configured with parameters.
Quick Start
from signalwire_agents import AgentBase
class SkillfulAgent(AgentBase):
def __init__(self):
super().__init__(name="skillful-agent", route="/skillful")
# Add skills with one-liners
self.add_skill("web_search") # Web search capability
self.add_skill("datetime") # Current date/time info
self.add_skill("math") # Mathematical calculations
# Configure skills with parameters
self.add_skill("web_search", {
"num_results": 3, # Get 3 search results instead of default 1
"delay": 0.5 # Add delay between requests
})
Available Built-in Skills
Web Search Skill (web_search
)
Provides web search capabilities using Google Custom Search API with web scraping.
Requirements:
- Packages:
beautifulsoup4
,requests
Parameters:
api_key
(required): Google Custom Search API keysearch_engine_id
(required): Google Custom Search Engine IDnum_results
(default: 1): Number of search results to returndelay
(default: 0): Delay in seconds between requeststool_name
(default: "web_search"): Custom name for the search toolno_results_message
(default: "I couldn't find any results for '{query}'. This might be due to a very specific query or temporary issues. Try rephrasing your search or asking about a different topic."): Custom message to return when no search results are found. Use\{query}
as a placeholder for the search query.
Multiple Instance Support: The web_search skill supports multiple instances with different search engines and tool names, allowing you to search different data sources:
Example:
# Basic single instance
agent.add_skill("web_search", {
"api_key": "your-google-api-key",
"search_engine_id": "your-search-engine-id"
})
# Creates tool: web_search
# Fast single result (previous default)
agent.add_skill("web_search", {
"api_key": "your-google-api-key",
"search_engine_id": "your-search-engine-id",
"num_results": 1,
"delay": 0
})
# Multiple results with delay
agent.add_skill("web_search", {
"api_key": "your-google-api-key",
"search_engine_id": "your-search-engine-id",
"num_results": 5,
"delay": 1.0
})
# Multiple instances with different search engines
agent.add_skill("web_search", {
"api_key": "your-google-api-key",
"search_engine_id": "general-search-engine-id",
"tool_name": "search_general",
"num_results": 1
})
# Creates tool: search_general
agent.add_skill("web_search", {
"api_key": "your-google-api-key",
"search_engine_id": "news-search-engine-id",
"tool_name": "search_news",
"num_results": 3,
"delay": 0.5
})
# Creates tool: search_news
# Custom no results message
agent.add_skill("web_search", {
"api_key": "your-google-api-key",
"search_engine_id": "your-search-engine-id",
"no_results_message": "Sorry, I couldn't find information about '\{query}'. Please try a different search term."
})
DateTime Skill (datetime
)
Provides current date and time information with timezone support.
Requirements:
- Packages:
pytz
Tools Added:
get_current_time
: Get current time with optional timezoneget_current_date
: Get current date with optional timezone
Example:
agent.add_skill("datetime")
# Agent can now tell users the current time and date
Math Skill (math
)
Provides safe mathematical expression evaluation.
Requirements:
- None (uses built-in Python functionality)
Tools Added:
calculate
: Evaluate mathematical expressions safely
Example:
agent.add_skill("math")
# Agent can now perform calculations like "2 + 3 * 4"
DataSphere Skill (datasphere
)
Provides knowledge search capabilities using SignalWire DataSphere RAG stack.
Requirements:
- Packages:
requests
Parameters:
space_name
(required): SignalWire space nameproject_id
(required): SignalWire project IDtoken
(required): SignalWire authentication tokendocument_id
(required): DataSphere document ID to searchcount
(default: 1): Number of search results to returndistance
(default: 3.0): Distance threshold for search matchingtags
(optional): List of tags to filter search resultslanguage
(optional): Language code to limit searchpos_to_expand
(optional): List of parts of speech for synonym expansion (e.g., ["NOUN", "VERB"])max_synonyms
(optional): Maximum number of synonyms to use for each wordtool_name
(default: "search_knowledge"): Custom name for the search toolno_results_message
(default: "I couldn't find any relevant information for '{query}' in the knowledge base. Try rephrasing your question or asking about a different topic."): Custom message when no results found
Multiple Instance Support: The DataSphere skill supports multiple instances with different tool names, allowing you to search multiple knowledge bases:
Example:
# Basic single instance
agent.add_skill("datasphere", {
"space_name": "my-space",
"project_id": "my-project",
"token": "my-token",
"document_id": "general-knowledge"
})
# Creates tool: search_knowledge
# Multiple instances for different knowledge bases
agent.add_skill("datasphere", {
"space_name": "my-space",
"project_id": "my-project",
"token": "my-token",
"document_id": "product-docs",
"tool_name": "search_products",
"tags": ["Products", "Features"],
"count": 3
})
# Creates tool: search_products
agent.add_skill("datasphere", {
"space_name": "my-space",
"project_id": "my-project",
"token": "my-token",
"document_id": "support-kb",
"tool_name": "search_support",
"no_results_message": "I couldn't find support information about '\{query}'. Try contacting our support team.",
"distance": 5.0
})
# Creates tool: search_support
Native Vector Search Skill (native_vector_search
)
Provides local document search capabilities using vector similarity and keyword search. This skill works entirely offline with local .swsearch
index files or can connect to remote search servers.
Requirements:
- Packages:
sentence-transformers
,scikit-learn
,numpy
(install withpip install signalwire-agents[search]
)
Parameters:
tool_name
(default: "search_knowledge"): Custom name for the search tooldescription
(default: "Search the local knowledge base for information"): Tool descriptionindex_file
(optional): Path to local.swsearch
index fileremote_url
(optional): URL of remote search server (e.g.,http://localhost:8001
)index_name
(default: "default"): Index name on remote server (for remote mode)build_index
(default: False): Auto-build index if missingsource_dir
(optional): Source directory for auto-building indexfile_types
(default: ["md", "txt"]): File types to include when building indexcount
(default: 3): Number of search results to returndistance_threshold
(default: 0.0): Minimum similarity score for resultstags
(optional): List of tags to filter search resultsresponse_prefix
(optional): Text to prepend to all search responsesresponse_postfix
(optional): Text to append to all search responsesno_results_message
(default: "No information found for '{query}'"): Custom message when no results found
Multiple Instance Support: The native vector search skill supports multiple instances with different indexes and tool names:
Example:
# Local mode with auto-build
agent.add_skill("native_vector_search", {
"tool_name": "search_docs",
"description": "Search SDK concepts guide",
"build_index": True,
"source_dir": "./docs",
"index_file": "concepts.swsearch",
"count": 5
})
# Creates tool: search_docs
# Remote mode connecting to search server
agent.add_skill("native_vector_search", {
"tool_name": "search_knowledge",
"description": "Search the knowledge base",
"remote_url": "http://localhost:8001",
"index_name": "concepts",
"count": 3
})
# Creates tool: search_knowledge
# Multiple local indexes
agent.add_skill("native_vector_search", {
"tool_name": "search_examples",
"description": "Search code examples",
"index_file": "examples.swsearch",
"response_prefix": "From the examples:"
})
# Creates tool: search_examples
# Voice-optimized responses using concepts guide
agent.add_skill("native_vector_search", {
"tool_name": "search_docs",
"index_file": "concepts.swsearch",
"response_prefix": "Based on the comprehensive SDK guide:",
"response_postfix": "Would you like more specific information?",
"no_results_message": "I couldn't find information about '\{query}' in the concepts guide."
})
Building Search Indexes: Before using local mode, you need to build search indexes:
# Build index from documentation
python -m signalwire_agents.cli.build_search docs --output docs.swsearch
# Build with custom settings
python -m signalwire_agents.cli.build_search ./knowledge \
--output knowledge.swsearch \
--file-types md,txt,pdf \
--chunk-size 500 \
--verbose
For complete documentation on the search system, see Local Search System.
Skill Management
# Check what skills are loaded
loaded_skills = agent.list_skills()
print(f"Loaded skills: {', '.join(loaded_skills)}")
# Check if a specific skill is loaded
if agent.has_skill("web_search"):
print("Web search is available")
# Remove a skill (if needed)
agent.remove_skill("math")
Advanced Skill Configuration with swaig_fields
Skills support a special swaig_fields
parameter that allows you to customize how SWAIG functions are registered. This parameter gets merged into the function decorator object, enabling the skill loader to add additional configuration to the tools.
# Add a skill with swaig_fields to customize SWAIG function properties
agent.add_skill("math", {
"precision": 2, # Regular skill parameter
"swaig_fields": { # Special fields merged into SWAIG function
"secure": False, # Override default security requirement
"fillers": {
"en-US": ["Let me calculate that...", "Computing the result..."],
"es-ES": ["Déjame calcular eso...", "Calculando el resultado..."]
}
}
})
# Add web search with custom security and fillers
agent.add_skill("web_search", {
"num_results": 3,
"delay": 0.5,
"swaig_fields": {
"secure": True, # Require authentication
"fillers": {
"en-US": ["Searching the web...", "Looking that up...", "Finding information..."]
}
}
})
The swaig_fields
can include any parameter accepted by AgentBase.define_tool()
:
secure
: Boolean indicating if the function requires authenticationfillers
: Dictionary mapping language codes to arrays of filler phrases- Any other fields supported by the SWAIG function system
This feature enables advanced customization of how skills integrate with the agent's SWAIG system.
Error Handling
The skills system provides detailed error messages for common issues:
try:
agent.add_skill("web_search")
except ValueError as e:
print(f"Failed to load skill: {e}")
# Output: "Failed to load skill 'web_search': Missing required environment variables: ['GOOGLE_SEARCH_API_KEY']"
Creating Custom Skills
You can create your own skills by extending the SkillBase
class:
from signalwire_agents.core.skill_base import SkillBase
from signalwire_agents.core.function_result import SwaigFunctionResult
class WeatherSkill(SkillBase):
"""A custom skill for weather information"""
SKILL_NAME = "weather"
SKILL_DESCRIPTION = "Get weather information for locations"
SKILL_VERSION = "1.0.0"
REQUIRED_PACKAGES = ["requests"]
REQUIRED_ENV_VARS = ["WEATHER_API_KEY"]
def setup(self) -> bool:
"""Setup the skill - validate dependencies and initialize"""
if not self.validate_env_vars() or not self.validate_packages():
return False
# Get configuration parameters
self.default_units = self.params.get('units', 'fahrenheit')
self.timeout = self.params.get('timeout', 10)
return True
def register_tools(self) -> None:
"""Register tools with the agent"""
self.define_tool_with_swaig_fields(
name="get_weather",
description="Get current weather for a location",
parameters={
"location": {
"type": "string",
"description": "City or location name"
},
"units": {
"type": "string",
"description": "Temperature units (fahrenheit or celsius)",
"enum": ["fahrenheit", "celsius"]
}
},
handler=self._get_weather_handler
)
def _get_weather_handler(self, args, raw_data):
"""Handle weather requests"""
location = args.get("location", "")
units = args.get("units", self.default_units)
if not location:
return SwaigFunctionResult("Please provide a location")
# Your weather API integration here
weather_data = f"Weather for {location}: 72°F and sunny"
return SwaigFunctionResult(weather_data)
def get_hints(self) -> List[str]:
"""Return speech recognition hints"""
return ["weather", "temperature", "forecast", "conditions"]
def get_prompt_sections(self) -> List[Dict[str, Any]]:
"""Return prompt sections to add to agent"""
return [
{
"title": "Weather Information",
"body": "You can provide current weather information for any location.",
"bullets": [
"Use get_weather tool when users ask about weather",
"Always specify the location clearly",
"Include temperature and conditions in your response"
]
}
]
Using the custom skill:
# Place the skill in signalwire_agents/skills/weather/skill.py
# Then use it in your agent:
agent.add_skill("weather", {
"units": "celsius",
"timeout": 15
})
Skills with Dynamic Configuration
Skills work seamlessly with dynamic configuration:
class DynamicSkillAgent(AgentBase):
def __init__(self):
super().__init__(name="dynamic-skill-agent")
self.set_dynamic_config_callback(self.configure_per_request)
def configure_per_request(self, query_params, body_params, headers, agent):
# Add different skills based on request parameters
tier = query_params.get('tier', 'basic')
# Basic skills for all users
agent.add_skill("datetime")
agent.add_skill("math")
# Premium skills for premium users
if tier == 'premium':
agent.add_skill("web_search", {
"num_results": 5,
"delay": 0.5
})
elif tier == 'basic':
agent.add_skill("web_search", {
"num_results": 1,
"delay": 0
})
Best Practices
-
Choose appropriate parameters: Configure skills for your use case
# For speed (customer service)
agent.add_skill("web_search", {"num_results": 1, "delay": 0})
# For research (detailed analysis)
agent.add_skill("web_search", {"num_results": 5, "delay": 1.0}) -
Handle missing dependencies gracefully:
try:
agent.add_skill("web_search")
except ValueError as e:
self.logger.warning(f"Web search unavailable: {e}")
# Continue without web search capability -
Document your custom skills: Include clear descriptions and parameter documentation
-
Test skills in isolation: Create simple test scripts to verify skill functionality
For more detailed information about the skills system architecture and advanced customization, see the Skills System Overview.
Quickstart
Integrate skills to your agent in a single line!
from signalwire_agents import AgentBase
# Create an agent
agent = AgentBase("My Assistant")
# Add skills with one-liners:
agent.add_skill("web_search") # Web search capability with default settings
agent.add_skill("datetime") # Current date/time info
agent.add_skill("math") # Mathematical calculations
# Add skills with custom parameters:
agent.add_skill("web_search", {
"num_results": 3, # Get 3 search results instead of default 1
"delay": 0.5 # Add 0.5s delay between requests instead of default 0
})
# Your agent now has all these capabilities automatically
Architecture
The skills system consists of:
Core Infrastructure
SkillBase
- Abstract base class for all skills with parameter supportSkillManager
- Handles loading/unloading and lifecycle management with parametersAgentBase.add_skill()
- Simple method to add skills to agents with optional parameters
Discovery & Registry
SkillRegistry
- Auto-discovers skills from theskills/
directory- Auto-discovery - Skills are found automatically on import
- Validation - Checks dependencies and environment variables
Built-in Skills
web_search
- Google Custom Search API integration with web scrapingdatetime
- Current date/time information with timezone supportmath
- Basic mathematical calculations
Examples
Basic usage
from signalwire_agents import AgentBase
# Create agent and add skills
agent = AgentBase("Assistant", route="/assistant")
agent.add_skill("datetime")
agent.add_skill("math")
agent.add_skill("web_search") # Uses defaults: 1 result, no delay
# Start the agent
agent.run()
Skills with custom parameters
from signalwire_agents import AgentBase
# Create agent
agent = AgentBase("Research Assistant", route="/research")
# Add web search optimized for research (more results)
agent.add_skill("web_search", {
"num_results": 5, # Get more comprehensive results
"delay": 1.0 # Be respectful to websites
})
# Add other skills without parameters
agent.add_skill("datetime")
agent.add_skill("math")
# Start the agent
agent.run()
Different parameter configurations
# Speed-optimized for quick responses
agent.add_skill("web_search", {
"num_results": 1,
"delay": 0
})
# Comprehensive research mode
agent.add_skill("web_search", {
"num_results": 5,
"delay": 1.0
})
# Balanced approach
agent.add_skill("web_search", {
"num_results": 3,
"delay": 0.5
})
Check available skills
from signalwire_agents.skills.registry import skill_registry
# List all discovered skills
for skill in skill_registry.list_skills():
print(f"- {skill['name']}: {skill['description']}")
if skill['required_env_vars']:
print(f" Requires: {', '.join(skill['required_env_vars'])}")
Runtime skill management
agent = AgentBase("Dynamic Agent")
# Add skills with different configurations
agent.add_skill("math")
agent.add_skill("datetime")
agent.add_skill("web_search", {"num_results": 2, "delay": 0.3})
# Check what's loaded
print("Loaded skills:", agent.list_skills())
# Remove a skill
agent.remove_skill("math")
# Check if specific skill is loaded
if agent.has_skill("datetime"):
print("Date/time capabilities available")
Quickstart
-
Install dependencies:
pip install pytz beautifulsoup4 requests
-
Run the demo:
python examples/skills_demo.py
-
For web search, set environment variables:
export GOOGLE_SEARCH_API_KEY="your_api_key"
export GOOGLE_SEARCH_ENGINE_ID="your_engine_id"
Testing
Test the skills system with parameters:
python3 -c "
from signalwire_agents import AgentBase
from signalwire_agents.skills.registry import skill_registry
# Show discovered skills
print('Available skills:', [s['name'] for s in skill_registry.list_skills()])
# Create agent and load skills with parameters
agent = AgentBase('Test', route='/test')
agent.add_skill('datetime')
agent.add_skill('math')
agent.add_skill('web_search', {'num_results': 2, 'delay': 0.5})
print('Loaded skills:', agent.list_skills())
print('Skills system with parameters working!')
"