The SignalWire Agents SDK now includes a powerful, modular skills system that allows you to add capabilities to your agents with simple one-liner calls and configurable parameters.
Instead of manually implementing every agent capability, you can now:
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
The skills system consists of:
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 parametersSkillRegistry
- Auto-discovers skills from the skills/
directoryweb_search
- Google Custom Search API integration with web scrapingdatetime
- Current date/time information with timezone supportmath
- Basic mathematical calculationsweb_search
) 🔗Search the internet and extract content from web pages.
Requirements:
GOOGLE_SEARCH_API_KEY
, GOOGLE_SEARCH_ENGINE_ID
beautifulsoup4
, requests
Parameters:
num_results
(default: 1) - Number of search results to retrieve (1-10)delay
(default: 0) - Delay in seconds between web requestsTools provided:
web_search(query, num_results)
- Search and scrape web contentUsage examples:
# Default: fast single result
agent.add_skill("web_search")
# Custom: multiple results with delay
agent.add_skill("web_search", {
"num_results": 3,
"delay": 0.5
})
# Speed optimized: single result, no delay
agent.add_skill("web_search", {
"num_results": 1,
"delay": 0
})
datetime
) 🔗Get current date and time information.
Requirements:
pytz
Parameters: None (no configurable parameters)
Tools provided:
get_current_time(timezone)
- Current time in any timezoneget_current_date(timezone)
- Current date in any timezonemath
) 🔗Perform mathematical calculations.
Requirements: None
Parameters: None (no configurable parameters)
Tools provided:
calculate(expression)
- Evaluate mathematical expressions safelynative_vector_search
) 🔗Search local document collections using vector similarity and keyword search.
Requirements:
sentence-transformers
, scikit-learn
, numpy
pip install signalwire-agents[search]
Parameters:
tool_name
(default: "search_knowledge") - Custom name for the search toolindex_file
(optional) - Path to local .swsearch
index fileremote_url
(optional) - URL of remote search serverindex_name
(default: "default") - Index name on remote serverbuild_index
(default: False) - Auto-build index if missingsource_dir
(optional) - Source directory for auto-buildingcount
(default: 3) - Number of search results to returndistance_threshold
(default: 0.0) - Minimum similarity scoreresponse_prefix
(optional) - Text to prepend to responsesresponse_postfix
(optional) - Text to append to responsesTools provided:
search_knowledge(query, count)
- Search documents with hybrid vector/keyword searchUsage examples:
# Local mode with auto-build from concepts guide
agent.add_skill("native_vector_search", {
"tool_name": "search_docs",
"build_index": True,
"source_dir": "./docs", # Will build from directory
"index_file": "concepts.swsearch"
})
# Or build from specific concepts guide file
agent.add_skill("native_vector_search", {
"tool_name": "search_concepts",
"index_file": "concepts.swsearch" # Pre-built from concepts guide
})
# Remote mode
agent.add_skill("native_vector_search", {
"remote_url": "http://localhost:8001",
"index_name": "knowledge"
})
# Multiple instances for different document collections
agent.add_skill("native_vector_search", {
"tool_name": "search_examples",
"index_file": "examples.swsearch"
})
For complete documentation, see Local Search System.
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()
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()
# 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
})
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'])}")
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")
Create a new skill by extending SkillBase
with parameter support:
# signalwire_agents/skills/my_skill/skill.py
from signalwire_agents.core.skill_base import SkillBase
from signalwire_agents.core.function_result import SwaigFunctionResult
class MyCustomSkill(SkillBase):
SKILL_NAME = "my_skill"
SKILL_DESCRIPTION = "Does something awesome with configurable parameters"
SKILL_VERSION = "1.0.0"
REQUIRED_PACKAGES = ["requests"] # Optional
REQUIRED_ENV_VARS = ["API_KEY"] # Optional
def setup(self) -> bool:
"""Initialize the skill with parameters"""
if not self.validate_env_vars() or not self.validate_packages():
return False
# Use parameters with defaults
self.max_items = self.params.get('max_items', 10)
self.timeout = self.params.get('timeout', 30)
self.retry_count = self.params.get('retry_count', 3)
return True
def register_tools(self) -> None:
"""Register SWAIG tools with the agent"""
self.agent.define_tool(
name="my_function",
description=f"Does something cool (max {self.max_items} items)",
parameters={
"input": {
"type": "string",
"description": "Input parameter"
}
},
handler=self._my_handler
)
def _my_handler(self, args, raw_data):
"""Handle the tool call using configured parameters"""
# Use self.max_items, self.timeout, self.retry_count in your logic
return SwaigFunctionResult(f"Processed with max_items={self.max_items}")
def get_hints(self):
"""Speech recognition hints"""
return ["custom", "skill", "awesome"]
def get_prompt_sections(self):
"""Prompt sections to add to agent"""
return [{
"title": "Custom Capability",
"body": f"You can do custom things with my_skill (configured for {self.max_items} items)."
}]
The skill will be automatically discovered and available as:
# Use defaults
agent.add_skill("my_skill")
# Use custom parameters
agent.add_skill("my_skill", {
"max_items": 20,
"timeout": 60,
"retry_count": 5
})
Install dependencies:
bash
pip install pytz beautifulsoup4 requests
Run the demo:
bash
python examples/skills_demo.py
For web search, set environment variables:
bash
export GOOGLE_SEARCH_API_KEY="your_api_key"
export GOOGLE_SEARCH_ENGINE_ID="your_engine_id"
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!')
"
agent.add_skill("skill_name")
agent.add_skill("skill_name", {"param": "value"})
Before (manual implementation):
# Had to manually implement every capability
class WebSearchAgent(AgentBase):
def __init__(self):
super().__init__("WebSearchAgent")
self.setup_google_search()
self.define_tool("web_search", ...)
# Lots of manual code...
After (skills system with parameters):
# Simple one-liner with custom configuration
agent = AgentBase("WebSearchAgent")
agent.add_skill("web_search", {
"num_results": 3, # Get more results
"delay": 0.5 # Be respectful to servers
})
# Done! Full web search capability with custom settings.
The skills system makes SignalWire agents more modular, maintainable, configurable, and powerful than ever before!