xiaohongshu
xiaohongshu
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.
Full skill instructions
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).
Activate this skill when the user:
signalwire_agents or signalwire_agents.coreAgentBase# 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 is the main class for building agents. It combines multiple mixins:
prompt_add_section, POM)define_tool, @tool)add_skill, remove_skill)Constructor Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
name | str | required | Agent identifier |
route | str | "/" | HTTP endpoint path |
host | str | "0.0.0.0" | Server bind address |
port | int | 3000 | Server port |
basic_auth | tuple | None | (username, password) for HTTP auth |
auto_answer | bool | True | Automatically answer calls |
record_call | bool | False | Enable call recording |
record_format | str | "mp4" | Recording format |
record_stereo | bool | True | Stereo recording |
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
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:[email protected]"}))
# 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 | dest | Transfer call to destination |
hangup | reason | End the call |
play | url, urls | Play audio file(s) |
set_global_data | key-value pairs | Update conversation data |
toggle_functions | active, inactive | Enable/disable functions |
playback_bg | file, wait | Background audio |
stop_playback_bg | - | Stop background audio |
# 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"
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"]
}
}
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
})
# Add hints for better recognition
self.add_hints(["SignalWire", "SWML", "SWAIG", "API"])
# Industry-specific hints
self.add_hints([
"account number",
"routing number",
"checking",
"savings"
])
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
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:
web_search - Google Custom Searchwikipedia_search - Wikipedia lookupsweather_api - Weather datamath - Mathematical operationsdatetime - Date/time functionsnative_vector_search - Local document searchswml_transfer - Call transfersdatasphere - Data integrationFor 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())
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()
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
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:
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)
Register your agent with SignalWire Fabric for phone/WebRTC access:
/public/my-agent# 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.
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.")
super().__init__() call with nameif __name__ == "__main__" block#!/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()
#!/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.run(event, context) for Lambda, agent.run(request) for GCF@self.tool decorator inside _setup_functions() method (not @AgentBase.tool)add_language()(self, args, raw_data)SwaigFunctionResult, not plain stringsname parameter# 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
| Problem | Likely Cause | Solution |
|---|---|---|
| Agent doesn't speak | No language configured | Add add_language() |
| Function never called | Poor description | Make description clearer |
| Parameters missing | Schema format wrong | Use JSON Schema format |
| Import error | Wrong import path | Use from signalwire_agents import AgentBase |
| Port in use | Another process | Change port or stop other process |
| Transfer fails | Bad destination | Use tel:+1... or sip:user@domain |
For detailed API documentation, see:
reference/agent-base.md - Complete AgentBase referencereference/swaig-functions.md - Function definition patternsreference/function-result.md - SwaigFunctionResult actionsreference/agent-server.md - Multi-agent deployment and static filesreference/datamap-advanced.md - DataMap expressions, webhooks, array processingreference/contexts-steps.md - Workflow system with steps and navigationreference/prefabs.md - Pre-built agents (InfoGatherer, Survey, Concierge, etc.)reference/voice-configuration.md - TTS engines, voices, fillers, pronunciationreference/dynamic-configuration.md - Per-request customization and routingreference/skills-complete.md - All built-in skills and custom skill developmentreference/sip-routing.md - SIP username-based routingreference/bedrock-agent.md - Amazon Bedrock voice-to-voice integrationreference/serverless.md - AWS Lambda, Google Cloud Functions, Azure, CGIreference/environment-variables.md - Complete env var referencereference/signalwire-integration.md - Fabric API, WebRTC, phone numbersreference/webhooks-debugging.md - Debug webhooks, monitoring, troubleshootingBest practices and reusable patterns:
patterns/common-patterns.md - Frequently used patterns (lookup, transfer, confirmation)patterns/error-handling.md - Error handling best practicespatterns/testing.md - Testing with swaig-test and pytestpatterns/security.md - Security best practicesWorking code examples:
examples/simple-agent.py - Basic agent templateexamples/multi-agent-server.py - Multiple agents with static filesexamples/webrtc-enabled-agent.py - Browser-based voice interactionexamples/faq-bot.py - FAQ bot with skillsexamples/datamap-agent.py - Server-side functions with DataMapexamples/serverless-agent.py - AWS Lambda, Google Cloud Functions, Azure deploymentSee troubleshooting.md for common issues and solutions.
xiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience