A multilingual WhatsApp farm advisor, built with the Claude API and running in a live pilot on a real onion, cotton, and groundnut farm in Saurashtra, Gujarat.
📺 Build-in-public video series · 💼 LinkedIn
Khet-Saathi (खेत साथी) means "farm companion." Farm supervisors message a WhatsApp number in Gujarati, Hindi, or English and get practical agronomy advice back in the same language — crop disease diagnosis, irrigation and harvest timing, spray recommendations — grounded in the crops and climate of the Mahuva region.
This is not a demo with mock data. It runs on a working farm, and the design decisions in this repo (and the video series documenting them) come from real messages sent by real supervisors standing in real fields.
Every message goes through a fast classifier, then routes to the agent best suited to answer it:
flowchart TD
WA[WhatsApp message] --> WH[Vercel webhook]
WH --> C{Classifier<br/>Claude Haiku}
C -->|greeting / off-topic| Canned[Canned reply]
C -->|crop_disease| D[Diagnosis agent<br/>Claude Haiku, structured JSON]
C -->|farm_strategy| S[Strategy agent<br/>Claude Sonnet + weather tool]
D --> R{Independent reviewer<br/>second Haiku pass}
R -->|high severity + concern| E[Escalate to human<br/>Kisan Call Centre]
R -->|otherwise| F[Formatted WhatsApp reply]
S --> W[wttr.in weather lookup]
W --> F
D -.->|diagnosis persisted| KV[(Upstash Redis<br/>24h conversation + farm state)]
KV -.->|context injected| S
The interesting parts:
- Two agents, two contracts. The diagnosis agent answers in strict JSON (validated, with a one-shot retry on malformed output) so replies can be formatted consistently for WhatsApp. The strategy agent answers conversationally and can call a weather tool when timing depends on current conditions.
- An independent reviewer. Every diagnosis gets a second, context-free review pass by a separate model call. A high-severity diagnosis that the reviewer flags doesn't get treatment advice — it gets escalated to a human agronomist instead. An AI that recommends the wrong pesticide dose is worse than no AI.
- Cross-agent memory. Diagnoses are persisted to Upstash Redis (REST API — no TCP sockets in serverless) and injected into the strategy agent's context, so "should I harvest early?" is answered with knowledge of last week's purple blotch diagnosis.
- Language detection without a language model. Unicode script counting picks Gujarati vs. Hindi vs. English in microseconds; the reply language is injected into the system prompt.
- Serverless-honest webhook handling. Meta retries on any non-200, so the handler is built to always return 200 — every processing path is wrapped so a Claude API hiccup never becomes a webhook retry storm.
| Layer | Choice |
|---|---|
| Messaging | WhatsApp Business Platform (Meta Graph API webhooks) |
| Compute | Vercel Python serverless functions |
| AI | Claude Haiku 4.5 (classification, diagnosis, review) + Claude Sonnet 4.6 (strategy, tool use) |
| Memory | Upstash Redis via REST (24h expiring conversation history, farm state, farmer profile) |
| Weather | wttr.in |
api/webhook.py # Entire bot: webhook handler, classifier, both agents, reviewer, escalation
test_classifier.py # Live classification accuracy suite (10 labelled cases incl. edge cases)
test_escalation.py # Pure-logic tests for the escalation decision
eval_strategy.py # Model-graded eval: Sonnet answers, Haiku grades against a rubric
public/privacy.html # Privacy policy for the pilot
branding/ # Logo + design philosophy
vercel.json # Routes /webhook → /api/webhook
You'll need a Meta WhatsApp Business app, an Anthropic API key, and an Upstash Redis database.
-
Set environment variables (in Vercel's dashboard, or
.env.localfor local dev — never committed):Variable Purpose WHATSAPP_VERIFY_TOKENWebhook verification handshake with Meta WHATSAPP_ACCESS_TOKENGraph API bearer token WHATSAPP_PHONE_NUMBER_IDWhatsApp Business phone number ID ANTHROPIC_API_KEYClaude API KV_REST_API_URL/KV_REST_API_TOKENUpstash Redis REST credentials -
Run locally and expose to Meta:
vercel dev # localhost:3000 ngrok http 3000 # register the https URL + /webhook in Meta's console
-
Push to
main— Vercel deploys automatically.
python test_escalation.py # Pure logic, no API calls
python test_classifier.py # Live classifier accuracy (needs env vars)
python eval_strategy.py # Model-graded quality eval (needs env vars)The eval uses a second model as grader with a per-question rubric and prefilled-JSON output — a small taste of LLM-as-judge in ~80 lines.
This bot advises supervisors on my dad's farm. I'm building it in public — every architecture decision, mistake, and fix is recorded as a video:
The bot is in a private pilot and not open to the public. See the privacy policy for what data is collected and how it's used.
- Async processing (enqueue → 200 → process) once response latency outgrows the synchronous window
- Webhook signature validation (
X-Hub-Signature-256) - Photo diagnosis — supervisors already send crop photos; the bot should read them
- Voice notes in Gujarati
- Possible migration to Telegram to support groups
