Testing

View as MarkdownOpen in Claude

Testing Stages

1. Local Testing

  • Run agent locally
  • Test with swaig-test CLI
  • Verify SWML output

2. Tunnel Testing

  • Expose via ngrok
  • Make real calls
  • Test end-to-end

3. Production Testing

  • Deploy to production server
  • Test with real phone
  • Monitor call logs

swaig-test CLI

Test agents without making calls:

# List available functions
swaig-test my_agent.py --list-tools
# View SWML output
swaig-test my_agent.py --dump-swml
# Execute a function
swaig-test my_agent.py --exec get_weather --city Seattle
# Raw JSON output
swaig-test my_agent.py --dump-swml --raw

Local Server Testing

Run your agent locally using the appropriate command for your language:

LanguageStart Command
Pythonpython my_agent.py
TypeScriptnpx tsx my_agent.ts

Then test the endpoint (the HTTP interface is identical regardless of language):

# In another terminal, test the endpoint (use credentials from agent output or env vars)
curl -X POST -u "$SWML_BASIC_AUTH_USER:$SWML_BASIC_AUTH_PASSWORD" http://localhost:3000/ \
-H "Content-Type: application/json" \
-d '{"call_id": "test-123"}'

Using ngrok

Expose local server for real calls:

# Terminal 1: Run agent
python my_agent.py
# Terminal 2: Start ngrok
ngrok http 3000

Copy the ngrok HTTPS URL and configure in SignalWire.

Test Call Checklist

Basic Functionality

  • Call connects successfully
  • Agent greeting plays
  • Speech recognition works
  • Agent responds appropriately

Function Calls

  • Functions execute correctly
  • Results returned to AI
  • AI summarizes results properly

Edge Cases

  • Silence handling
  • Interruption handling
  • Long responses
  • Multiple function calls

Error Handling

  • Invalid input handled
  • Function errors handled gracefully
  • Timeout behavior correct

Viewing Logs

In SignalWire dashboard:

  1. Go to Logs
  2. Find your test call
  3. View details:
    • Call duration
    • SWML executed
    • Function calls
    • Errors

Debugging with Logs

Add logging to your agent:

import logging
logging.basicConfig(level=logging.DEBUG)
class MyAgent(AgentBase):
def __init__(self):
super().__init__(name="my-agent")
self.log.info("Agent initialized")
def my_handler(self, args, raw_data):
self.log.debug(f"Function called with args: {args}")
self.log.debug(f"Raw data: {raw_data}")
result = "Some result"
self.log.info(f"Returning: {result}")
return FunctionResult(result)

Testing Transfers

Test call transfers carefully. The transfer API is the same across languages via FunctionResult:

LanguageTransfer Call
PythonFunctionResult("Transferring").connect(number, final=True)
TypeScriptnew FunctionResult("Transferring").connect(number, true)
def test_transfer(self, args, raw_data):
# Use a test number you control
test_number = "+15551234567"
return (
FunctionResult("Transferring now")
.connect(test_number, final=True)
)

Testing SMS

Test SMS sending. The SMS API follows the same pattern across languages:

LanguageSend SMS
PythonFunctionResult("Sent").send_sms(to_number=to, from_number=from_, body=msg)
TypeScriptnew FunctionResult("Sent").sendSms({ toNumber: to, fromNumber: from, body: msg })
def test_sms(self, args, raw_data):
# Send to your own phone for testing
return (
FunctionResult("Sent test SMS")
.send_sms(
to_number="+15551234567", # Your test phone
from_number="+15559876543", # Your SignalWire number
body="Test message from agent"
)
)

Load Testing

For production readiness:

  • Test concurrent call handling
  • Monitor server resources
  • Check response times under load
  • Verify function execution at scale
  • Test database/API connection pooling

Common Test Scenarios

ScenarioWhat to Test
Happy pathNormal conversation flow
No speechSilence and timeout handling
Background noiseSpeech recognition accuracy
Rapid speechInterruption handling
Invalid requestsError handling
Function errorsGraceful degradation
Long callsMemory and stability

Automated Testing

Create test scripts:

import requests
def test_swml_endpoint():
"""Test that SWML endpoint returns valid response"""
response = requests.post(
"http://localhost:3000/",
json={"call_id": "test-123"},
headers={"Content-Type": "application/json"}
)
assert response.status_code == 200
data = response.json()
assert "version" in data
assert data["version"] == "1.0.0"
def test_function_execution():
"""Test that functions execute correctly"""
response = requests.post(
"http://localhost:3000/swaig",
json={
"function": "get_weather",
"argument": {"parsed": [{"city": "Seattle"}]},
"call_id": "test-123"
}
)
assert response.status_code == 200