A real-time communication system that facilitates warm call transfers between agents using LiveKit and AI-powered call summaries.
This application enables seamless warm transfers where Agent A can brief Agent B about a customer call before transferring the conversation. The system uses LiveKit for real-time video/audio communication and Groq LLM for generating intelligent call summaries.
- FastAPI framework for REST API endpoints
- LiveKit Python SDK for official token generation and room management
- LiveKit API for creating/managing rooms and participants
- Groq API integration for AI-powered call summaries
- Environment-based configuration for security
- Proper participant removal for clean transfers
- Next.js 15 with TypeScript and Tailwind CSS
- LiveKit React Components for video conferencing UI
- React hooks for state management
- Responsive design for optimal user experience
- Python 3.8+
- Node.js 18+
- LiveKit account and server
- Groq API key
git clone <repository-url>
cd warm-callcd backend
# Create virtual environment
python -m venv venv
# Activate virtual environment
# Windows:
venv\Scripts\activate
# macOS/Linux:
source venv/bin/activate
# Install dependencies
pip install -r requirements.txt
# Create environment file
cp .env.example .envEdit backend/.env with your credentials:
LIVEKIT_API_KEY=your_livekit_api_key_here
LIVEKIT_API_SECRET=your_livekit_api_secret_here
LIVEKIT_URL=wss://your-livekit-server.com
GROQ_API_KEY=your_groq_api_key_here
HOST=127.0.0.1
PORT=8000cd frontend
# Install dependencies
npm install
# Create environment file
cp .env.example .env.localEdit frontend/.env.local:
NEXT_PUBLIC_LIVEKIT_URL=wss://your-livekit-server.com
NEXT_PUBLIC_API_BASE_URL=http://localhost:8000Option A: Use provided scripts
# Windows
start-dev.bat
# macOS/Linux
chmod +x start-dev.sh
./start-dev.shOption B: Manual startup
Terminal 1 (Backend):
cd backend
uvicorn main:app --reload --host 127.0.0.1 --port 8000Terminal 2 (Frontend):
cd frontend
npm run dev- Frontend: http://localhost:3000
- Backend API: http://localhost:8000
- API Documentation: http://localhost:8000/docs
Generate LiveKit access token for room participation using official LiveKit Python SDK.
Query Parameters:
room_name(string): Target room nameidentity(string): Participant identity/name
Response:
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}Features:
- β Official LiveKit SDK token generation
- β Automatic room creation if it doesn't exist
- β Proper video/audio permissions granted
- β Secure JWT signing with API credentials
List participants currently in a specific LiveKit room.
Query Parameters:
room_name(string): Target room name
Response:
{
"room": "support-room-1",
"participants": [
{ "identity": "Agent A", "name": "Agent A", "metadata": null }
]
}Notes:
- Returns an empty list (instead of 500) if listing fails to keep UI resilient.
List all active LiveKit rooms and their participants.
Response:
{
"rooms": [
{
"name": "customer-support-room-1",
"sid": "RM_abc123",
"num_participants": 2,
"creation_time": 1699123456
}
]
}Generate AI summary of call context for warm transfer.
Request Body:
{
"call_context": "Customer John Smith called about billing issue with account #12345..."
}Response:
{
"summary": "Customer John Smith is experiencing billing discrepancies...",
"id": "b1a0d5b0-0e5d-4a9c-8e76-5fd4d0c6b9e2"
}Notes:
- If
GROQ_API_KEYis missing orFORCE_MOCK_GROQ=1, returns a mock summary for local development. - Summary is persisted (SQLite) and the record ID is returned.
Finalize transfer by removing Agent A from the original room using LiveKit API.
Request Body:
{
"original_room_name": "customer-support-room-1",
"agent_a_identity": "Agent A",
"agent_b_identity": "Agent B"
}Response:
{
"success": true,
"message": "Transfer completed. Agent A removed from customer-support-room-1"
}Features:
- β Automatic participant removal via LiveKit API
- β Proper error handling for disconnection issues
- β Clean transfer completion without manual intervention
List persisted transfer summary records.
Query Parameters:
room_name(optional): Filter by roomlimit(optional int, default 50)
Response:
{
"transfers": [
{
"id": "b1a0d5b0-0e5d-4a9c-8e76-5fd4d0c6b9e2",
"room_name": "unknown",
"agent_a": "unknown",
"agent_b": null,
"summary": "Mock Summary: ...",
"call_context": "Customer ...",
"created_at": 1737050123.123
}
]
}Retrieve a single persisted transfer summary.
Response:
{
"id": "b1a0d5b0-0e5d-4a9c-8e76-5fd4d0c6b9e2",
"room_name": "unknown",
"agent_a": "unknown",
"agent_b": null,
"summary": "Mock Summary: ...",
"call_context": "Customer ...",
"created_at": 1737050123.123
}Errors:
- 404 if the record does not exist.
Generate speech (WAV) from text. If GROQ_API_KEY is set and not forced to mock, it first generates a response via Groq, then synthesizes locally with pyttsx3.
Request Body:
{ "prompt": "Say hello" }Response: audio/wav stream
Start, talk, and stop a lightweight AI agent participant. The system supports multiple agent modes:
Voice AI Agent (Full Conversational):
- Real-time Speech-to-Text (STT) using OpenAI Whisper
- Large Language Model (LLM) conversation using OpenAI GPT
- Text-to-Speech (TTS) using OpenAI voices
- Natural voice conversations with customers
- Intelligent responses and context awareness
Basic Agent (TTS Only):
- Text-to-speech output using local pyttsx3
- Agent can respond to programmatic prompts
- Real audio publishing via LiveKit RTC
Mock Agent (Testing):
- Validates control surface without media
- Logs all commands for debugging
Agent Endpoints:
- POST
/agent/start- Body:
{ "room_name": "support-1", "identity": "ai-agent" } - Ensures room exists then starts agent session for the room
- Body:
- POST
/agent/say- Body:
{ "room_name": "support-1", "text": "Welcome to support!" } - Sends a prompt to the agent (voice AI responds naturally, basic agent uses TTS)
- Body:
- POST
/agent/stop- Body:
{ "room_name": "support-1" } - Stops the agent session for that room
- Body:
Agent Configuration:
ENABLE_AGENT_MOCK=1: Use mock agent (default for testing)ENABLE_VOICE_AI=1: Enable full voice AI agent (requires OpenAI API key)ENABLE_AGENT_MOCK=0: Enable basic real agent with TTS
- Customer joins a room using any room name
- Agent A joins the same room to assist the customer
- Agent A clicks "Warm Transfer" button
- System prompts for call context input
- Agent A describes the current situation and customer needs
- System calls Groq API to generate a concise summary
- Agent A reviews the AI-generated summary
- Agent A connects with Agent B separately (via phone, chat, etc.)
- Agent A shares the summary with Agent B
- Agent B prepares to take over the call
- Agent B joins the original room with the customer
- Agent A clicks "Complete Transfer"
- System removes Agent A from the room
- Agent B continues the conversation with the customer
warm-call/
βββ backend/
β βββ main.py # FastAPI application
β βββ requirements.txt # Python dependencies
β βββ .env.example # Environment template
βββ frontend/
β βββ src/
β β βββ app/
β β β βββ page.tsx # Main landing page
β β β βββ layout.tsx # App layout
β β βββ components/
β β βββ CallRoom.tsx # Video conference component
β βββ package.json # Node.js dependencies
β βββ .env.example # Environment template
βββ .gitignore # Git ignore rules
βββ start-dev.bat # Windows startup script
βββ start-dev.sh # Unix startup script
Backend:
- FastAPI: Modern, fast web framework for Python APIs
- LiveKit Server SDK: Real-time communication infrastructure
- Groq: Fast LLM inference for call summaries
- Uvicorn: ASGI server for production deployment
Frontend:
- Next.js 15: React framework with app directory structure
- TypeScript: Type-safe JavaScript development
- Tailwind CSS: Utility-first CSS framework
- LiveKit Components: Pre-built React components for video calls
Backend (backend/.env):
LIVEKIT_API_KEY=your_livekit_api_key
LIVEKIT_API_SECRET=your_livekit_api_secret
LIVEKIT_URL=wss://your-livekit-server.com
GROQ_API_KEY=your_groq_api_key
OPENAI_API_KEY=your_openai_api_key # Required for Voice AI Agent
HOST=127.0.0.1
PORT=8000
FORCE_MOCK_GROQ=0 # Set to 1 to force mock summaries (optional)
PERSIST_DB_PATH= # Optional custom path for SQLite persistence
ENABLE_AGENT_MOCK=1 # Set to 0 to enable real agent implementation (requires livekit-agents)
ENABLE_VOICE_AI=0 # Set to 1 to enable full voice AI agent (requires OpenAI API key)Frontend (frontend/.env.local):
NEXT_PUBLIC_LIVEKIT_URL=wss://your-livekit-server.com
NEXT_PUBLIC_API_BASE_URL=http://localhost:8000- Create account at LiveKit Cloud
- Generate API key and secret
- Note your WebSocket URL
- Update environment variables
- Sign up at Groq
- Generate API key
- Update
GROQ_API_KEYin backend environment
- Sign up at OpenAI
- Generate API key
- Update
OPENAI_API_KEYin backend environment - Set
ENABLE_VOICE_AI=1to enable voice AI capabilities
The backend includes comprehensive test scripts to validate LiveKit integration:
Test Token Generation:
cd backend
python test_token_only.pyβ
Tests official LiveKit SDK token generation
β
Validates API credentials
β
Confirms token format and length
Test API Integration:
cd backend
python test_api_integration.pyβ
Tests room creation and listing
β
Validates API connectivity
β
Confirms participant management capabilities
Test Full Backend:
cd backend
python test_livekit.pyβ
Tests all API endpoints
β
Validates token endpoint responses
β
Confirms room management functionality
- Start both servers using provided scripts
- Open three browser tabs to http://localhost:3000
Tab 1 - Customer:
- Name: "Customer John"
- Room: "support-room-1"
- Click "Join Room"
Tab 2 - Agent A:
- Name: "Agent A"
- Room: "support-room-1"
- Click "Join Room"
Tab 3 - Agent B:
- Name: "Agent B"
- Room: "support-room-1"
- Wait for transfer completion
- Simulate Transfer:
- In Agent A tab, click "Warm Transfer"
- Enter call context: "Customer needs help with account billing"
- Review generated summary
- Click "Complete Transfer"
- Agent A will be removed from the call
- Agent B can now join and continue
- (Optional) Query
/transfersendpoint to view persisted summary
# Using Docker
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]# Build for production
npm run build
# Deploy to Vercel, Netlify, or similar
npm run start1. LiveKit Connection Failed
- Verify
LIVEKIT_URLis correct WebSocket URL - Check API key and secret are valid
- Ensure LiveKit server is accessible
2. Groq API Errors
- Verify
GROQ_API_KEYis set correctly - Check Groq service status
- Review API rate limits
3. CORS Issues
- Backend includes CORS middleware for localhost:3000
- Update CORS origins for production deployment
4. Token Generation Fails
- Check all LiveKit environment variables
- Verify room name and identity are provided
- Review server logs for detailed errors
5. Backend Dependencies If you encounter import errors, ensure all dependencies are installed:
cd backend
pip install -r requirements.txtKey backend packages:
livekit-api==1.0.5- Official LiveKit Python SDKfastapi==0.104.1- Web frameworkgroq==0.4.1- AI API clientpython-dotenv==1.0.0- Environment management
Your Warm Transfer application is now fully functional with:
- β Official LiveKit SDK integration
- β Real-time video/audio communication
- β AI-powered call summaries
- β Mock summary fallback for offline / keyless development
- β Proper participant management
- β Clean transfer workflows
- β Persistent storage of generated summaries
- β Comprehensive testing suite
Enjoy seamless warm transfers with live audio calls! π
Enable debug logging in backend:
import logging
logging.basicConfig(level=logging.DEBUG)- Fork the repository
- Create feature branch:
git checkout -b feature-name - Make changes with proper git commits
- Test thoroughly
- Submit pull request
This project is open source and available under the MIT License.
For issues and questions:
- Check the troubleshooting section
- Review LiveKit documentation
- Check Groq API documentation
- Create an issue in the repository
Built with β€οΈ using LiveKit, FastAPI, Next.js, and Groq