Contact Sales

All fields are required

Calls Are Not Jobs | SignalWire
Architecture

Your Caller Is Waiting in a Queue

LiveKit dispatches jobs to workers. SignalWire answers calls. That distinction determines whether your caller waits 50 seconds or under one.

< 1.2s
typical AI response latency
13s
LiveKit p50 dispatch delay (documented)
4 min
LiveKit p90 at 50 concurrent users
2,000+
companies on SignalWire infrastructure
The problem

Job dispatch was designed for batch processing, not phone calls

Callers wait for worker assignment

Every inbound call creates a room, evaluates dispatch rules, queues a job, selects a worker, and initializes an agent process before conversation begins. Ten steps to say hello.

Cold starts punish real callers

LiveKit Cloud shuts down deployed agents after inactivity. Developers report 10 to 20 second cold starts even on paid plans. A caller who waits that long hangs up.

Burst traffic compounds the delay

At 50 concurrent users on the Scale plan, documented p90 latency reached 245 seconds (over four minutes). LiveKit's recommendation: stagger connections with one-second delays.

WebRTC overhead on every call

Each phone call negotiates ICE candidates, STUN discovery, and track subscriptions. These solve NAT traversal for browsers, not for server-side telephony.

Build a Voice AI Agent

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()

Two architectures, one phone call

LiveKit: Job Dispatch

  • Call arrives, room created
  • Dispatch rule evaluated
  • Job created and queued
  • Worker selected from pool
  • Worker accepts job
  • Agent process initialized
  • Agent joins room
  • Track subscription established
  • Audio pipeline ready
  • Conversation begins

SignalWire: Direct Answer

  • Call arrives
  • Routed to the agent
  • Agent answers
  • Conversation begins

Documented dispatch latency at 50 concurrent users

PercentileLiveKit LatencySignalWire Latency
p5013,498ms (~13 seconds)<1200ms
p90245,331ms (~4 minutes)<1200ms
p99276,611ms (~4.6 minutes)<1200ms
At 50 concurrent users on the Scale plan, a developer documented p90 latency of 245 seconds. LiveKit's response: stagger connections with one-second delays between batches. Source: LiveKit Community Forum.
The solution

Calls as first-class objects, not jobs in a queue

Direct call answering

No job dispatch, no room creation, no track subscription. The agent answers the call. Sub-second response, every time.

One address for everything

Phone numbers, SIP endpoints, AI agents, and subscribers are all addressable the same way. No separate APIs per type.

Native telephony, no bridge

SIP and PSTN handled natively. No WebRTC bridge, no ICE candidates, no STUN discovery, no TURN relay. Media stays on the platform.

Transfers without room migration

Transfer between agents, numbers, and endpoints using standard telephony primitives. No participant migration between rooms.

Architecture comparison

AspectLiveKitSignalWire
Call modelRoom with participantsFirst-class call object
Agent modelWorker dispatched to roomAddressable endpoint
Call answeringJob dispatch (10-50s documented)Sub-second
Media transportSIP-to-WebRTC bridge + ICE/STUN/TURNNative SIP/PSTN
Cold start10-50 seconds documentedNone (HTTP server)
Burst handlingp90 of 245s at 50 concurrentHTTP endpoint scaling
TransferParticipant migration between roomsStandard telephony primitives
Transport is not the bottleneck A published analysis shows the transport layer accounts for less than 5% of total conversational latency. The bottleneck is the model, not the pipe. WebRTC adds complexity without improving voice AI performance.

Get from pip install to production calls

1

Install the SDK

pip install signalwire-agents. One package, one version, zero dependency coordination.

2

Define your agent

Inherit AgentBase, set a prompt, add skills and tools with Python decorators.

3

Point a phone number at it

Configure a SignalWire number to route to your agent. No rooms, no dispatch, no workers.

4

Deploy anywhere

The same code runs on a server, Lambda, Cloud Functions, or Azure. No platform lock-in.

FAQ

Why does LiveKit's dispatch model add so much latency?

LiveKit creates a room, evaluates dispatch rules, queues a job, assigns a worker, and initializes an agent for every call. Each step adds time. Under load, jobs queue behind each other.

Does SignalWire use WebRTC at all?

SignalWire supports WebRTC for browser-based use cases. For phone calls, media flows through the native SIP/PSTN stack with no bridge conversion.

What happens during traffic spikes?

SignalWire agents are HTTP endpoints. They scale the same way any web service scales. No job queue, no worker pool bottleneck.

Can I migrate from LiveKit incrementally?

Yes. SignalWire handles SIP trunking natively. You can route specific numbers to SignalWire agents while keeping other traffic on existing infrastructure.

Trusted by 2,000+ companies

Calls, not jobs. Sub-second, not minutes.

Build voice AI on infrastructure designed for phone calls, not job queues.