An AI-powered WhatsApp bot built for Indian farmers, delivering expert agricultural advice through text, voice, and real-time phone calls β backed by human reviewer verification, multi-lingual localization, and a rich ecosystem of domain-specific MCP tool servers.
- Overview
- Key Features
- Architecture
- Tech Stack
- Quick Start
- Project Structure
- API Endpoints
- Configuration
- Deployment
- Documentation
- Contributing
- License
AjraSakha (wa-client) is a production-grade WhatsApp Business API integration built on NestJS using CQRS architecture. It serves as the communication layer of the Annam.AI Foundation platform β connecting Indian farmers with AI-driven agricultural intelligence through WhatsApp text, voice notes, and real-time VoIP calls.
Provide accessible, multilingual agricultural advisory services to Indian farmers who may be illiterate or semi-literate, by:
- Answering farming questions via text or voice in the farmer's local language
- Routing unanswered questions to human expert reviewers for quality assurance
- Delivering expert-reviewed answers back to farmers, automatically localized
- Providing real-time voice consultations via WhatsApp VoIP calls powered by Gemini Live
| Category | Capability |
|---|---|
| Multi-Modal Input | Text messages, voice notes (STT via Sarvam AI), real-time VoIP calls |
| AI-Powered Responses | LangGraph agent orchestration with MCP tool integration |
| Voice Output | Text-to-Speech via Sarvam AI, delivered as WhatsApp voice notes |
| Real-Time Calling | WebRTC β Gemini Live bridge for live voice conversations |
| Expert Review Pipeline | Questions auto-uploaded to reviewer system; answers polled/webhoooked and localized |
| Multi-Lingual | Auto-detects 10+ Indian languages; translates expert answers via Claude |
| Access Control | Whitelist (dev) / Blacklist (prod) system backed by MongoDB |
| User Analytics | Unique user counts, message history, engagement tracking |
| CQRS Architecture | Clean command/query separation for maintainable business logic |
| Production Hardened | Webhook signature verification, thread repair, graceful error handling |
ββββββββββββββββββββββββ
β Meta WhatsApp Cloud β
β Business API β
ββββββββββββ¬ββββββββββββ
β Webhook (POST /whatsapp/webhook)
βΌ
ββββββββββββββββββββββββ βββββββββββββββββββ
β WhatsApp Controller ββββββΆβ CQRS Command β
β (Signature verify) β β Bus (NestJS) β
ββββββββββββββββββββββββ ββββββββββ¬βββββββββ
β
ββββββββββββββββββββββββββββΌβββββββββββββββββββββββββββ
βΌ βΌ βΌ
βββββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββββββ
β AddUserText β β AddUserVoice β β SetUserLocation β
β MessageHandler β β MessageHandler β β Handler β
ββββββββββ¬βββββββββ ββββββββββ¬ββββββββββ ββββββββββ¬ββββββββββ
β β β
β ββββββββββΌββββββββββ β
β β Sarvam AI STT β β
β β (Voice β Text) β β
β ββββββββββ¬ββββββββββ β
β β β
βββββββββββββ¬ββββββββββββ β
βΌ βΌ
βββββββββββββββββββββββ ββββββββββββββββββββββ
β LangGraph Client β β LangGraph Client β
β (Aegra Server) β β (Location Update) β
β βββββββββββββββββ β ββββββββββββββββββββββ
β β MCP Tool β β
β β Servers (7+) β β
β βββββββββββββββββ β
ββββββββββββ¬βββββββββββ
β
ββββββββββββββΌβββββββββββββ
βΌ βΌ βΌ
ββββββββββββ ββββββββββββ ββββββββββββββββ
β MongoDB β β Reviewer β β WhatsApp API β
β (State) β β System β β (Outbound) β
ββββββββββββ ββββββββββββ ββββββββββββββββ
For complete architecture documentation including data flow diagrams and sequence diagrams, see docs/architecture.md.
| Layer | Technology |
|---|---|
| Runtime | Node.js 20 (Debian Bookworm Slim) |
| Framework | NestJS 11 with CQRS (@nestjs/cqrs) |
| Language | TypeScript 5.7 |
| Database | MongoDB 7 (Mongoose 9) |
| Cache | Redis 7 (ioredis) β referenced but not actively used |
| AI Orchestration | LangGraph SDK (@langchain/langgraph-sdk) via Aegra server |
| LLM Providers | OpenAI-compatible APIs, Anthropic (Claude), Google Gemini |
| Voice AI | Sarvam AI (STT/TTS), Gemini Live (real-time voice) |
| WebRTC | werift (Node.js WebRTC), @discordjs/opus |
| Protocol | MCP (Model Context Protocol) for tool integration |
| Secrets | Infisical (production), .env (development) |
| Container | Docker (single-stage), docker-compose |
| CI/CD | GitHub Actions β Docker Hub β GCP VM via Tailscale |
- Node.js β₯ 20.x
- MongoDB β₯ 7.x (local or cloud β e.g., MongoDB Atlas)
- Redis β₯ 7.x (optional β not actively used)
- Meta WhatsApp Business API account with verified phone number
- API Keys: Sarvam AI, Gemini, LLM provider, LangGraph/Aegra server
git clone <repository-url>
cd wa-client
npm installcp .env.example .env
cp config.example.yaml config.yamlEdit .env with your secrets (API keys, tokens, MongoDB URI).
Edit config.yaml for non-secret configuration (system prompts, MCP servers, feature flags).
See docs/setup.md for detailed configuration guide.
# Option A: Docker (MongoDB + Redis)
npm run docker:dev
# Option B: Use managed cloud services
# Set MONGO_URI in .env to your Atlas connection string
npm run start:dev- Go to Meta Developer Dashboard
- Set webhook URL:
https://yourdomain.com/whatsapp/webhook - Set verify token to match
WHATSAPP_WEBHOOK_VERIFY_TOKENin.env - Subscribe to
messagesandcallsfields
# Development (with hot-reload)
npm run start:dev
# Production
npm run build
npm run start:prodwa-client/
βββ src/
β βββ main.ts # Application bootstrap
β βββ app.module.ts # Root module (Config, MongoDB, WhatsApp)
β βββ config/ # Configuration subsystem
β β βββ configuration.ts # YAML loader with env overrides
β β βββ config.schema.ts # class-validator schemas
β β βββ validate-config.ts # Validation logic
β β βββ app-config.service.ts # Typed config accessor
β β βββ index.ts # Barrel exports
β βββ whatsapp/ # Core WhatsApp module
β βββ whatsapp.module.ts # Module registration
β βββ whatsapp.controller.ts # HTTP endpoints (webhook, API)
β βββ manual-outbound-message.ts # Expert message formatting
β βββ whatsapp-api/ # Meta Graph API integration
β β βββ whatsapp.service.ts # Send text/voice/location/media
β β βββ whatsapp.config.ts # API URL construction
β β βββ whatsapp-api.module.ts # Module
β βββ conversations/ # CQRS conversation pipeline
β β βββ conversation.module.ts # Module registration
β β βββ langgraph-client.service.ts # LangGraph SDK wrapper
β β βββ langgraph.module.ts # Module
β β βββ application/ # Command handlers
β β βββ add-user-text-message/
β β βββ add-user-voice-message/
β β βββ set-user-location/
β βββ calling/ # Real-time VoIP module
β β βββ calling.service.ts # WebRTC lifecycle & RTP pacing
β β βββ gemini-live.service.ts # Gemini Live WebSocket bridge
β β βββ audio-codec.service.ts # Opus β PCM transcoding
β β βββ mcp-tools.service.ts # MCP tool discovery for voice
β β βββ calling.module.ts # Module
β βββ pending-questions/ # Expert review pipeline
β β βββ reviewer-polling.service.ts # Cron polling + webhook handler
β β βββ reviewer-answer-localization.service.ts # Multi-lingual translation
β β βββ pending-question.schema.ts # Mongoose schema
β β βββ pending-question.repository.ts # Abstract repository
β β βββ mongo-pending-question.repository.ts # MongoDB implementation
β β βββ pending-questions.module.ts # Module
β βββ access-control/ # Whitelist/Blacklist system
β β βββ access-control.service.ts
β β βββ whitelist.schema.ts
β β βββ blacklist.schema.ts
β β βββ access-control.module.ts
β βββ sarvam-api/ # Speech-to-Text & Text-to-Speech
β β βββ sarvam.service.ts
β β βββ sarvam.module.ts
β βββ user-stats/ # User analytics
β βββ whatsapp-user.schema.ts
β βββ whatsapp-user.repository.ts
β βββ mongo-whatsapp-user.repository.ts
β βββ user-stats.module.ts
βββ test/ # E2E tests
βββ config.yaml # Non-secret configuration
βββ config.example.yaml # Example config (version-controlled)
βββ .env # Secrets (git-ignored)
βββ .env.example # Secret template
βββ Dockerfile # Production container
βββ docker-compose.yml # Local dev infrastructure
βββ .github/workflows/ # CI/CD
β βββ dockerhub-build.yml # Build β Deploy pipeline
βββ package.json # Dependencies & scripts
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/whatsapp/webhook |
Verify Token | WhatsApp webhook subscription verification |
POST |
/whatsapp/webhook |
HMAC-SHA256 | Incoming messages, statuses, and call events |
GET |
/whatsapp/health |
None | Health check |
POST |
/whatsapp/send-message |
x-internal-api-key |
Send outbound message (expert/admin) |
POST |
/whatsapp/reviewer-webhook |
x-internal-api-key |
Receive real-time expert answers |
GET |
/whatsapp/test-poll |
x-internal-api-key |
Manually trigger reviewer polling |
GET |
/whatsapp/users/count |
x-internal-api-key |
Unique user count |
GET |
/whatsapp/users |
x-internal-api-key |
Paginated user list |
Full API documentation: docs/api-reference.md
The application uses a dual-layer configuration system:
| Layer | File | Purpose |
|---|---|---|
| Secrets | .env |
API keys, tokens, database URIs β never committed |
| Config | config.yaml |
System prompts, MCP servers, feature flags, thresholds β safe to commit |
Environment variables in .env can override config.yaml values at runtime.
Full configuration reference: docs/setup.md
Production deployment uses:
- Docker containers on a GCP VM
- Infisical for secrets management in production
- Tailscale mesh VPN for secure CI/CD access
- GitHub Actions for automated build β push β deploy pipeline
# Manual Docker deployment
docker build -t wa-bot .
docker run -d --env-file .env -p 3000:3000 wa-bot
# Via docker-compose (includes MongoDB + Redis)
docker-compose up -dFull deployment guide: docs/deployment.md
| Document | Description |
|---|---|
| Architecture | System design, data flows, sequence diagrams |
| Setup Guide | Prerequisites, environment variables, local development |
| API Reference | All endpoints, payloads, authentication |
| Database | MongoDB collections, schemas, indexes |
| Deployment | CI/CD, Docker, infrastructure, rollback |
| Security | Auth, secrets, webhook verification |
| Troubleshooting | Common errors and resolution steps |
- Create a feature branch from
main - Follow the existing NestJS module pattern (module β service β repository)
- Use the CQRS pattern for new message-handling flows
- Add entries to
config.yamlfor new configurable values - Keep secrets in
.envonly - Run
npm run lintandnpm run formatbefore committing - See docs/architecture.md for detailed developer guidance
UNLICENSED β Proprietary. All rights reserved by Annam.AI Foundation.