All fields are required
Twilio webhooks are stateless. You rebuild context on every request. SignalWire is Twilio-compatible at the API level, and the native interfaces eliminate webhook state management entirely.
A hangup webhook arrives after a transfer command. The call is live with no tracking. Your state store says the call ended. The caller is still on the line.
Two concurrent webhooks for the same call read state, both mutate it, and the last write wins. The other mutation is silently lost.
The transfer target answers during a network partition. Your state store still shows "ringing." The caller is talking to someone your system does not know about.
The caller interrupts while the LLM generates. The old response plays anyway because the cancellation signal traveled a different path than the audio.
from signalwire_agents import AgentBase
from signalwire_agents.core.function_result import SwaigFunctionResult
class SupportAgent(AgentBase):
def __init__(self):
super().__init__(name="Support Agent", route="/support")
self.prompt_add_section("Instructions",
body="You are a customer support agent. "
"Greet the caller and resolve their issue.")
self.add_language("English", "en-US", "rime.spore:mistv2")
@AgentBase.tool(name="check_order")
def check_order(self, order_id: str):
"""Check the status of a customer order.
Args:
order_id: The order ID to look up
"""
return SwaigFunctionResult(f"Order {order_id}: shipped, ETA April 2nd")
agent = SupportAgent()
agent.run()
Start with Twilio-compatible REST APIs for call management, number provisioning, SIP trunking, and webhook endpoints. Your existing code works on day one.
Transfer phone numbers from Twilio. The process is standard number porting. No downtime required.
Replace TwiML with declarative YAML. Replace webhook state management with platform-native state. Each conversion eliminates a category of race conditions.
Replace webhook chains with tool calling. Your backend handles business logic. The platform handles conversation flow, state, and orchestration.
Use the platform's integrated STT, LLM, and TTS. No third-party AI vendor integrations, no separate billing relationships.
Enable scoped prompts per step, constrained tool access, and enforced state machine transitions. Production safety without prompt-level guardrails.
| What Changes | What Stays |
|---|---|
| State management (platform-native) | Your backend and business logic |
| AI orchestration (built-in) | Your API endpoints |
| Webhook chains (eliminated) | Your phone numbers (port them) |
| Multi-vendor coordination (eliminated) | Your deployment infrastructure |
| Log correlation (unified) | Your monitoring and alerting |
| Component | Twilio + Vendors | SignalWire |
|---|---|---|
| Voice (per minute) | $0.013-0.022 | Included |
| STT | $0.006-0.015 per 15s | Included |
| LLM | Variable (per token) | Included |
| TTS | $0.015-0.030 per 1K chars | Included |
| Total per AI minute | $0.15-0.40+ | $0.16 flat |
SignalWire provides Twilio-compatible REST APIs for call management, number provisioning, SIP trunking, and webhook endpoints. Existing Twilio code can run with minimal changes. The native interfaces go further.
Yes. Start with API compatibility, then convert individual call flows to native interfaces at your own pace. You do not need to migrate everything at once.
Standard number porting from Twilio. No downtime required. Your numbers transfer to SignalWire and work with both the compatibility layer and native interfaces.
Not for call state. The platform is the system of record. Your tool handlers receive authoritative context on every invocation. If you use Redis for business-level state (inventory, user profiles), that stays the same.
Trusted by
Start with Twilio-compatible APIs. Graduate to platform-native capabilities at your own pace.