Chat-GPT: Chat Gateway for Personal Trainers.
A WhatsApp chatbot that qualifies personal training leads through conversational discovery, scores prospects against PT preferences, and automatically books intro calls for qualified leads.
- Natural Conversation: AI-powered discovery agent conducts warm, conversational lead qualification
- Smart Extraction: Automatically extracts structured data (goals, budget, location, etc.) from conversations
- Intelligent Scoring: Scores leads against PT preferences with explainable reasoning
- Automated Actions: Books calendar slots for qualified leads or sends polite rejections
- Idempotent Processing: Prevents duplicate message handling using Twilio MessageSid
- Rate Limiting: Built-in protection against message spam
- Backend: FastAPI + Python 3.11+
- AI: Pydantic AI + Claude Sonnet 4.5 (Anthropic)
- Database: SQLite + SQLAlchemy ORM
- Messaging: Twilio WhatsApp API
- Calendar: Google Calendar API (mock implementation for demo)
qualify-ai/
├── app/
│ ├── agents/ # AI agents (discovery, extraction, scoring)
│ ├── api/ # FastAPI endpoints
│ ├── middleware/ # Rate limiting middleware
│ ├── models/ # SQLAlchemy database models
│ ├── schemas/ # Pydantic schemas
│ ├── services/ # External integrations (WhatsApp, Calendar)
│ ├── tasks/ # Background task processing
│ ├── config.py # Configuration management
│ └── database.py # Database setup
├── scripts/
│ └── init_db.py # Database initialization script
├── main.py # FastAPI application entry point
├── requirements.txt # Python dependencies
└── .env.example # Environment variables template
- Python 3.11 or higher
- Twilio account (for WhatsApp API)
- Anthropic API key (for Claude)
- ngrok (for local development) or a deployment platform
# Clone the repository
git clone <your-repo-url>
cd qualify-ai
# Create virtual environment
python -m venv venv
# Activate virtual environment
# On macOS/Linux:
source venv/bin/activate
# On Windows:
# venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt# Copy the example env file
cp .env.example .env
# Edit .env with your credentials
nano .env # or use your preferred editorRequired environment variables:
# Anthropic API key (required)
ANTHROPIC_API_KEY=sk-ant-xxxx
# Twilio credentials (required for WhatsApp)
TWILIO_ACCOUNT_SID=ACxxxx
TWILIO_AUTH_TOKEN=xxxx
TWILIO_WHATSAPP_NUMBER=+14155238886
# PT Configuration (customize for your PT)
PT_NAME=Adam Powe
PT_SPECIALTY=Weight loss and functional fitness for busy professionals
PT_TARGET_GOALS=weight loss, strength building, general fitness
PT_AGE_RANGE=25-45
PT_LOCATION=London (in-person or online)
PT_MIN_BUDGET=200
PT_REQUIRED_COMMITMENT=2# Run the database initialization script
python scripts/init_db.pyThis will:
- Create all database tables
- Seed the PT preferences from your environment variables
# Development mode (with auto-reload)
python main.py
# Or using uvicorn directly
uvicorn main:app --reload --host 0.0.0.0 --port 8000The API will be available at http://localhost:8000
Use ngrok to expose your local server to the internet:
# Install ngrok (if not already installed)
# Visit https://ngrok.com/download
# Start ngrok
ngrok http 8000Copy the HTTPS URL (e.g., https://abc123.ngrok.io)
- Go to Twilio Console
- Navigate to Messaging → Try it out → Send a WhatsApp message
- Join the sandbox by sending the code to the provided number
- Configure the webhook URL:
- When a message comes in:
https://your-ngrok-url.ngrok.io/webhook/whatsapp - Method: POST
- When a message comes in:
- Save the configuration
- From your phone, send the join code to the Twilio sandbox number
- You should receive a confirmation message
Send a message like:
Hi, I'm interested in personal training
The bot will:
- Ask about your fitness goals
- Ask about your age
- Ask about your location
- Ask about commitment level (sessions per week)
- Ask about budget
- Extract and score your information
- Either book a call or send a polite rejection
You: Hi, I'm interested in personal training
Bot: Great to hear! I'd love to help you find the right fit with Adam. What are your main fitness goals right now?
You: I want to lose about 20 pounds and get stronger
Bot: Excellent goals! Weight loss and strength building are definitely achievable. Can I ask your age?
You: I'm 32
Bot: Perfect! Are you based in London, or would you be interested in online training?
You: I'm in Shoreditch actually
Bot: That's great - Adam trains in Central London! How many times per week could you realistically commit to training sessions?
You: Probably 2-3 times a week
Bot: That's a solid commitment. Just one more thing - what's your budget range for monthly training?
You: Yeah I can do £250/month
Bot: Great news! Based on what you've shared, I think you'd be a great fit for Adam's program...
GET /health
Returns:
{
"status": "healthy",
"timestamp": "2025-11-15T10:30:00Z"
}POST /webhook/whatsapp
Receives incoming WhatsApp messages from Twilio. Responds within 1 second with empty TwiML and processes in background.
GET /
Returns API information and available endpoints.
Tracks each lead conversation with status and timestamps.
Stores all messages (user and assistant) with Twilio MessageSid for idempotency.
Contains extracted structured data and qualification scores.
Stores PT's preferences for lead matching.
- Conducts natural, conversational lead qualification
- Asks one question at a time
- Warm and encouraging tone
- Gradually extracts required information
- Parses conversation history
- Extracts structured data conservatively
- Determines if enough info collected for scoring
- Scores leads 1-100 based on:
- Goal alignment (30%)
- Budget fit (25%)
- Location compatibility (20%)
- Commitment level (15%)
- Availability (10%)
- Provides reasoning for decisions
- Recommends action (book_call, send_rejection, needs_more_info)
Built-in rate limiting:
- Max 1 message per 3 seconds from same number
- Prevents spam and abuse
- Returns 200 to Twilio to avoid retries
- Idempotency: Duplicate MessageSids are ignored
- Fallback Messages: Errors trigger "Can you try again?" message
- Logging: Comprehensive logging for debugging
- Graceful Degradation: Always returns 200 to Twilio
Railway.app:
# Connect GitHub repo
# Set environment variables in Railway dashboard
# DeployRender.com:
# Connect GitHub repo
# Set environment variables
# Build Command: pip install -r requirements.txt
# Start Command: uvicorn main:app --host 0.0.0.0 --port $PORTFor production use, consider:
- PostgreSQL instead of SQLite
- Proper error monitoring (Sentry)
- Real Google Calendar integration
- Twilio WhatsApp Business API (not sandbox)
- Multi-PT support with admin dashboard
- Webhook signature validation
- HTTPS only
- Environment-based configuration
- Conversation timeout (24 hours inactivity)
- Max messages per conversation limit (20)
- Check ngrok is running and URL is correct in Twilio
- Check logs:
tail -f logsor console output - Verify environment variables are set correctly
- Test health endpoint:
curl http://localhost:8000/health
- Re-run initialization:
python scripts/init_db.py - Check file permissions on
pt_chatbot.db - Delete database and reinitialize if needed
- Verify webhook URL is HTTPS
- Check Twilio credentials in
.env - Ensure phone number format is correct (+447123456789)
- Check Twilio console for error logs
- Verify Anthropic API key is valid
- Check API quota/rate limits
- Review logs for specific error messages
- Ensure proper model name:
claude-sonnet-4-5-20250929
# Install dev dependencies
pip install pytest pytest-asyncio
# Run tests (when implemented)
pytest tests/- Use async/await for all agent calls
- Follow FastAPI best practices
- Use SQLAlchemy ORM for database operations
- Keep agents stateless and functional
- Log important events and errors
- Multi-PT platform support
- Admin dashboard for PTs
- Real Google Calendar integration with availability checking
- Instagram DM integration
- Payment integration (Stripe)
- Analytics and reporting
- Voice message support
- Multi-language support
- CRM integration (HubSpot, Salesforce)
- Fine-tuning on successful conversations
MIT License - feel free to use and modify for your needs.
For issues or questions:
- Check logs for error messages
- Review Twilio console for webhook errors
- Verify all environment variables are set
- Check database was initialized properly
Contributions welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes
- Submit a pull request
Built with Claude Sonnet 4.5 and Pydantic AI