Haris Ullah Khan published an open-source LiveKit chained voice pipeline demo (Deepgram STT → OpenAI LLM + tools → ElevenLabs TTS) with a Next.js frontend and FastAPI backend. Clone https://github.com/HarrixK/VoiceAI-Frontend and https://github.com/HarrixK/VoiceAI-Backend, add your API keys, and run a Luma Bistro reservation agent locally in minutes.
Teams learning voice AI often ask for a minimal but real template: not a slide deck, not a hosted SaaS — something they can clone, plug keys into, and hear a tool-calling agent on a LiveKit room.
I published two public repos that do exactly that:
- VoiceAI-Backend — FastAPI control plane + LiveKit agent worker
- VoiceAI-Frontend — Next.js browser UI that joins the room and plays remote audio
Together they implement a chained (cascaded) voice pipeline for a restaurant booking persona — Luma Bistro / host Maya Rivera.
What “chained modeling” means here
Browser (Next.js)
→ POST /api/v1/livekit/sessions → FastAPI :8080
→ LiveKit Cloud room
↑ worker: Deepgram STT → OpenAI LLM + tools → ElevenLabs TTS
tools → HTTP → same backend (mock /availability + /reservations)| Stage | Role | Provider in this demo |
|---|---|---|
| Media | WebRTC rooms + agent join | LiveKit |
| STT | Speech → text | Deepgram |
| LLM + tools | Reasoning, booking tools | OpenAI |
| TTS | Text → speech | ElevenLabs |
| API | Sessions + mock reservations | FastAPI |
Each hop is explicit. That is why assessments and teaching favor cascades: you can measure STT latency, tool success, and TTS time separately. It is also why cascades feel slower than speech-to-speech (Hume, Cartesia, etc.) in production sales calls — I discuss that trade-off in LiveKit vs Retell and the Use Cortana voice architecture post.
Clone and run
1. Backend (VoiceAI-Backend)
git clone https://github.com/HarrixK/VoiceAI-Backend.git
cd VoiceAI-Backend
python3 -m venv venv
source venv/bin/activate # Windows: .\venv\Scripts\Activate.ps1
pip install -r requirements.txt
cp .env.example .envSet at least:
LIVEKIT_URL,LIVEKIT_API_KEY,LIVEKIT_API_SECRETOPENAI_API_KEYDEEPGRAM_API_KEYELEVENLABS_API_KEY
Then:
python main.py
# API: http://0.0.0.0:8080
# Docs: http://localhost:8080/docs
# Health: GET /api/v1/healthWith START_LIVEKIT_WORKER=1 (default in the example), the API spawns the LiveKit worker for you.
2. Frontend (VoiceAI-Frontend)
git clone https://github.com/HarrixK/VoiceAI-Frontend.git
cd VoiceAI-Frontend
npm install
cp .env.local.example .env.local
# NEXT_PUBLIC_LUMA_API_BASE=http://localhost:8080
npm run devOpen http://localhost:5173 → Start call → allow mic.
Expect status roughly: creating session → connected → agent joined → agent speaking. A 2:00 call timer starts when remote agent audio plays (matches backend MAX_CALL_SECONDS).
Reset seed data between scenarios:
curl -X POST http://127.0.0.1:8080/admin/resetFull smoke steps and layout notes live in each repo README — frontend · backend.
What the agent demonstrates
This is a demo / assessment stack (in-memory mock reservations, not a production deploy), but the voice patterns are real:
- Confirm-before-write — tools require
confirmed=truebefore mutating bookings - Idempotency-Key + duplicate fingerprints — safe retries on create
- 503 once then recover — temporary availability failure with client retry
- Idle nudges — if the user is quiet ~4 seconds, the agent prompts again
- 2-minute hard cap — keeps demo costs and sessions bounded
- Mock handoff — spoken transfer line via
POST /handoff
Automated T1–T7 scenarios (create, unavailable time, barge-in party size, modify, cancel, API failure, duplicates) are documented in the backend README. Offline pytest hits the mock API in-process; the live tool harness needs the server running.
When to use this vs speech-to-speech
| Use this cascade template when… | Prefer speech-to-speech when… |
|---|---|
| You need inspectable STT / LLM / TTS stages | Callers notice cascade delay |
| Tool calling and eval harnesses are the point | Emotion / prosody should drive replies (e.g. Hume) |
| Teaching or assessing chained modeling | Production speed-to-lead is the product |
I chose the cascade because the assignment required chained modeling. In client work I often migrate cascades to Hume speech-to-speech once latency shows up in conversion — while keeping the same studio and Twilio wiring. See production voice at Use Cortana.
Repo map
| Repo | Stack | Role |
|---|---|---|
| HarrixK/VoiceAI-Backend | FastAPI, LiveKit Agents, Deepgram, OpenAI, ElevenLabs | Sessions, worker, mock reservations, eval harness |
| HarrixK/VoiceAI-Frontend | Next.js 15, livekit-client | Start/end call UI, remote audio, call timer |
Assessment docs (architecture answers, evaluation results, AI tools disclosure, handover) ship with the frontend repo.
Related work
Common questions
What is a chained voice AI pipeline?
A cascaded (chained) voice pipeline runs speech-to-text, then an LLM with tools, then text-to-speech as separate stages — here Deepgram → OpenAI → ElevenLabs over LiveKit WebRTC. Each stage is measurable and controllable, at the cost of more end-to-end latency than speech-to-speech.
Where are the open-source repos?
Frontend: https://github.com/HarrixK/VoiceAI-Frontend (Next.js + livekit-client). Backend: https://github.com/HarrixK/VoiceAI-Backend (FastAPI + LiveKit agent worker + mock reservation API). Both are public.
What do I need to run the demo?
Node.js 18+, Python 3.11+, and API keys for LiveKit Cloud, OpenAI, Deepgram, and ElevenLabs. Clone both repos, copy .env.example / .env.local.example, start the backend on :8080, then npm run dev on the frontend (:5173).
Why chained modeling instead of speech-to-speech?
This demo was built where chained modeling was required. Cascades make STT/LLM/TTS stages and tool discipline easy to inspect and evaluate. For production latency and emotion-aware dialog, Haris often prefers speech-to-speech (e.g. Hume EVI) — see the Use Cortana architecture case study.
What does the demo agent do?
Maya Rivera, a Luma Bistro host, books and modifies restaurant reservations via tools against a mock FastAPI reservation API — availability checks, create/update/cancel with confirm-before-write, idempotency, and a spoken handoff path. Call cap is two minutes for demo use.
Who built this LiveKit voice template?
Haris Ullah Khan (https://harisullahkhan.me) — production LiveKit/Twilio/Hume stacks at Use Cortana and VoiceCake. Hire at https://harisullahkhan.me/hire-voice-ai-developer.