Awesome-omni-skill signalwire-agents-sdk
Expert assistance for building SignalWire AI Agents in Python. Automatically activates when working with AgentBase, SWAIG functions, skills, SWML, voice configuration, DataMap, or any signalwire_agents code. Provides patterns, best practices, and complete working examples.
git clone https://github.com/diegosouzapw/awesome-omni-skill
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data-ai/signalwire-agents-sdk" ~/.claude/skills/diegosouzapw-awesome-omni-skill-signalwire-agents-sdk-e2f994 && rm -rf "$T"
skills/data-ai/signalwire-agents-sdk/SKILL.mdSignalWire AI Agents SDK Expert
You are an expert in the SignalWire AI Agents SDK for Python. You help developers build production-ready voice AI agents using SWML (SignalWire Markup Language) and SWAIG (SignalWire AI Gateway).
When This Skill Applies
Activate this skill when the user:
- Imports from
orsignalwire_agentssignalwire_agents.core - Creates classes extending
AgentBase - Works with SWAIG functions, tools, or handlers
- Configures voice, language, or TTS settings
- Uses DataMap for server-side functions
- Works with agent skills (built-in or custom)
- Asks about SWML, prompts, or call flow
- Deploys agents (serverless, Docker, multi-agent)
Core SDK Knowledge
Package Structure
# Main imports from signalwire_agents import AgentBase from signalwire_agents.core.function_result import SwaigFunctionResult from signalwire_agents.core.data_map import DataMap # For multi-agent deployments from signalwire_agents import AgentServer # For custom skills from signalwire_agents.core.skill_base import SkillBase # For workflows from signalwire_agents.core.contexts import Context, Step, ContextBuilder
AgentBase - The Foundation
AgentBase is the main class for building agents. It combines multiple mixins:
- PromptMixin: Prompt building (
, POM)prompt_add_section - ToolMixin: SWAIG functions (
,define_tool
)@tool - SkillMixin: Skill management (
,add_skill
)remove_skill - AIConfigMixin: Voice, language, hints, parameters
- WebMixin: HTTP endpoints and routing
- AuthMixin: Basic auth, token security
- StateMixin: Conversation state
- ServerlessMixin: Lambda/Cloud Functions support
Constructor Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
| str | required | Agent identifier |
| str | "/" | HTTP endpoint path |
| str | "0.0.0.0" | Server bind address |
| int | 3000 | Server port |
| tuple | None | (username, password) for HTTP auth |
| bool | True | Automatically answer calls |
| bool | False | Enable call recording |
| str | "mp4" | Recording format |
| bool | True | Stereo recording |
SWAIG Function Definition
Method 1: @tool Decorator (Recommended)
@AgentBase.tool( name="function_name", description="Clear description for the AI to understand when to call this", parameters={ "param_name": { "type": "string", "description": "What this parameter represents" }, "optional_param": { "type": "integer", "description": "Optional parameter", "default": 10 } } ) def function_name(self, args, raw_data): param = args.get("param_name") return SwaigFunctionResult(f"Result for {param}")
Method 2: define_tool() (Imperative)
def __init__(self): super().__init__(name="my-agent") self.define_tool( name="lookup_order", description="Look up an order by ID", parameters={ "order_id": { "type": "string", "description": "The order ID to look up" } }, handler=self.handle_lookup_order ) def handle_lookup_order(self, args, raw_data): order_id = args.get("order_id") # ... lookup logic return SwaigFunctionResult(f"Order {order_id} status: shipped")
Handler Signature:
def handler(self, args: dict, raw_data: dict) -> SwaigFunctionResult: # args: Parameters passed by the AI # raw_data: Full request including call_id, metadata, etc. pass
SwaigFunctionResult
The return type for all SWAIG function handlers.
from signalwire_agents.core.function_result import SwaigFunctionResult # Simple response return SwaigFunctionResult("The weather is sunny and 72°F") # Response with action return SwaigFunctionResult("Transferring you now").add_action( "transfer", {"dest": "tel:+15551234567"} ) # Multiple actions (method chaining) return (SwaigFunctionResult("Let me play some music while I transfer you") .add_action("play", {"url": "https://example.com/hold.mp3"}) .add_action("transfer", {"dest": "sip:support@company.com"})) # Post-process (AI responds before actions execute) return SwaigFunctionResult("I'll transfer you to support", post_process=True).add_action( "transfer", {"dest": "tel:+15559876543"} )
Common Actions:
| Action | Parameters | Description |
|---|---|---|
| | Transfer call to destination |
| | End the call |
| , | Play audio file(s) |
| key-value pairs | Update conversation data |
| , | Enable/disable functions |
| , | Background audio |
| - | Stop background audio |
Voice and Language Configuration
# Add a language with voice self.add_language("English", "en-US", "rime.spore") # Multiple languages self.add_language("English", "en-US", "rime.spore") self.add_language("Spanish", "es-MX", "rime.spore") # Available TTS engines and example voices: # - ElevenLabs: "elevenlabs.josh", "elevenlabs.rachel" # - Google: "gcloud.en-US-Neural2-A" # - Azure: "azure.en-US-JennyNeural" # - Amazon: "polly.Matthew" # - Cartesia: "cartesia.default" # - Deepgram: "deepgram.aura-asteria-en" # - OpenAI: "openai.nova" # - Rime (default): "rime.spore", "rime.marsh"
Prompt Building
Method 1: prompt_add_section()
# Simple section self.prompt_add_section("Role", "You are a helpful customer service agent.") # Section with bullets self.prompt_add_section( "Guidelines", body="Follow these rules:", bullets=[ "Be friendly and professional", "Keep responses concise", "Ask clarifying questions when needed" ] ) # Subsection self.prompt_add_subsection( "Guidelines", "Escalation", body="Transfer to a human if the customer asks." )
Method 2: Declarative PROMPT_SECTIONS
class MyAgent(AgentBase): PROMPT_SECTIONS = { "Role": "You are a helpful assistant.", "Guidelines": [ "Be concise", "Be accurate", "Be helpful" ], "Personality": { "body": "You have a friendly demeanor.", "bullets": ["Use casual language", "Add appropriate humor"] } }
AI Parameters
self.set_params({ # Speech detection "end_of_speech_timeout": 1000, # ms of silence to end turn "attention_timeout": 10000, # ms before "are you there?" "inactivity_timeout": 300000, # ms before hanging up # Interruption handling "barge_match_string": "stop|cancel|help", "barge_min_words": 2, # AI behavior "ai_volume": 0, # -50 to 50 dB adjustment "local_tz": "America/New_York", # Energy detection "energy_threshold": 0.05 # 0.01-1.0, lower = more sensitive })
Speech Recognition Hints
# Add hints for better recognition self.add_hints(["SignalWire", "SWML", "SWAIG", "API"]) # Industry-specific hints self.add_hints([ "account number", "routing number", "checking", "savings" ])
Call Flow Customization
Control what happens before/after the AI conversation:
# Pre-answer: Play ringback while call rings self.add_pre_answer_verb("play", { "urls": ["ring:us"], "auto_answer": False # Required for pre-answer }) # Post-answer: Welcome message before AI self.add_post_answer_verb("play", { "url": "say:Thank you for calling. This call may be recorded." }) self.add_post_answer_verb("sleep", {"time": 500}) # Post-AI: Cleanup after conversation ends self.add_post_ai_verb("request", { "url": "https://api.example.com/call-complete", "method": "POST" }) self.add_post_ai_verb("hangup", {})
Pre-answer safe verbs: transfer, execute, return, label, goto, request, switch, cond, if, eval, set, unset, hangup, send_sms, sleep
Skills System
Adding Built-in Skills:
# Web search self.add_skill("web_search", { "api_key": "your-google-api-key", "search_engine_id": "your-cse-id" }) # Weather self.add_skill("weather_api", { "provider": "openweathermap", "api_key": "your-api-key", "units": "imperial" }) # Date/time self.add_skill("datetime", {"timezone": "America/New_York"}) # Math operations self.add_skill("math")
Available Built-in Skills:
- Google Custom Searchweb_search
- Wikipedia lookupswikipedia_search
- Weather dataweather_api
- Mathematical operationsmath
- Date/time functionsdatetime
- Local document searchnative_vector_search
- Call transfersswml_transfer
- Data integrationdatasphere
DataMap (Server-Side Functions)
For functions that don't need local handlers:
from signalwire_agents.core.data_map import DataMap weather_func = (DataMap("get_weather") .purpose("Get current weather for a location") .parameter("city", "string", "City name", required=True) .webhook("GET", "https://api.weather.com/v1/current?q=${args.city}&key=KEY") .output(SwaigFunctionResult( "The weather in ${args.city} is ${response.condition} " "and ${response.temp_f}°F" )) ) self.register_swaig_function(weather_func.to_swaig_function())
Multi-Agent Deployment
from signalwire_agents import AgentServer server = AgentServer(host="0.0.0.0", port=3000) server.register(SupportAgent(), "/support") server.register(SalesAgent(), "/sales") server.register(FAQAgent(), "/faq") # Optionally serve static files (web UI) server.serve_static_files("./web") server.run()
Environment Variables
Common environment variables for configuration:
# SignalWire credentials (required for Fabric API) export SIGNALWIRE_SPACE_NAME="myspace" export SIGNALWIRE_PROJECT_ID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" export SIGNALWIRE_TOKEN="PTxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # Proxy URL for SWML callbacks export SWML_PROXY_URL_BASE="https://your-domain.com" # Basic auth export SWML_BASIC_AUTH_USER="agent" export SWML_BASIC_AUTH_PASSWORD="secret" # Debug webhooks export DEBUG_WEBHOOK_URL="https://webhook.site/your-id" export DEBUG_WEBHOOK_LEVEL="1" # 0=off, 1=basic, 2=verbose # Logging export SWML_LOG_LEVEL="DEBUG" # DEBUG, INFO, WARNING, ERROR
Debug Webhooks
Send real-time events to external URL for monitoring:
self.set_params({ "debug_webhook_url": "https://webhook.site/your-id", "debug_webhook_level": 1 # 1=basic, 2=verbose })
Debug levels:
- 0: Off (default)
- 1: Function calls, errors, state changes
- 2: Full transcripts and payloads
Post-Prompt and Summaries
Get structured data when conversations end:
# Text summary self.set_post_prompt("Summarize this conversation in 2-3 sentences.") # Structured JSON self.set_post_prompt(json_schema={ "type": "object", "properties": { "resolved": {"type": "boolean"}, "category": {"type": "string"}, "summary": {"type": "string"} } }) # Handle summary in your agent def on_summary(self, summary=None, raw_data=None): if summary: self.log.info("call_complete", summary=summary)
SignalWire Platform Integration
Register your agent with SignalWire Fabric for phone/WebRTC access:
- Create External SWML Handler - Points SignalWire to your agent URL
- Create Subscriber - Gets an address like
/public/my-agent - Create Guest Token - For browser WebRTC connections
# Agent with basic auth for Fabric class MyAgent(AgentBase): def __init__(self): super().__init__( name="my-agent", basic_auth=("user", "password") # Embedded in Fabric URL )
See
reference/signalwire-integration.md for complete Fabric API examples.
Dynamic Configuration
Override agent behavior per-request:
def on_swml_request(self, request_data=None, callback_path=None, request=None): """Called before SWML is generated for each request.""" call_data = (request_data or {}).get("call", {}) caller = call_data.get("from", "") # Customize based on caller if caller.startswith("+1555"): self.prompt_add_section("VIP", "This is a VIP customer.")
Code Generation Guidelines
Always Include
- Shebang and imports
- Class docstring
call withsuper().__init__()name- Language configuration
- At least one prompt section
blockif __name__ == "__main__"
Standard Template
#!/usr/bin/env python3 from signalwire_agents import AgentBase from signalwire_agents.core.function_result import SwaigFunctionResult class MyAgent(AgentBase): """Description of what this agent does.""" def __init__(self): super().__init__(name="my-agent", port=3000) # Configure voice self.add_language("English", "en-US", "rime.spore") # Build prompt self.prompt_add_section("Role", "You are a helpful assistant.") self.prompt_add_section( "Guidelines", bullets=[ "Be concise and helpful", "Ask clarifying questions when needed" ] ) # Configure AI behavior self.set_params({ "end_of_speech_timeout": 1000, "attention_timeout": 10000 }) @AgentBase.tool( name="example_function", description="Describe what this function does", parameters={ "input": { "type": "string", "description": "The input to process" } } ) def example_function(self, args, raw_data): """Handle the example_function call.""" input_value = args.get("input", "") return SwaigFunctionResult(f"Processed: {input_value}") if __name__ == "__main__": agent = MyAgent() agent.run()
Serverless Template (AWS Lambda / Google Cloud / Azure)
#!/usr/bin/env python3 """Serverless handler for SignalWire agent.""" import os from signalwire_agents import AgentBase, SwaigFunctionResult class MyAgent(AgentBase): """Description of what this agent does.""" def __init__(self): super().__init__(name="my-serverless-agent") # Configure voice self.add_language("English", "en-US", "rime.spore") # Build prompt self.prompt_add_section("Role", "You are a helpful assistant.") self._setup_functions() def _setup_functions(self): @self.tool( description="Describe what this function does", parameters={ "type": "object", "properties": { "input": { "type": "string", "description": "The input to process" } }, "required": ["input"] } ) def example_function(args, raw_data): input_value = args.get("input", "") return SwaigFunctionResult(f"Processed: {input_value}") # CRITICAL: Create agent instance OUTSIDE handler for cold start optimization agent = MyAgent() # AWS Lambda def lambda_handler(event, context): return agent.run(event, context) # Google Cloud Functions def main(request): return agent.run(request) # Azure Functions (requires: import azure.functions as func) # def main(req: func.HttpRequest) -> func.HttpResponse: # return agent.run(req)
Key Differences from Server-Based:
- Agent instantiated outside the handler function
- Use
for Lambda,agent.run(event, context)
for GCFagent.run(request) - No port binding needed - HTTP trigger handles routing
- Use
decorator inside@self.tool
method (not_setup_functions()
)@AgentBase.tool
Common Mistakes to Avoid
- Missing language: Agent won't speak without
add_language() - Wrong handler signature: Must be
(self, args, raw_data) - Returning strings: Use
, not plain stringsSwaigFunctionResult - Missing name: Constructor requires
parametername - Vague descriptions: AI needs clear function descriptions to call correctly
- Forgetting super().init(): Will break mixin initialization
Testing
# Verify SWML output swaig-test agent.py --dump-swml # List registered functions swaig-test agent.py --list-tools # Execute a function swaig-test agent.py --exec function_name --param_name "value" # Test specific class in multi-class file swaig-test agent.py --agent-class MyAgent
Troubleshooting
| Problem | Likely Cause | Solution |
|---|---|---|
| Agent doesn't speak | No language configured | Add |
| Function never called | Poor description | Make description clearer |
| Parameters missing | Schema format wrong | Use JSON Schema format |
| Import error | Wrong import path | Use |
| Port in use | Another process | Change port or stop other process |
| Transfer fails | Bad destination | Use or |
Reference Files
For detailed API documentation, see:
Core Reference
- Complete AgentBase referencereference/agent-base.md
- Function definition patternsreference/swaig-functions.md
- SwaigFunctionResult actionsreference/function-result.md
- Multi-agent deployment and static filesreference/agent-server.md
Advanced Features
- DataMap expressions, webhooks, array processingreference/datamap-advanced.md
- Workflow system with steps and navigationreference/contexts-steps.md
- Pre-built agents (InfoGatherer, Survey, Concierge, etc.)reference/prefabs.md
- TTS engines, voices, fillers, pronunciationreference/voice-configuration.md
- Per-request customization and routingreference/dynamic-configuration.md
- All built-in skills and custom skill developmentreference/skills-complete.md
- SIP username-based routingreference/sip-routing.md
- Amazon Bedrock voice-to-voice integrationreference/bedrock-agent.md
Deployment
- AWS Lambda, Google Cloud Functions, Azure, CGIreference/serverless.md
- Complete env var referencereference/environment-variables.md
- Fabric API, WebRTC, phone numbersreference/signalwire-integration.md
- Debug webhooks, monitoring, troubleshootingreference/webhooks-debugging.md
Patterns
Best practices and reusable patterns:
- Frequently used patterns (lookup, transfer, confirmation)patterns/common-patterns.md
- Error handling best practicespatterns/error-handling.md
- Testing with swaig-test and pytestpatterns/testing.md
- Security best practicespatterns/security.md
Example Files
Working code examples:
- Basic agent templateexamples/simple-agent.py
- Multiple agents with static filesexamples/multi-agent-server.py
- Browser-based voice interactionexamples/webrtc-enabled-agent.py
- FAQ bot with skillsexamples/faq-bot.py
- Server-side functions with DataMapexamples/datamap-agent.py
- AWS Lambda, Google Cloud Functions, Azure deploymentexamples/serverless-agent.py
Troubleshooting
See
troubleshooting.md for common issues and solutions.