A comprehensive AI-powered interview system combining real-time video conferencing, AI interviewer agent, proctoring, and violation tracking.
This project implements an end-to-end AI interviewing platform that:
- Schedules interviews with candidates
- Extracts resume content and generates interview questions using AI (OpenAI GPT)
- Conducts real-time video interviews with an AI agent using LiveKit
- Monitors candidate behavior (head tracking, tab switching, copy/paste attempts, fullscreen enforcement)
- Records violation logs in JSON format for later review
- Provides a web-based UI (Streamlit) for scheduling and Next.js for the interview experience
AI_Interview_Agent/
βββ generate_token.py # FastAPI backend - handles interview scheduling, room creation, token generation
βββ agent.py # LiveKit AI Agent - conducts the actual interview
βββ utils.py # Utility functions for resume extraction & interview plan generation
βββ streamlit_app.py # Streamlit web UI for scheduling interviews
βββ requirements.txt # Python dependencies
β
βββ meet/ # Next.js frontend - interview experience
β βββ app/
β β βββ api/ # Next.js API routes
β β β βββ connection-details/ # Endpoint to get LiveKit credentials
β β β βββ save-interview-log/ # Endpoint to save violation logs
β β β βββ log-violations/ # (Legacy) endpoint for violation logging
β β βββ eye-test/ # Proctoring components
β β β βββ EyeTestClient.tsx # Dynamic import wrapper for head tracking
β β β βββ EyeTestInner.tsx # Head movement detection using TensorFlow
β β β βββ BrowserProctor.tsx # Tab/window/copy-paste/fullscreen enforcement
β β β βββ page.tsx # Standalone demo page
β β βββ rooms/[roomName]/ # Interview room
β β β βββ page.tsx # Room page
β β β βββ PageClientImpl.tsx # Main interview UI (LiveKit + Proctoring)
β β βββ layout.tsx
β βββ lib/
β β βββ usePerfomanceOptimiser.ts # Performance optimization for video
β β βββ useSetupE2EE.ts # End-to-end encryption setup
β β βββ KeyboardShortcuts.tsx # Keyboard navigation
β β βββ SettingsMenu.tsx # Camera/mic settings
β β βββ types.ts # TypeScript type definitions
β βββ package.json
β βββ next.config.js
β
βββ interview-logs/ # (Generated) JSON violation logs
β βββ {interviewId}_violations.json
β
βββ resumes/ # (Generated) Uploaded candidate resumes
β βββ {candidate_name}_{filename}
β
βββ .env.local # Environment variables (NOT in git)
- FastAPI - REST API for interview scheduling and room management
- LiveKit API - Real-time communication (video/audio)
- OpenAI GPT - Resume analysis and interview question generation
- Uvicorn - ASGI server
- Streamlit - Lightweight web UI for admin/scheduling
- Next.js 15 - React framework with App Router
- TypeScript - Type safety
- LiveKit Client SDK - Video conferencing components
- TensorFlow.js - Client-side face detection for head tracking
- MediaPipe - Face landmark detection for proctoring
- LiveKit Cloud - Video conferencing infrastructure (requires account & API keys)
- OpenAI API - LLM for resume analysis and interview questions
- Node.js 18+ (for Next.js)
- Python 3.9+
- LiveKit Account (get API keys from livekit.io)
- OpenAI API Key (get from openai.com)
# Backend dependencies
pip install -r requirements.txt
# Frontend dependencies
cd meet
npm install
cd ..Create .env.local in the ob_agent/ directory:
# LiveKit Configuration
LIVEKIT_URL=wss://your-livekit-url.livekit.cloud
LIVEKIT_API_KEY=your_api_key
LIVEKIT_API_SECRET=your_api_secret
# OpenAI Configuration
OPENAI_API_KEY=sk-your-openai-key-here
# Optional: Langfuse (for monitoring)
LANGFUSE_PUBLIC_KEY=your_langfuse_public_key
LANGFUSE_SECRET_KEY=your_langfuse_secret_keyTerminal 1 - FastAPI Backend (Port 8000)
python generate_token.pyTerminal 2 - Next.js Frontend (Port 3000)
cd meet
npm run devTerminal 3 - Streamlit UI (Port 8501) [Optional]
streamlit run streamlit_app.pyTerminal 4 - AI Agent Worker
python agent.py- Candidate submits name, email, resume
- Backend (
generate_token.py) processes request:- β
Saves resume to
resumes/folder - β Extracts resume text using pdfplumber/python-docx
- β Generates interview plan & questions using OpenAI GPT
- β Creates LiveKit room
- β Returns room name and token
- β
Saves resume to
- Candidate joins via Next.js UI at
localhost:3000/rooms/{roomName} - Frontend (
PageClientImpl.tsx):- Connects to LiveKit room using server token
- Starts head tracking (
EyeTestInner) - detects:- Face not detected
- Face partially covered
- Not looking at screen
- Head not straight
- Starts browser monitoring (
BrowserProctor) - detects:- Copy/Paste attempts
- Tab switching
- Window switching
- Fullscreen exit
- Tracks violations with timestamps in state
- All violations logged to console
Proctoring_Video.mp4
- Backend (
agent.py):- LiveKit agent joins room
- Waits for participant
- Conducts real-time conversation using OpenAI Realtime Model
- Asks prepared interview questions
- Follows system instructions (professional interviewer)
- Frontend collects violations as they occur:
{ "count": 1, "time": "00:03", "warning": "face not detected" } - De-duplicated - same violation only logged once per 2 seconds
- Stored in React state with timestamps relative to interview start
- When candidate leaves room (room disconnects):
- Frontend compiles final log:
{ "interviewId": "interview-abc123xyz", "startTime": "2026-02-04T10:30:00Z", "endTime": "2026-02-04T10:40:00Z", "duration": "10:00", "violations": [ { "count": 1, "time": "00:03", "warning": "face not detected" }, { "count": 2, "time": "00:05", "warning": "copy/paste" }, { "count": 3, "time": "00:08", "warning": "tab switched" } ] } - Sends to backend via
/api/save-interview-log - Backend saves as JSON to
interview-logs/{interviewId}_violations.json
- Frontend compiles final log:
βββββββββββββββ
β Candidate β
ββββββββ¬βββββββ
β
βΌ
ββββββββββββββββββββββββββββββββββββββββ
β Streamlit Scheduling UI β
β (streamlit_app.py) β
β - Resume upload β
β - Schedule interview β
ββββββββββββ¬ββββββββββββββββββββββββββ¬ββ
β β
βΌ βΌ
ββββββββββββββββββββ ββββββββββββββββββ
β Resume File β β FastAPI Calls β
β (resumes/) β β /api/get-tokenβ
ββββββββββββββββββββ ββββββββββ¬ββββββββ
β
βββββββββββββββββΌβββββββββββββββββ
β generate_token.py β
β - Extract resume (utils.py) β
β - Generate plan (OpenAI) β
β - Create LiveKit room β
β - Return credentials β
βββββββββββββββββ¬βββββββββββββββββ
β
βββββββββββββββββΌβββββββββββββββββ
β Next.js Frontend β
β /rooms/{roomName} β
β - LiveKit video β
β - Head tracking (EyeTest) β
β - Browser monitoring (Proctor)β
β - Collect violations β
βββββββββββββββββ¬βββββββββββββββββ
β
βββββββββββββββββΌβββββββββββββββββ
β β β
βΌ βΌ βΌ
βββββββββββββββ ββββββββββββββββ ββββββββββββββββ
β LiveKit API β β OpenAI API β β Browser β
β Video/Audio β β Conversation β β Monitoring β
βββββββββββββββ ββββββββββββββββ ββββββββββββββββ
β β β
βββββββββββββββββΌβββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββ
β Violation Log (React state) β
β + Interview metadata β
βββββββββββββββββ¬ββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββ
β /api/save-interview-log β
β (Next.js API Route) β
βββββββββββββββββ¬ββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββ
β generate_token.py β
β /api/save-interview-log β
β Save to file β
βββββββββββββββββ¬ββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββ
β interview-logs/ β
β {interviewId}_violations.jsonβ
βββββββββββββββββββββββββββββββββ
| Item | Location | Format | When |
|---|---|---|---|
| Resume | resumes/{candidateName}_{filename} |
PDF/DOCX | Uploaded during scheduling |
| Interview Plan | In-memory (INTERVIEW_CACHE) | JSON | Generated from resume |
| Violation Log | interview-logs/{interviewId}_violations.json |
JSON | Interview ends |
| Interview Metadata | In-memory (INTERVIEW_CACHE) | JSON | Interview scheduled |
| Feedback | In-memory (INTERVIEW_FEEDBACK) | JSON | Posted after interview |
- Endpoints:
POST /api/get-token- Schedule interview, create room, generate tokenPOST /api/interview-feedback- Record interview feedbackGET /api/interview-status/{room_name}- Check interview statusGET /api/interviews- List all interviewsPOST /api/save-interview-log- Save violation logDELETE /api/interview/{room_name}- Delete interview record
- Connects to LiveKit room
- Waits for participant
- Conducts real-time conversation
- Uses OpenAI Realtime Model for natural dialogue
- Follows interview instructions
-
Violation Tracking State:
violations- Array of { count, time, warning }interviewStartTime- Ref to interview start timestampaddViolation()- Callback to record violations
-
Child Components:
EyeTestClientβEyeTestInner- Head tracking with TensorFlowBrowserProctor- Tab/window/copy-paste/fullscreen monitoring
-
EyeTestInner.tsx - Uses TensorFlow.js + MediaPipe
- Detects face landmarks
- Calculates head rotation (yaw) and tilt (pitch)
- Calls
onViolation()when thresholds exceeded
-
BrowserProctor.tsx - Browser API monitoring
visibilitychange- Tab switchingblur- Window switchingcopy/cut/paste- Clipboard attemptsfullscreenchange- Fullscreen exit
# REQUIRED - LiveKit
LIVEKIT_URL=wss://your-domain.livekit.cloud
LIVEKIT_API_KEY=APIxxxx
LIVEKIT_API_SECRET=secrets...
# REQUIRED - OpenAI
OPENAI_API_KEY=sk-proj-xxxxx
# OPTIONAL - Monitoring
LANGFUSE_PUBLIC_KEY=pk_xxxx
LANGFUSE_SECRET_KEY=sk_xxxx
# OPTIONAL - Backend URL (for Next.js to call backend)
NEXT_PUBLIC_BACKEND_URL=http://localhost:8000- Start all services (backend, frontend, agent)
- Go to Streamlit UI:
localhost:8501 - Upload resume and schedule interview
- Join interview in Next.js:
localhost:3000 - To trigger violations:
- Head tracking: Move head side-to-side or tilt up/down
- Tab switch: Press Alt+Tab
- Copy/Paste: Try Ctrl+C/V (will be blocked)
- Window: Click outside browser
- Leave interview
- Check
interview-logs/folder for JSON file
# Backend logs (terminal where generate_token.py runs)
# Shows: Room creation, token generation, violations saved
# Frontend console (browser DevTools)
# Shows: Violation tracking console logs
# Format: [Violation N] MM:SS - violation_name-
No head-tracking warnings?
- Check browser console for errors
- Ensure camera permissions granted
- Verify TensorFlow model loading
-
Violations not saving?
- Check if backend
/api/save-interview-logis called - Verify
interview-logs/directory exists - Check backend console for errors
- Check if backend
-
Agent not speaking?
- Check
agent.pyis running - Verify OpenAI API key is valid
- Check LiveKit logs for agent connection
- Check
Future enhancement: Add Dockerfile for containerized deployment.
POST http://localhost:8000/api/get-token
Content-Type: multipart/form-data
participant: "John Doe"
email: "john@example.com"
scheduled_time: "2026-02-05T10:00:00Z"
resume: <file>Response:
{
"interviewId": "interview-abc123",
"serverUrl": "wss://livekit.cloud",
"participantToken": "token...",
"plan": { "summary": "...", "questions": [...] }
}POST http://localhost:8000/api/save-interview-log
Content-Type: application/json
{
"interviewId": "interview-abc123",
"startTime": "2026-02-04T10:30:00Z",
"endTime": "2026-02-04T10:40:00Z",
"duration": "10:00",
"violations": [
{ "count": 1, "time": "00:03", "warning": "face not detected" }
]
}Future contributors should:
- Follow existing code structure
- Update this README if adding new features
- Ensure all environment variables are documented
- Test both frontend and backend
For issues or questions:
- Check the Troubleshooting section above
- Review console logs (browser + terminal)
- Verify environment variables are set correctly
- Check LiveKit dashboard for room/participant info