of cost is plumbing in a typical multi-vendor model
1
bill instead of five
$0
orchestration surcharge
The Cost Stacking Problem
Four Vendors Billing Per-Minute Compounds at Scale
Orchestration costs overtake LLM costs
At 30,000 minutes per month, the middleware connecting your STT to your LLM to your TTS costs more than the LLM itself. You pay the orchestrator more than your AI provider.
Each vendor adds a per-minute surcharge
STT bills per minute. TTS bills per character. Telephony bills per minute. Orchestration adds another per-minute fee on top. These costs compound at every layer.
Hidden minimums and overage rates
Minimum monthly commitments per vendor, overage rates at 1.5 to 2x base rate, and premium charges for high concurrency. The invoice never matches the pricing page.
Billing reconciliation across systems
Matching call records across four billing systems with different cycles, formats, and usage tiers that reset independently.
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();}
What Multi-Vendor Plumbing Actually Costs
Four-Vendor Stack
STT vendor: $0.01 to $0.05/min
LLM provider: $0.01 to $0.10/min equivalent
TTS vendor: $0.02 to $0.15/min equivalent
Telephony vendor: $0.01 to $0.04/min plus number fees
Orchestration middleware: $0.05 to $0.15/min surcharge
Total: $0.10 to $0.49/min stacked
Four account managers, four support tickets, four invoices
SignalWire
Native AI: $0.16/min (STT + LLM + TTS + orchestration). Transport at carrier rates.
BYOAI mode: carrier-rate telephony, bring your own AI stack
No orchestration surcharge or middleware markup
No minimum monthly commitments
One bill, one vendor, one support channel
Monthly Cost at Scale (30,000 Minutes)
Cost Component
Four-Vendor Stack
SignalWire Native AI
Speech-to-text
$1,200
Included
LLM orchestration
$900
Included
Text-to-speech
$2,400
Included
Transport (PSTN/SIP)
$600 + number fees
Carrier rates (separate)
Orchestration middleware
$2,100
$0 (no middleware)
Monthly total
~$7,200
$4,800
Hidden Costs of Multi-Vendor Stacks
Hidden Cost
Impact
Integration maintenance
Each vendor API changes independently. Upgrades break integrations.
Debugging across boundaries
When a call fails, which vendor caused it? Hours of log correlation.
Compliance multiplication
Each vendor needs a separate BAA/DPA. Each is a separate audit surface.
Vendor management
Four account managers, four support tickets, four escalation paths.
Latency stacking
Each hop adds milliseconds. More vendors means more latency per turn.
Consolidate in Under 10 Minutes
1
Install the SDK
pip install signalwire-agents. One dependency replaces the middleware layer.
2
Define your agent
Python or YAML. Your prompts, your tools, your conversation logic. No orchestration vendor.
3
Assign a phone number
Carrier-rate telephony. No separate number provider, no trunk configuration.
4
Ship and track one invoice
One bill, usage-based pricing, no minimum commitments. See what your calls actually cost.
At 30,000 minutes per month, the orchestration layer alone costs $2,100. You pay the middleware vendor more than your LLM provider for the privilege of connecting vendors together.
FAQ
What does $0.16/min include?
AI processing: speech-to-text, LLM orchestration, text-to-speech, and orchestration. Transport (PSTN, SIP) is billed separately at carrier rates. One vendor, one bill.
What if I want to keep my own LLM, STT, and TTS?
BYOAI mode provides carrier-rate telephony with call control, recording, and compliance infrastructure. No per-agent fees. No orchestration surcharges. You bring your own AI stack.
Are there minimum monthly commitments?
No. Usage-based pricing from the first minute. Volume discounts are available when your application is validated, not before.
How does SignalWire offer carrier rates?
SignalWire is the carrier infrastructure, built by the team that wrote FreeSWITCH. There is no markup on top of a third-party telephony provider because SignalWire is the telephony provider.
What about existing vendor contracts?
You can run SignalWire alongside existing providers during migration. No lock-in, no minimum terms. Test with real calls before committing.
Trusted by 2,000+ companies
Your AI Is the Hard Part. The Plumbing Should Not Be.
One vendor, one bill, no orchestration surcharge. See what your calls actually cost.