LiveKit is an open-source WebRTC platform used by 300,000+ developers handling 3+ billion real-time calls annually. Its Agents SDK (Python and Node.js) lets you build AI voice agents that join real-time rooms as participants — receiving audio from users, processing it through an STT → LLM → TTS pipeline, and speaking responses back in under 500ms. Integrated with LiveKit's SIP service, these agents can answer inbound PSTN phone calls via any SIP trunk or your existing Asterisk/FreeSWITCH PBX.
1. Voice Agent Pipeline Architecture
A LiveKit voice agent's core is the VoicePipelineAgent — a high-level abstraction that orchestrates three streaming stages:
All stages stream concurrently — first audio byte typically delivered in 400–600ms
The key innovation is streaming overlap: STT sends partial transcripts to the LLM before the user finishes speaking; the LLM streams tokens to TTS before generating a complete response; TTS begins synthesising audio before receiving all tokens. This parallel execution cuts latency from 2–4 seconds (sequential) to under 600ms in production.
2. Installation and First Voice Agent
Install the LiveKit Agents SDK with the plugins for your chosen providers:
Terminal
# Install LiveKit Agents and plugins
pip install "livekit-agents[deepgram,openai,elevenlabs,silero]~=1.0"A complete voice agent that answers questions using GPT-4o and speaks responses with ElevenLabs:
agent.py — Minimal LiveKit voice agent
import asyncio
from livekit import agents
from livekit.agents import AutoSubscribe, JobContext, WorkerOptions, cli
from livekit.agents.voice import Agent, AgentSession
from livekit.plugins import deepgram, openai, elevenlabs, silero
async def entrypoint(ctx: JobContext):
await ctx.connect(auto_subscribe=AutoSubscribe.AUDIO_ONLY)
session = AgentSession(
vad=silero.VAD.load(), # Voice Activity Detection
stt=deepgram.STT(model="nova-2"), # Speech-to-Text
llm=openai.LLM(model="gpt-4o-mini"), # Language Model
tts=elevenlabs.TTS(voice="Rachel"), # Text-to-Speech
)
await session.start(
ctx.room,
agent=Agent(
instructions="""You are a friendly customer service agent for CelloIP Technologies.
Help callers with VoIP development enquiries, pricing, and project scope.
Keep responses concise — under 3 sentences for voice delivery.
If the caller wants to speak to a human, say you will transfer them.""",
),
)
if __name__ == "__main__":
cli.run_app(WorkerOptions(entrypoint_fnc=entrypoint))3. STT / LLM / TTS Provider Comparison
LiveKit Agents supports any combination of providers. Choose based on latency, quality, cost, and data residency requirements:
STT Providers
| Provider | Latency | Quality | Self-Hostable | Best For |
|---|---|---|---|---|
| Deepgram Nova-2 | ~200ms | ★★★★★ | Cloud only | Best overall, lowest latency |
| OpenAI Whisper | ~400ms | ★★★★ | On-premise / GDPR | |
| AssemblyAI | ~250ms | ★★★★ | Cloud only | High accuracy + speaker diarisation |
| Azure Speech | ~300ms | ★★★★ | Cloud only | Enterprise / Microsoft stack |
LLM Providers
| Provider | Latency | Quality | Self-Hostable | Best For |
|---|---|---|---|---|
| OpenAI GPT-4o | ~300ms first token | ★★★★★ | Cloud only | Best reasoning + function calling |
| Anthropic Claude 3.5 Haiku | ~200ms | ★★★★★ | Cloud only | Fast, smart, safe |
| LLaMA 3 (Ollama) | ~100ms (GPU) | ★★★★ | On-premise / air-gapped GDPR | |
| Mistral 7B | ~150ms | ★★★★ | EU data residency, fast inference |
TTS Providers
| Provider | Latency | Quality | Self-Hostable | Best For |
|---|---|---|---|---|
| ElevenLabs Turbo v2 | ~200ms | ★★★★★ | Cloud only | Most natural voice quality |
| Cartesia Sonic | ~100ms | ★★★★★ | Cloud only | Lowest latency TTS |
| OpenAI TTS-1-HD | ~300ms | ★★★★ | Cloud only | Simple + high quality |
| Coqui TTS / Piper | ~150ms | ★★★ | Free, self-hosted |
4. Key Agent Capabilities
Semantic Turn Detection
Transformer-based model detects when the user is genuinely done speaking — not just paused. Dramatically reduces false interruptions vs simple VAD silence detection. Built into livekit-agents 1.x as the default turn detector.
Streaming STT→LLM→TTS
All three stages run concurrently in a streaming pipeline. STT streams partial transcripts to LLM; LLM streams tokens to TTS; TTS begins generating audio before full LLM response. First audio byte under 500ms in optimal conditions.
Tool / Function Calling
Agents can call external tools mid-conversation: CRM lookup (Salesforce, HubSpot), database queries, calendar booking (Google Calendar), REST APIs, and MCP (Model Context Protocol) servers. LLM decides when to call which tool.
Interruption Handling
When the user speaks while the agent is talking, VAD detects barge-in. The agent gracefully stops TTS playback, discards queued audio, and re-enters listening state. interruption_min_words parameter prevents premature stops on short utterances.
Multi-language Support
Automatic language detection with Deepgram or Azure STT. Agents can detect mid-call language switch and reconfigure STT/TTS providers on-the-fly. LiveKit supports building multilingual agents that switch languages without call restart.
DTMF + Fallback IVR
Handle keypress input when speech fails. Agent listens for DTMF events (0-9, *, #) as a fallback when speech confidence is low. Useful for call centre menus, PIN entry, and legacy callers who prefer keypress navigation.
5. Function / Tool Calling — CRM + SIP Transfer
Agents become truly useful when they can act on information — looking up customer records, booking appointments, or transferring calls. The @function_tool decorator registers a Python function that the LLM can call:
tools.py — CRM lookup + SIP REFER transfer
# Add function/tool calling — CRM lookup example
from livekit.agents import function_tool
from livekit.agents.voice import Agent, AgentSession
@function_tool
async def lookup_account(phone_number: str) -> str:
"""Look up customer account by phone number."""
# Replace with real CRM API call
customer = await crm_api.get_customer(phone=phone_number)
if customer:
return f"Found account: {customer.name}, Plan: {customer.plan}"
return "No account found for this number."
@function_tool
async def transfer_to_human(department: str) -> str:
"""Transfer caller to a human agent in the specified department."""
# Trigger SIP REFER transfer back to Asterisk
await sip_client.transfer_participant(
room_name=ctx.room.name,
participant_identity="phone_caller",
transfer_to=f"sip:+1800{department}@asterisk.company.com"
)
return f"Transferring to {department} team now."
# Pass tools to agent
session = AgentSession(
vad=silero.VAD.load(),
stt=deepgram.STT(model="nova-2"),
llm=openai.LLM(model="gpt-4o"),
tts=elevenlabs.TTS(voice="Rachel"),
tools=[lookup_account, transfer_to_human],
)6. Handling Inbound SIP / PSTN Calls
To accept real phone calls, configure a SIP inbound trunk in LiveKit and create dispatch rules that route incoming calls to your agent workers:
Cloud SIP Carrier Setup
- 1.Create LiveKit inbound SIP trunk via API
- 2.Add DID numbers (+15551234567)
- 3.Point carrier SIP trunk to LiveKit SIP service
- 4.Create dispatch rule: DID → room prefix
- 5.Deploy agent worker — it auto-joins new rooms
Asterisk PBX Bridge
- 1.Create SIP peer in Asterisk pjsip.conf
- 2.Define extension routing to LiveKit SIP
- 3.Create LiveKit inbound trunk for Asterisk IP
- 4.Set dispatch rule for Asterisk DID range
- 5.Agent handles call; SIP REFER returns to Asterisk
Production note: Always configure IP allowlisting on your LiveKit SIP trunk to restrict signalling to known carrier/PBX IP addresses. Use SIP digest authentication and enforce TLS for signalling + SRTP for media in production deployments.
7. Self-Hosted Stack for GDPR / HIPAA Compliance
All LiveKit components are open source and self-hostable. For EU data residency or healthcare deployments, CelloIP recommends a fully on-premise AI stack:
LiveKit Server
→ Self-hosted K8s Helm chart
STT (Deepgram)
→ faster-whisper or whisper.cpp
LLM (GPT-4o)
→ Ollama + LLaMA 3 / Mistral
TTS (ElevenLabs)
→ Piper / Coqui TTS