Appearance
Builtin Skills
FreshBuilt-in Skills
For AI agents: a documentation index is available at the root level at /llms.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Available Skills
| Skill | Description | Requirements |
|---|---|---|
datetime | Date/time information | pytz |
math | Mathematical calculations | (none) |
web_search | Web search via Google API | API key |
wikipedia_search | Wikipedia lookups | (none) |
weather_api | Weather information | API key |
joke | Tell jokes | (none) |
play_background_file | Play audio files | (none) |
swml_transfer | Transfer to SWML endpoint | (none) |
datasphere | DataSphere document search | API credentials |
native_vector_search | Local vector search | search extras |
mcp_gateway | MCP server integration | MCP Gateway service |
google_maps | Address validation & routing | Google Maps API key |
info_gatherer | Structured question collection | (none) |
claude_skills | Load SKILL.md files as tools | PyYAML |
api_ninjas_trivia | Trivia questions from API Ninjas | API key |
ask_claude | Anthropic Claude reasoning / sub-queries | ANTHROPIC_API_KEY |
custom_skills | Register one-off SWAIG tools from config | (none) |
datasphere_serverless | DataSphere search via DataMap (no server callback) | API credentials |
spider | Web scraping & crawling | cheerio (TS) / lxml (Python) |
datetime
Get current date and time information with timezone support. This is one of the most commonly used skills, callers often ask “what time is it?” or need scheduling help.
Functions:
get_current_time- Get current time in a timezoneget_current_date- Get today’s date
Requirements:pytz package (usually installed automatically)
Parameters:
This skill takes no configuration parameters. Timezone is specified per call via the timezone argument on get_current_time; UTC is the default when omitted.
Output format:
- Time: “The current time in America/New_York is 2:30 PM”
- Date: “Today’s date is November 25, 2024”
Common use cases:
- “What time is it?” / “What time is it in Tokyo?”
- “What’s today’s date?”
- Scheduling and appointment contexts
- Time zone conversions
Limitations:
- Requires valid timezone names (e.g., “America/New_York”, not “EST”)
- Doesn’t do time math or calculate durations
- Doesn’t handle historical dates
| Language | Adding datetime |
|---|---|
| Python | self.add_skill("datetime") |
| TypeScript | await agent.addSkillByName('datetime') |
from signalwire import AgentBase
class TimeAgent(AgentBase):
def __init__(self):
super().__init__(name="time-agent")
self.add_language("English", "en-US", "rime.spore")
self.add_skill("datetime")
self.prompt_add_section(
"Role",
"You help users with date and time information."
)math
Perform mathematical calculations safely. The skill uses a secure expression evaluator that supports common operations without executing arbitrary code.
Functions:
calculate- Evaluate mathematical expressions
Requirements: None
Parameters:
This skill takes no configuration parameters. The registered tool is always named calculate.
Supported operations:
- Basic:
+,-,*,/,**(power),%(modulo) - Functions:
sqrt,sin,cos,tan,log,abs,round - Constants:
pi,e - Parentheses for grouping
Common use cases:
- “What’s 15 percent of 230?”
- “Calculate 45 times 67”
- “What’s the square root of 256?”
- Price calculations, tip calculations
Limitations:
- Limited to supported functions (no arbitrary Python)
- Large numbers may lose precision
- Can’t solve equations or do symbolic math
from signalwire import AgentBase
class CalculatorAgent(AgentBase):
def __init__(self):
super().__init__(name="calculator")
self.add_language("English", "en-US", "rime.spore")
self.add_skill("math")
self.prompt_add_section(
"Role",
"You are a calculator that helps with math."
)web_search
Search the web using Google Custom Search API. Results are filtered for quality and summarized for voice delivery.
Functions:
web_search- Search the web and return summarized results
Requirements:
- Google Custom Search API key (from Google Cloud Console)
- Search Engine ID (from Programmable Search Engine)
Setup:
- Create a project in Google Cloud Console
- Enable the Custom Search JSON API
- Create an API key
- Create a Programmable Search Engine at https://programmablesearchengine.google.com/
- Get the Search Engine ID
Parameters:
| Parameter | Type | Description | Default |
|---|---|---|---|
api_key | string | Google API key (falls back to GOOGLE_SEARCH_API_KEY) | Required |
search_engine_id | string | Search engine ID (falls back to GOOGLE_SEARCH_ENGINE_ID) | Required |
tool_name | string | Custom function name (set per instance) | “web_search” |
num_results | integer | Results to return | 3 |
delay | number | Seconds between requests | 0.5 |
max_content_length | integer | Max characters of scraped page content | 32768 |
oversample_factor | number | Fetch extra results then re-rank | 2.5 |
min_quality_score | number | Quality threshold (0-1) | 0.3 |
no_results_message | string | Message returned when nothing matches | default |
safe_search | string | "off", "medium", or "high" | ”medium” |
Multi-instance support: Yes - add multiple instances with unique tool_name values (e.g. search_news, search_docs).
from signalwire import AgentBase
class SearchAgent(AgentBase):
def __init__(self):
super().__init__(name="search-agent")
self.add_language("English", "en-US", "rime.spore")
self.add_skill("web_search", {
"api_key": "YOUR_GOOGLE_API_KEY",
"search_engine_id": "YOUR_SEARCH_ENGINE_ID",
"num_results": 3
})
self.prompt_add_section(
"Role",
"You search the web to answer questions."
)wikipedia_search
Search Wikipedia for information. A free, no-API-key alternative to web search for factual queries.
Functions:
search_wikipedia- Search and retrieve Wikipedia article summaries
Requirements: None (uses public Wikipedia API)
Parameters:
| Parameter | Type | Description | Default |
|---|---|---|---|
num_results | integer | Max articles returned (1-5) | 1 |
no_results_message | string | Message returned when nothing matches | default template |
from signalwire import AgentBase
class WikiAgent(AgentBase):
def __init__(self):
super().__init__(name="wiki-agent")
self.add_language("English", "en-US", "rime.spore")
self.add_skill("wikipedia_search", {
"num_results": 3 # Return up to three articles
})
self.prompt_add_section(
"Role",
"You look up information on Wikipedia to answer factual questions."
)weather_api
Get current weather information for locations worldwide. Commonly used for small talk, travel planning, and location-aware services.
Functions:
get_weather- Get current weather conditions for a location
Requirements: WeatherAPI.com API key (free tier available)
Setup:
- Sign up at https://www.weatherapi.com/
- Get your API key from the dashboard
- Free tier allows 1 million calls/month
Parameters:
| Parameter | Type | Description | Default |
|---|---|---|---|
api_key | string | WeatherAPI.com API key (falls back to WEATHER_API_KEY) | Required |
tool_name | string | Custom function name | ”get_weather” |
units | string | "metric", "imperial", "standard", "celsius", or "fahrenheit" | ”fahrenheit” |
from signalwire import AgentBase
class WeatherAgent(AgentBase):
def __init__(self):
super().__init__(name="weather-agent")
self.add_language("English", "en-US", "rime.spore")
self.add_skill("weather_api", {
"api_key": "YOUR_WEATHER_API_KEY"
})
self.prompt_add_section(
"Role",
"You provide weather information for any location."
)joke
Tell jokes to lighten the mood or entertain callers. Uses a curated joke database for clean, family-friendly humor.
Functions:
tell_joke- Get a random joke
Requirements: None
Parameters:
| Parameter | Type | Description | Default |
|---|---|---|---|
tool_name | string | Custom function name | ”tell_joke” |
from signalwire import AgentBase
class FunAgent(AgentBase):
def __init__(self):
super().__init__(name="fun-agent")
self.add_language("English", "en-US", "rime.spore")
self.add_skill("joke")
self.prompt_add_section(
"Role",
"You are a fun assistant that tells jokes when asked."
)play_background_file
Play audio files in the background during calls. Audio plays while conversation continues, useful for hold music, ambient sound, or audio cues.
Functions:
play_background_file- Start playing audio filestop_background_file- Stop currently playing audio
Requirements: None (audio file must be accessible via URL)
Parameters:
This skill supports two configuration styles:
- Catalog mode, preload named files via
files, caller selects bykey:
| Parameter | Type | Description | Default |
|---|---|---|---|
tool_name | string | Custom play function name | ”play_background_file” |
files | array | List of { key, description, url, wait? } entries | Required |
- Free-form mode, caller supplies a URL at call time (gated by
allowed_domains):
| Parameter | Type | Description | Default |
|---|---|---|---|
default_file_url | string | URL played when no argument is provided | Required |
allowed_domains | array | Whitelisted domains for caller-supplied URLs | Required |
Supported formats: MP3, WAV, OGG
from signalwire import AgentBase
class MusicAgent(AgentBase):
def __init__(self):
super().__init__(name="music-agent")
self.add_language("English", "en-US", "rime.spore")
self.add_skill("play_background_file", {
"files": [\
{\
"key": "hold_music",\
"description": "Looping hold music",\
"url": "https://example.com/hold-music.mp3",\
}\
]
})swml_transfer
Transfer calls to another SWML endpoint.
Functions:
transfer_call(default name) - Transfer based on matched pattern
Requirements: None
Parameters:
| Parameter | Type | Description | Default |
|---|---|---|---|
transfers | object | Pattern → `{ url | address, message?, return_message?, post_process?, final?, from_addr? }` |
patterns | array | Alternative shape: list of pattern entries | Required (or use transfers) |
allow_arbitrary | boolean | Accept caller-supplied URL instead of matching a pattern | false |
tool_name | string | Custom function name | ”transfer_call” |
description | string | Tool description | default |
parameter_name | string | Argument name the LLM supplies | ”transfer_type” |
parameter_description | string | Argument description | default |
default_message | string | Message when no pattern matches | default |
default_post_process | boolean | Default for transferred calls returning to the agent | false |
required_fields | object | Extra per-pattern required fields | {} |
from signalwire import AgentBase
class TransferAgent(AgentBase):
def __init__(self):
super().__init__(name="transfer-agent")
self.add_language("English", "en-US", "rime.spore")
self.add_skill("swml_transfer", {
"transfers": {
"specialist": {
"url": "https://your-server.com/other-agent",
"message": "Transferring you to a specialist."
}
}
})datasphere
Search SignalWire DataSphere documents.
Functions:
search_knowledge(default name) - Search uploaded documents
Requirements: DataSphere API credentials
Parameters:
| Parameter | Type | Description | Default |
|---|---|---|---|
space_name | string | DataSphere space name | Required |
project_id | string | Project ID (falls back to SIGNALWIRE_PROJECT_ID) | Required |
token | string | API token (falls back to SIGNALWIRE_TOKEN) | Required |
document_id | string | Document ID to search within | Required |
tool_name | string | Custom function name | ”search_knowledge” |
count | integer | Results to return (1-10) | 1 |
distance | number | Distance threshold (0-10) | 3.0 |
tags | array | Filter by document tags | , |
language | string | Language filter | , |
pos_to_expand | array | POS tags to expand (NOUN, VERB, ADJ, ADV) | , |
max_synonyms | integer | Synonym expansion limit (1-10) | , |
no_results_message | string | Message when nothing matches | default |
from signalwire import AgentBase
class KnowledgeAgent(AgentBase):
def __init__(self):
super().__init__(name="knowledge-agent")
self.add_language("English", "en-US", "rime.spore")
self.add_skill("datasphere", {
"space_name": "your-space",
"project_id": "YOUR_PROJECT_ID",
"token": "YOUR_API_TOKEN",
"document_id": "your-document-id"
})native_vector_search
Local vector search using .swsearch index files.
Functions:
- Dynamic name (default
search_knowledge) - Search a local vector index
Requirements: Search extras installed (pip install "signalwire-sdk[search]")
Parameters:
| Parameter | Type | Description | Default |
|---|---|---|---|
tool_name | string | Custom function name | ”search_knowledge” |
index_file | string | SQLite .swsearch path (SQLite backend) | , |
backend | string | "sqlite" or "pgvector" | ”sqlite” |
connection_string | string | PostgreSQL URL (pgvector backend) | , |
collection_name | string | Table/collection name (pgvector backend) | , |
build_index | boolean | Rebuild index on startup | false |
source_dir | string | Source directory when building | , |
remote_url | string | Remote search-server URL (alternative to local index) | , |
index_name | string | Named index on remote server | ”default” |
count | integer | Results to return (1-20) | 5 |
similarity_threshold | number | Minimum score (0.0-1.0) | 0.0 |
tags | array | Filter results by tag | [] |
global_tags | array | Always-applied tag filter | [] |
file_types | array | File extensions to index | ["md","txt","pdf","docx","html"] |
exclude_patterns | array | Glob patterns to skip | defaults |
no_results_message | string | Message when nothing matches | default template |
response_prefix | string | Prepended to result text | , |
response_postfix | string | Appended to result text | , |
max_content_length | integer | Max result chars | 32768 |
description | string | Tool description override | , |
from signalwire import AgentBase
class LocalSearchAgent(AgentBase):
def __init__(self):
super().__init__(name="local-search")
self.add_language("English", "en-US", "rime.spore")
self.add_skill("native_vector_search", {
"index_file": "/path/to/knowledge.swsearch",
"tool_name": "search_docs"
})mcp_gateway
Connect to MCP (Model Context Protocol) servers via the MCP Gateway service. This skill dynamically creates SWAIG functions from MCP tools, enabling your agent to use any MCP-compatible tool.
Functions: Dynamically created based on connected MCP services
Requirements:
- MCP Gateway service running
- Gateway URL and authentication credentials
Parameters:
| Parameter | Type | Description | Default |
|---|---|---|---|
gateway_url | string | MCP Gateway service URL | Required |
auth_user | string | Basic auth username | None |
auth_password | string | Basic auth password | None |
auth_token | string | Bearer token (alternative auth) | None |
services | array | Services and tools to enable | All |
session_timeout | integer | Session timeout (seconds) | 300 |
tool_prefix | string | Prefix for function names | ”mcp_“ |
retry_attempts | integer | Connection retries | 3 |
request_timeout | integer | Request timeout (seconds) | 30 |
verify_ssl | boolean | Verify SSL certificates | true |
How it works:
- Skill connects to gateway and discovers available tools
- Each MCP tool becomes a SWAIG function (e.g.,
mcp_todo_add_todo) - Sessions persist per call_id, enabling stateful tools
- Session automatically closes when call ends
from signalwire import AgentBase
class MCPAgent(AgentBase):
def __init__(self):
super().__init__(name="mcp-agent")
self.add_language("English", "en-US", "rime.spore")
self.add_skill("mcp_gateway", {
"gateway_url": "http://localhost:8080",
"auth_user": "admin",
"auth_password": "secure-password",
"services": [\
{"name": "todo", "tools": "*"},\
{"name": "calculator", "tools": ["add", "multiply"]}\
]
})
self.prompt_add_section(
"Role",
"You help users manage tasks and perform calculations."
)google_maps
Validate addresses and compute driving routes using Google Maps. Supports geocoding, spoken number normalization (e.g., “seven one four” becomes “714”), and location-biased search.
Functions:
lookup_address- Validate and geocode a street address or business namecompute_route- Compute driving distance and estimated travel time between two points
Requirements: Google Maps API key with Geocoding and Routes APIs enabled
Parameters:
| Parameter | Type | Description | Default |
|---|---|---|---|
api_key | string | Google Maps API key (falls back to GOOGLE_MAPS_API_KEY) | Required |
lookup_tool_name | string | Address lookup function name | ”lookup_address” |
route_tool_name | string | Route computation function name | ”compute_route” |
geocode_tool_name | string | Reverse-geocoding function name | ”geocode_address” |
route_by_coords_tool_name | string | Coord-based route function name | ”compute_route_by_coords” |
default_mode | string | "driving", "walking", "bicycling", or "transit" | ”driving” |
from signalwire import AgentBase
class DeliveryAgent(AgentBase):
def __init__(self):
super().__init__(name="delivery-agent")
self.add_language("English", "en-US", "rime.spore")
self.add_skill("google_maps", {
"api_key": "YOUR_GOOGLE_MAPS_API_KEY"
})
self.prompt_add_section(
"Role",
"You help customers verify delivery addresses and estimate delivery times."
)info_gatherer
Gather answers to a configurable list of questions. This is the skill version of the InfoGathererAgent prefab, designed to be embedded within larger agents.
Functions:
start_questions- Begin the question sequencesubmit_answer- Submit an answer and get the next question
Requirements: None
Parameters:
| Parameter | Type | Description | Default |
|---|---|---|---|
questions | list | List of question dictionaries (key_name, question_text, confirm, prompt_add) | Required |
prefix | string | Prefix for tool names and namespace (enables multi-instance) | None |
completion_message | string | Message read after the last question | default template |
Multi-instance support: Yes - use the prefix parameter to run multiple question sets on a single agent. With prefix="intake", tools become intake_start_questions and intake_submit_answer, and state is stored under skill:intake in global_data.
from signalwire import AgentBase
class MultiFormAgent(AgentBase):
def __init__(self):
super().__init__(name="multi-form")
self.add_language("English", "en-US", "rime.spore")
# First question set
self.add_skill("info_gatherer", {
"prefix": "contact",
"questions": [\
{"key_name": "name", "question_text": "What is your name?"},\
{"key_name": "email", "question_text": "What is your email?", "confirm": True}\
]
})
# Second question set
self.add_skill("info_gatherer", {
"prefix": "feedback",
"questions": [\
{"key_name": "rating", "question_text": "How would you rate our service?"},\
{"key_name": "comments", "question_text": "Any additional comments?"}\
]
})claude_skills
Load Claude Code-style SKILL.md files as agent tools. Each SKILL.md file in the configured directory becomes a SWAIG function, with YAML frontmatter parsed for metadata (name, description, parameters).
Functions: Dynamically created from SKILL.md files (prefixed with claude_ by default)
Requirements: PyYAML package
Parameters:
| Parameter | Type | Description | Default |
|---|---|---|---|
skills_path | string | Path to directory containing SKILL.md files | Required |
include | array | Glob patterns of SKILL.md files to load | ["*"] |
exclude | array | Glob patterns to skip | [] |
tool_prefix | string | Prefix for generated function names | ”claude_“ |
prompt_title | string | Section title added to agent prompt | ”Claude Skills” |
prompt_intro | string | Prose introducing the loaded skills | default template |
skill_descriptions | object | Override descriptions, keyed by skill name | {} |
response_prefix | string | Prepended to each skill response | , |
response_postfix | string | Appended to each skill response | , |
allow_shell_injection | boolean | Permit shell metacharacters in arguments | false |
allow_script_execution | boolean | Permit running scripts referenced by a skill | false |
ignore_invocation_control | boolean | Bypass per-skill invocation gating | false |
shell_timeout | integer | Shell command timeout (seconds) | 30 |
from signalwire import AgentBase
class ClaudeSkillsAgent(AgentBase):
def __init__(self):
super().__init__(name="claude-skills-agent")
self.add_language("English", "en-US", "rime.spore")
self.add_skill("claude_skills", {
"skills_path": "/path/to/skills/directory",
"tool_prefix": "skill_"
})Skills Summary Table
| Skill | Functions | API Required | Multi-Instance |
|---|---|---|---|
datetime | 2 | No | No |
math | 1 | No | No |
web_search | 1 | Yes | Yes |
wikipedia_search | 1 | No | No |
weather_api | 1 | Yes | No |
joke | 1 | No | No |
play_background_file | 2 | No | No |
swml_transfer | 1 | No | Yes |
datasphere | 1 | Yes | Yes |
native_vector_search | 1 | No | Yes |
mcp_gateway | Dynamic | No* | Yes |
google_maps | 2 | Yes | No |
info_gatherer | 2 | No | Yes |
claude_skills | Dynamic | No | Yes |
api_ninjas_trivia | 1 | Yes | Yes |
ask_claude | 1 | Yes | No |
custom_skills | Dynamic | No | No |
datasphere_serverless | 1 | Yes | Yes |
spider | 1 | No | Yes |
\* Requires MCP Gateway service, not external API
