Your OpenAI Realtime API integration works in demos. In production, SIP calls start failing. That is not an AI problem. That is a telephony infrastructure problem.
OpenAI Built a Remarkable AI. They Did Not Build a Phone Company.
Webhook services collapse under load
A forum post attributed the root cause to the webhook service running out of memory under production traffic. Failed calls escalated when developers began onboarding real customers.
Developers report 10 to 20% of inbound calls never trigger a webhook
Based on community forum discussions, session establishment fails silently. No error message, no retry, no callback. Callers hear nothing. Developers see nothing in their logs.
SIP session management is an afterthought
Call state and AI state live in different systems with no atomic synchronization. When the webhook service lags, call state drifts from conversation state.
Enterprise features do not exist
No native call transfers, no recording with consent management, no compliance logging, no failover routing. Every production requirement is a custom build.
Build a Voice AI Agent
fromsignalwire_agentsimportAgentBasefromsignalwire_agents.core.function_resultimportSwaigFunctionResultclassSupportAgent(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")defcheck_order(self,order_id:str):"""Check the status of a customer order. Args: order_id: The order ID to look up """returnSwaigFunctionResult(f"Order {order_id}: shipped, ETA April 2nd")agent=SupportAgent()agent.run()
import{AgentBase,FunctionResult}from'@signalwire/sdk';constagent=newAgentBase({name:'Support Agent',route:'/support',});agent.promptAddSection('Instructions','You are a customer support agent. Greet the caller and resolve their issue.');agent.addLanguage({name:'English',code:'en-US',voice:'rime.spore:mistv2'});agent.defineTool({name:'check_order',description:'Check the status of a customer order',parameters:{type:'object',properties:{order_id:{type:'string',description:'The order ID to look up'},},required:['order_id'],},handler:(args)=>{returnnewFunctionResult(`Order ${args.order_id}: shipped, ETA April 2nd`);},});agent.run();
packagemainimport("fmt""github.com/signalwire/signalwire-go/pkg/agent""github.com/signalwire/signalwire-go/pkg/swaig")funcmain(){a:=agent.NewAgentBase(agent.WithName("Support Agent"),agent.WithRoute("/support"),)a.PromptAddSection("Instructions","You are a customer support agent. Greet the caller and resolve their issue.")a.AddLanguage(map[string]any{"name":"English","code":"en-US","voice":"rime.spore:mistv2",})a.DefineTool(agent.ToolDefinition{Name:"check_order",Description:"Check the status of a customer order",Parameters:map[string]any{"type":"object","properties":map[string]any{"order_id":map[string]any{"type":"string","description":"The order ID to look up",},},"required":[]string{"order_id"},},Handler:func(argsmap[string]any,rawDatamap[string]any)*swaig.FunctionResult{orderID:=args["order_id"]returnswaig.NewFunctionResult(fmt.Sprintf("Order %v: shipped, ETA April 2nd",orderID),)},})a.Run()}
importcom.signalwire.sdk.agent.AgentBase;importcom.signalwire.sdk.swaig.FunctionResult;importjava.util.List;importjava.util.Map;publicclassSupportAgent{publicstaticvoidmain(String[]args)throwsException{varagent=AgentBase.builder().name("Support Agent").route("/support").build();agent.promptAddSection("Instructions","You are a customer support agent. "+"Greet the caller and resolve their issue.");agent.addLanguage("English","en-US","rime.spore:mistv2");agent.defineTool("check_order","Check the status of a customer order",Map.of("type","object","properties",Map.of("order_id",Map.of("type","string","description","The order ID to look up")),"required",List.of("order_id")),(toolArgs,rawData)->{varorderId=toolArgs.get("order_id");returnnewFunctionResult("Order "+orderId+": shipped, ETA April 2nd");});agent.run();}}
# frozen_string_literal: truerequire'signalwire'agent=SignalWire::AgentBase.new(name:'Support Agent',route:'/support')agent.prompt_add_section('Instructions','You are a customer support agent. Greet the caller and resolve their issue.')agent.add_language(name:'English',code:'en-US',voice:'rime.spore:mistv2')agent.define_tool(name:'check_order',description:'Check the status of a customer order',parameters:{'order_id'=>{'type'=>'string','description'=>'The order ID to look up'}})do|args,_raw|SignalWire::Swaig::FunctionResult.new("Order #{args['order_id']}: shipped, ETA April 2nd")endagent.run
<?phprequire'vendor/autoload.php';useSignalWire\Agent\AgentBase;useSignalWire\SWAIG\FunctionResult;$agent=newAgentBase(['name'=>'Support Agent','route'=>'/support']);$agent->promptAddSection('Instructions','You are a customer support agent. Greet the caller and resolve their issue.');$agent->addLanguage('English','en-US','rime.spore:mistv2');$agent->defineTool(name:'check_order',description:'Check the status of a customer order',parameters:['order_id'=>['type'=>'string','description'=>'The order ID to look up'],],handler:function(array$args):FunctionResult{returnnewFunctionResult("Order {$args['order_id']}: shipped, ETA April 2nd");});$agent->run();
#!/usr/bin/env perlusestrict;usewarnings;uselib'lib';useSignalWire::Agent::AgentBase;useSignalWire::SWAIG::FunctionResult;my$agent=SignalWire::Agent::AgentBase->new(name=>'Support Agent',route=>'/support',);$agent->prompt_add_section('Instructions','You are a customer support agent. Greet the caller and resolve their issue.');$agent->add_language(name=>'English',code=>'en-US',voice=>'rime.spore:mistv2');$agent->define_tool(name=>'check_order',description=>'Check the status of a customer order',parameters=>{order_id=>{type=>'string',description=>'The order ID to look up'},},handler=>sub{my($args,$raw)=@_;returnSignalWire::SWAIG::FunctionResult->new(response=>"Order $args->{order_id}: shipped, ETA April 2nd");},);$agent->run;
#include<signalwire/agent/agent_base.hpp>usingnamespacesignalwire;usingjson=nlohmann::json;classSupportAgent:publicagent::AgentBase{public:SupportAgent():AgentBase("Support Agent","/support"){prompt_add_section("Instructions","You are a customer support agent. ""Greet the caller and resolve their issue.");add_language({"English","en-US","rime.spore:mistv2"});define_tool({.name="check_order",.description="Check the status of a customer order",.parameters={{"order_id",{{"type","string"},{"description","The order ID to look up"}}}},.handler=[](constjson&args,constjson&){autoorder_id=args.value("order_id","unknown");returnswaig::FunctionResult("Order "+order_id+": shipped, ETA April 2nd");}});}};intmain(){SupportAgent().run();}
usingSignalWire.Agent;usingSignalWire.SWAIG;varagent=newAgentBase(newAgentOptions{Name="Support Agent",Route="/support"});agent.PromptAddSection("Instructions","You are a customer support agent. Greet the caller and resolve their issue.");agent.AddLanguage("English","en-US","rime.spore:mistv2");agent.DefineTool("check_order","Check the status of a customer order",new{type="object",properties=new{order_id=new{type="string",description="The order ID to look up"}},required=new[]{"order_id"}},(args,rawData)=>{varorderId=args.TryGetValue("order_id",outvarid)?id:"unknown";returnnewFunctionResult($"Order {orderId}: shipped, ETA April 2nd");});agent.Run();
usesignalwire::agent::AgentBase;usesignalwire::swaig::FunctionResult;useserde_json::json;fnmain(){letmutagent=AgentBase::builder().name("Support Agent").route("/support").build();agent.prompt_add_section("Instructions","You are a customer support agent. Greet the caller and resolve their issue.",&[]).add_language("English","en-US","rime.spore:mistv2");agent.define_tool("check_order","Check the status of a customer order",json!({"type":"object","properties":{"order_id":{"type":"string","description":"The order ID to look up"}},"required":["order_id"]}),Box::new(|args,_raw|{letorder_id=args.get("order_id").and_then(|v|v.as_str()).unwrap_or("unknown");FunctionResult::with_response(&format!("Order {order_id}: shipped, ETA April 2nd"))}),);agent.run();}
Two Architectures, One Choice
DIY SIP (Twilio + OpenAI Direct)
Caller dials in via third-party SIP trunk
Webhook service processes (OOM-prone under load)
Session state split across two vendors
10 to 20% call failure rate reported in forums
No native transfers, recording, or compliance
Application-level retry is your problem
SignalWire + Your OpenAI Integration
Caller dials in via carrier-grade infrastructure
Native SIP session lifecycle management
Unified call and conversation state
Built by the FreeSWITCH team (20 years of telecom)
Native transfers, recording, and compliance
Infrastructure-level redundancy and failover
Production Metrics That Matter
Metric
DIY SIP (Reported)
SignalWire
Call reliability
80 to 90% community-reported (10 to 20% failure)
Carrier-grade (FreeSWITCH heritage)
Session management
Webhook-based, OOM-prone
Native SIP, purpose-built
Concurrent scaling
Limited by webhook throughput
Built for carrier-scale traffic
Call transfers
Not natively supported
Blind and attended, native methods
Call recording
Manual implementation required
Native with compliance controls
Failover
Application-level retry
Infrastructure-level redundancy
From Demo to Production Calls
1
Keep your OpenAI integration
Your Realtime API code stays where it is. The conversational AI is yours. SignalWire provides the phone system underneath.
2
Define your call flow in YAML
Specify the prompt, available tool functions, and webhook endpoints. Your handler processes conversation events from your OpenAI pipeline.
3
Provision a phone number
Assign a number in your SignalWire dashboard and point it at your YAML document. Carrier-grade SIP, no trunk configuration.
4
Ship production
Calls arrive over carrier-grade infrastructure, route to your AI, and your OpenAI Realtime handler processes the conversation. No OOM failures. No dropped webhooks.
The Realtime API is an AI product, not a phone system. It was not designed to handle carrier-grade SIP session management at production scale. The SIP integration path adds failure modes at every hop between your telephony provider and the webhook service.
FAQ
Does this replace OpenAI's Realtime API?
No. Your OpenAI Realtime integration handles the conversation. SignalWire handles the phone call: SIP signaling, media transport, call transfers, recording, and compliance. Two systems, each purpose-built.
Will this fix the dropped call problem?
The dropped calls come from the webhook/SIP bridge layer collapsing under load. SignalWire replaces that layer with carrier-grade SIP session management built on FreeSWITCH, the same engine that handles trillions of minutes globally.
What enterprise features are included?
Call recording with consent management, HIPAA compliance under a single BAA, blind and attended transfers, and fallback routing to human agents. It also includes TCPA consent tracking and audit-ready compliance logging.
What does it cost?
Voice AI processing starts at $0.16 per minute. Phone numbers and SIP trunking at carrier rates. No per-feature surcharges.
Trusted by 2,000+ companies
Your AI Deserves Infrastructure That Does Not Collapse.
Stop losing production calls to webhook failures. Put carrier-grade telephony underneath your Realtime API integration.