Build and run a voice agent that makes outbound PSTN calls using LiveKit. This example wires up VAD, STT, LLM, and TTS into a Voice Pipeline and includes a small CLI for local development, health checks, and model prewarming.
- Voice Pipeline with Silero VAD, Deepgram STT, OpenAI LLM + TTS
- Outbound PSTN calls via LiveKit SIP Outbound Trunks
- Callable tools for call control and basic appointment flows
- Simple CLI:
dev
,healthcheck
,download-files
,prewarm
- Python 3.10+
- LiveKit Cloud project and
lk
CLI installed - Accounts/API keys for OpenAI and Deepgram
Run the following commands to clone, create a virtual environment, and install dependencies.
git clone https://github.com/tetratensor/LiveKit-Outbound-Caller-Voice-Agent.git
cd LiveKit-Outbound-Caller-Voice-Agent
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
Windows instructions (click to expand)
:: Windows (CMD/PowerShell)
git clone https://github.com/tetratensor/LiveKit-Outbound-Caller-Voice-Agent.git
cd LiveKit-Outbound-Caller-Voice-Agent
python -m venv venv
venv\Scripts\activate
pip install -r requirements.txt
Copy .env.example
to .env.local
and fill in the values:
LIVEKIT_URL
LIVEKIT_API_KEY
LIVEKIT_API_SECRET
OPENAI_API_KEY
DEEPGRAM_API_KEY
SIP_OUTBOUND_TRUNK_ID
(from steps below)
You can also populate LiveKit variables via CLI:
lk app env
Downloads/caches VAD model to avoid a cold start on first run:
python3 agent.py download-files
python3 agent.py healthcheck
python3 agent.py dev
Now the worker is running and waiting for dispatches to make outbound calls.
- Create a Twilio account
- Get a Twilio phone number
- Create a SIP trunk
- Twilio Console → Explore products → Elastic SIP Trunking → SIP Trunks → Get started → Create a SIP Trunk
- Configure SIP Termination
- Termination → enter a Termination SIP URI
- Create Credentials List (friendly name, username, password)
- Copy
outbound-trunk-example.json
tooutbound-trunk.json
and update with your SIP provider credentials. Do not commit this file.name
: Any friendly nameaddress
: Your provider's Termination SIP URInumbers
: Your Twilio phone number to call fromauth_username
: Username from your credentials listauth_password
: Password from your credentials list
- Create the trunk with the CLI:
lk sip outbound create outbound-trunk.json
- Copy the
SIPTrunkID
from the response into.env.local
asSIP_OUTBOUND_TRUNK_ID
.
With the worker running in a terminal, open another terminal and dispatch an agent to dial a number:
lk dispatch create \
--new-room \
--agent-name outbound-caller \
--metadata "+1234567890"
lk project list
lk sip outbound list
lk sip dispatch list
- Ensure all required environment variables are present: run
python3 agent.py healthcheck
. - First run may download models; use
python3 agent.py download-files
to prewarm. - For more logs, run with
--log-level DEBUG
, e.g.python3 agent.py --log-level DEBUG dev
.
python3 agent.py dev # run the worker locally
python3 agent.py healthcheck # validate required env vars
python3 agent.py download-files # pre-download/cache models (e.g., VAD)
python3 agent.py prewarm # alias to download/cache models