What You Are Actually Building When You Build It Yourself
Vendor evaluation takes months
STT, TTS, LLM, and telephony providers each require proof-of-concept testing. Two to three months pass before you write any integration code.
Distributed state is the hard problem
Race conditions, zombie calls, double updates. Conversation context scattered across four independent systems with no shared state model.
Error recovery across vendors
When one vendor in a five-vendor chain fails, your code handles the fallback. Each failure mode requires its own mitigation path.
Observability requires correlation
Four or five dashboards, each showing a partial picture. Building unified monitoring and correlated logs is a project unto itself.
Compliance surface multiplies
PCI scope reduction, data isolation, and audit logging must happen across every vendor independently. One audit surface becomes five.
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();
DIY Stack vs. One Platform
DIY (6 Vendors)
✗ Telephony provider for numbers and PSTN
✗ Separate STT provider with its own SDK
✗ Separate TTS provider with its own SDK
✗ LLM provider with token-based billing
✗ Your glue code managing state across all four
✗ 16 to 23 months before a production call
SignalWire (1 Platform)
✓ Telephony, STT, TTS, and LLM in one platform
✓ AI runs inside the media stack, not outside it
✓ State management is platform-native
✓ 800-1200ms typical response latency
✓ One vendor, one invoice, one escalation path
✓ Production calls in four to six weeks
Monthly Cost at 10,000 Minutes
Component
DIY Stack
SignalWire
Transport (PSTN/SIP)
$700-1,500
Carrier rates (separate)
STT provider
$400-800
Included
LLM provider
$1,000-4,000+
Included
TTS provider
$500-2,000
Included
Infrastructure
$500-1,500
$50-200 (your agent hosting)
Engineering (2-3 FTEs maintaining glue)
$40,000-75,000
$0 incremental
Total
$43,100-84,800
$1,650-1,800
From Install to Production
1
Day 1: Install and build your first agent
pip install signalwire-agents. Define your agent class, add a prompt, run it. Make your first phone call to a working AI agent.
2
Weeks 1-2: Connect your business logic
Add tool functions that call your backend. Order lookups, appointment scheduling, account verification. The tools that differentiate your product.
3
Weeks 2-3: Structure conversation flow
Define steps with scoped prompts and scoped tools. Each step handles one phase of the conversation with focused context.
4
Weeks 3-4: Test and iterate
Test with real calls. Iterate on prompts and flows. Use the sandbox environment for rapid development cycles.
5
Weeks 4-6: Go live
Deploy your agent as a standard HTTP microservice. Provision phone numbers. Route calls. You are in production.
⚠️
After 18 months of infrastructure work, you have not written a single line of business logic. Every month spent on glue code is a month not spent on the features that differentiate your product.
FAQ
What happens when we need to switch LLM providers?
The platform is model-agnostic. Changing providers is a configuration update. Your agent code, tools, and tests stay the same.
What happens when we add a new language?
Update the agent configuration. The platform handles multilingual STT and TTS natively. No new vendor integrations required.
What does the compliance audit look like?
One vendor, one data flow, one audit surface. Compare that to auditing four or five independent systems with separate data handling policies.
Can we migrate incrementally?
Yes. Start with telephony replacement and add platform capabilities at your own pace. Each phase delivers value independently.
What is the SLA story?
One platform, one SLA, one escalation path. No finger-pointing between vendors when something breaks at 2am.
Trusted by 2,000+ companies
Ship your first agent this week.
Build on infrastructure designed for voice AI, not assembled from six vendors.