An enterprise AI-powered phone receptionist that answers calls 24/7, checks real-time availability, books appointments on Google Calendar, and sends instant SMS confirmations via Twilio β powered by Django, Claude AI (Anthropic), Vapi, and PostgreSQL.
- What It Does
- Architecture & Call Flow
- Tech Stack
- Quick Start Guide
- Project Layout & Endpoints
- Django Admin & Telemetry
- Production Deployment
- Author & Community
- License
- π 24/7 Inbound Voice Calls: Answers phone calls with ultra-low latency, human-like voice synthesis.
- π Real-Time Calendar Sync: Dynamically checks Google Calendar for conflict-free availability.
- β‘ Autonomous Booking: Locks in appointments and auto-generates Google Calendar events.
- π± Instant SMS Verification: Dispatches booking confirmations and reminders via Twilio SMS.
- π Audit & Call Logs: Persists full call transcripts, duration, summaries, and patient data into PostgreSQL.
Vapi is leveraged as the voice transport layer (Speech-to-Text and Text-to-Speech), while the Django backend acts as the autonomous decision brain driving Claude AI function calling and tool execution.
sequenceDiagram
autonumber
actor Caller as π€ Caller
participant Vapi as ποΈ Vapi (STT/TTS)
participant Django as π Django Backend
participant Claude as π€ Claude AI (Anthropic)
participant GCal as π
Google Calendar
participant Twilio as π¬ Twilio SMS
participant DB as ποΈ PostgreSQL
Caller->>Vapi: Speaks ("I want to book an appointment")
Vapi->>Django: POST /api/vapi/chat/completions/ (Transcript)
Django->>Claude: Prompt + Tool Definitions + History
Claude-->>Django: Tool Call: check_calendar_availability
Django->>GCal: Query busy/free slots
GCal-->>Django: Available slots returned
Django->>Claude: Tool Response (Slots)
Claude-->>Django: Natural Voice Response
Django->>DB: Log conversation turns
Django-->>Vapi: Synthesized Text Reply
Vapi-->>Caller: Speaks response back to caller
Note over Caller,DB: Once confirmed: GCal Event Created & Twilio SMS Sent!
| Component | Technology | Purpose |
|---|---|---|
| Backend Core | Django 5.0, DRF | Application server, tool orchestration, admin interface |
| LLM & Reasoning | Claude API (Anthropic) | Context understanding, conversation flow, agentic tool execution |
| Voice Transport | Vapi AI | Telephony integration, real-time STT (Deepgram) & TTS (ElevenLabs/PlayHT) |
| Database | PostgreSQL 16 | Relational storage for call logs, appointments, and audit trails |
| Calendar API | Google Calendar API v3 | Service-account-driven schedule queries and event creations |
| Messaging | Twilio SMS API | Automated booking confirmations sent directly to callers |
| Containerization | Docker & Docker Compose | Multi-container local orchestration |
git clone https://github.com/codewithmuh/ai-voice-agent.git
cd ai-voice-agent
cp .env.example .envpython3 -c "import secrets; print(secrets.token_urlsafe(50))"Paste the output into .env as the SECRET_KEY value.
SECRET_KEY=your-generated-secret-key
DEBUG=True
ALLOWED_HOSTS=localhost,127.0.0.1,0.0.0.0,*
DB_NAME=ai_receptionist
DB_USER=postgres
DB_PASSWORD=postgres
DB_HOST=db
DB_PORT=5432
ANTHROPIC_API_KEY=sk-ant-...
VAPI_API_KEY=...
GOOGLE_CALENDAR_CREDENTIALS=google-calendar-credentials.json
GOOGLE_CALENDAR_ID=your-calendar-id@group.calendar.google.com
TWILIO_ACCOUNT_SID=AC...
TWILIO_AUTH_TOKEN=...
TWILIO_PHONE_NUMBER=+1...Where to get keys:
- Anthropic: console.anthropic.com
- Vapi: dashboard.vapi.ai
- Twilio: twilio.com/console
- Google Calendar: Follow setup below
- Go to Google Cloud Console.
- Click Select a Project β New Project β Name it β Create.
- Go to APIs & Services β Library.
- Search for "Google Calendar API" β Click Enable.
- Go to APIs & Services β Credentials.
- Click + Create Credentials β Service Account.
- Name it (e.g.
calendar-bot) β Create and Continue β Done. - Click the newly created service account β Keys tab β Add Key β Create New Key β JSON.
- Save the file in the project root as
google-calendar-credentials.json.
- Copy the
client_emailfromgoogle-calendar-credentials.json(e.g.calendar-bot@project.iam.gserviceaccount.com). - In Google Calendar, click your calendar settings β Share with specific people or groups.
- Add the service account email and give permission: Make changes to events.
docker compose up --buildDjango will start at http://localhost:8000 with PostgreSQL connected.
docker compose exec web python manage.py createsuperuserngrok http 8000Copy the forwarding HTTPS URL (https://xxxx.ngrok-free.app).
- Go to Vapi Dashboard.
- Create an Assistant β Set Model to Custom LLM:
https://xxxx.ngrok-free.app/api/vapi/chat/completions/ - Set Server URL (for post-call summary webhooks):
https://xxxx.ngrok-free.app/api/vapi/webhook/ - Assign a phone number and dial to test!
ai-voice-agent/
βββ receptionist_project/
β βββ settings.py # Django config
β βββ urls.py # Root URL routing
βββ calls/
β βββ models.py # CallLog & Appointment schema
β βββ views.py # Custom LLM & Vapi webhook endpoints
β βββ urls.py # API route definitions
β βββ admin.py # Django admin registration
β βββ agent/
β β βββ receptionist.py # Claude agentic loop orchestrator
β β βββ tools.py # Tool schemas (Calendar, SMS, DB)
β β βββ prompts.py # Domain system prompt
β βββ services/
β βββ calendar.py # Google Calendar API integration
β βββ sms.py # Twilio SMS client
β βββ database.py # Database operations
βββ docker-compose.yml
βββ Dockerfile
βββ .env.example
βββ requirements.txt
| Endpoint | Method | Description |
|---|---|---|
/api/vapi/chat/completions/ |
POST |
Custom LLM bridge connecting Vapi voice requests to Claude |
/api/vapi/webhook/ |
POST |
Receives end-of-call telemetry, saving summaries to DB |
/api/vapi/webhook/ |
GET |
Health check endpoint |
Access the admin dashboard at http://localhost:8000/admin/:
- Call Records: Full transcripts, duration, caller phone numbers, and LLM sentiment.
- Appointments: View, modify, or cancel bookings synced with Google Calendar.
- Filters: Quickly filter calls and appointments by date, status, and patient name.
Deploy easily on platforms like Railway, AWS EC2, or Render:
# Example with Railway CLI
railway init
railway add --plugin postgresql
railway upSet environment variables in your cloud provider's dashboard and update the Vapi webhook URLs accordingly.
Muhammad Rashid β AI & DevOps Engineer, AWS Community Builder.
- π₯ YouTube: @codewithmuh
- πΌ LinkedIn: Muhammad Rashid
- π Website: codewithmuh.com Β· devopsbymuh.com
β If you find this AI Voice Agent helpful, please give it a star!
This project is licensed under the MIT License.