Hisham Alhussain
All work

Case study

WhatsApp AI Front-Desk Agent

A bilingual (Arabic/English) agent that runs a business's WhatsApp number like a front desk: answers, books, reminds, follows up, and hands off to staff.

For
Independent · clinics, salons, law firms
My role
Sole architect & engineer
Stack
Claude API, Python, FastAPI, PostgreSQL

Problem

Small businesses in the Gulf get most enquiries on WhatsApp, often late at night and in dialect. Missed replies mean missed bookings.

What I built

A FastAPI + Postgres agent on the Claude API with code-enforced booking guardrails, an exactly-once reminder scheduler, a staff inbox and an eval gate on every release.

Outcome

Live-tested on a real WhatsApp Business number. Every release must pass 138/138 eval runs in both languages.

eval runs passed
138/138eval runs passed
per conversation
~$0.003per conversation
median reply
2.8smedian reply
unit & integration tests
292unit & integration tests

Architecture

  1. 01WhatsAppCustomer messages via Meta Cloud API
  2. 02Webhook APIHMAC check, dedupe, enqueue in ms
  3. 03WorkerPostgres job queue (SKIP LOCKED)
  4. 04Agent loopClaude + booking & handoff tools
  5. 05Replies & reminders24h-window guard, exactly-once sends
  • Eval-gated
  • Exactly-once
  • PDPL-aware
  • One Docker image

The problem

In Saudi Arabia and the Gulf, WhatsApp is how people contact a business. They expect an answer quickly, in their own dialect, often outside working hours. A small clinic or law firm can't staff that, so leads go cold and appointments slip.

I wanted an agent that could run the front desk end to end, and that a business owner could trust with real customers.

What it does

  • Answers FAQs from the business's knowledge base, mirroring the customer's language and register (formal Arabic when they use it, natural Gulf phrasing otherwise).
  • Books, reschedules and cancels through a pluggable calendar (Postgres or Google Calendar), offering only slots that are really free as a WhatsApp list.
  • Confirms before acting. Every change shows a code-written summary with Confirm / Change buttons.
  • Sends reminders as approved templates with Confirm / Reschedule quick replies, and follows up once with leads who didn't book, respecting quiet hours and opt-outs.
  • Hands off to staff when a customer is upset, asks for a person, or goes out of scope, with a web inbox for staff to reply and hand the chat back.

Key engineering decisions

Guardrails in code, not just the prompt. Early evals caught the model saying "you're booked" before any booking existed. Instead of a longer prompt, a booking tool is now rejected unless the previous turn asked for confirmation, and all confirmation messages are written by code from the actual database result.

Exactly-once messaging. Reminders must never send twice, even with several workers or a crash mid-send. Each row is claimed with FOR UPDATE SKIP LOCKED and marked sent with the WhatsApp message id in the same transaction. A smoke test runs two schedulers concurrently against real Postgres, and it caught real double-sends before launch.

Postgres as the queue. One Docker image runs three roles (api, worker, scheduler). No Redis, no broker: fewer moving parts for a small business to pay for.

Evaluation-driven development. 46 scripted conversations (23 Arabic, 23 English) replay through the real production path. Grading is programmatic first (bookings, state, facts, language), with an LLM judge on a stronger model only for judgment calls like prompt-injection resistance and a Gulf-dialect rubric. Every case runs three times and releases are gated on 3/3.

Cost control. The knowledge base and an Arabic style guide sit in a cached system prompt, history is capped, and the cheapest model that passes the gate is used.

Results

  • 138/138 eval runs passing across both languages
  • ~$0.003 per conversation and 2.8s median reply time on the eval set
  • 292 unit and integration tests, mypy --strict clean
  • Live-tested end to end on a real WhatsApp Business number with approved templates
Source on GitHub
Next case studyESRA: Environmental & Social Responsibility Application