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
lkCLI 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.txtWindows 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.txtCopy .env.example to .env.local and fill in the values:
LIVEKIT_URLLIVEKIT_API_KEYLIVEKIT_API_SECRETOPENAI_API_KEYDEEPGRAM_API_KEYSIP_OUTBOUND_TRUNK_ID(from steps below)
You can also populate LiveKit variables via CLI:
lk app envDownloads/caches VAD model to avoid a cold start on first run:
python3 agent.py download-filespython3 agent.py healthcheckpython3 agent.py devNow 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.jsontooutbound-trunk.jsonand 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
SIPTrunkIDfrom the response into.env.localasSIP_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 listlk sip outbound listlk 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-filesto 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