Claude x WhatsApp Agent

  • By Praveen Jha · Updated 2026-10-23 · 15 min read · Developer & MCP tools

WHATSAPP BUSINESS PLATFORM • CLAUDE • PYTHON

Build a production WhatsApp AI agent for a business - instant replies in the brand's tone, tap-through menus, call booking, file delivery and lead capture - on the official WhatsApp Business Platform (Cloud API).

The one idea that controls cost and speed: menus and buttons are scripted - free and instant. Claude is called only when a customer types a free-form message. Design every journey so most taps never touch the AI.

Who this is for

A developer building this for a business owner, using Claude Code to write most of the code. You do not need to be a WhatsApp specialist - you need Python basics, a Meta account, and care with tokens, webhooks and the 24-hour messaging window.

How to use this guide

  1. Work through Phases 0-1 to get a talking bot on a free test number.
  2. Add Phase 2 scripted features and Phase 3 Claude tools.
  3. Test locally (Phase 4), then harden and launch (Phase 5).
  4. Start the actual build with the starter brief on the last pages.

1. 1 What you will build

A business WhatsApp assistant that behaves like a good front desk, inside the chat customers already use:

Instant replies in brand tone - greetings, prices, timings, FAQs.

Tap menus - lists and buttons instead of typing, wherever possible.

Booking calls - offer slots, hold one briefly, confirm it.

File delivery - send a brochure, price list, image or PDF on request.

  • Lead capture - collect name, need and contact details into a record the owner can act on, without making the chat feel like a form.

Scripted (no AI cost)

Welcome, menus, buttons, forms, slot lists, file sends, confirmations. Deterministic, testable, instant.

Claude (paid, per typed message) Open questions, mixed language, follow-ups, and choosing a real action through tools. Only here does quality of wording matter most.

2 Architecture at a glance

Customer on WhatsApp

↓

Meta Cloud API - sends each message to your webhook (HTTPS POST)

↓

Python bot (Flask, bot.py ) - verifies, dedupes, routes

  • → known tap / keyword → scripted flow
  • → free-typed text → Claude API (with business knowledge + tools)

↓

Reply via Cloud API - text, list, buttons, image or PDF

Keep the bot as one small, readable service at first. Split files by job (flows, cards, knowledge) rather than adding frameworks, queues or a database before you need them.

3 What you need before you start

ItemNotes
Meta / Facebook account + business portfolioFree. This owns the Meta app, the WhatsApp account and, later, business verification.
WhatsApp test numberFree from Meta. Can message up to 5 recipient numbers you add - enough for development and demos.
Claude API key + small creditFrom the Anthropic Console. Start with about $5 credit and leave auto-reload off until production spend is understood.
Claude CodeYour coding partner for the build. The starter brief (Section 14) is its first message.
Python 3.11+With pip and git available. Flask is the web layer.
cloudflaredExposes your local bot over HTTPS so Meta's webhook can reach it during testing.
Hosting (production only)An always-on host with persistent disk, or a VPS. A sleeping laptop is not production.

4 Phase 0 - Accounts and keys

  1. Create the Meta app and add the WhatsApp use case / product.
  2. Note the two IDs from the WhatsApp setup screen: the Phone Number ID (which number is sending) and the WABA ID - WhatsApp Business Account ID (which business account it belongs to). Mixing these up is a common source of errors.
  3. Copy the temporary access token. It lasts roughly 24 hours - fine for testing, never for production.
  4. Add your own phone as a recipient of the test number, and verify it if prompted.
  5. Create the Anthropic API key in the Console and add the starting credit.
  6. Check your tools:

Copy-ready text

python --version    # 3.11 or newer
pip --version
git --version

Rule for every secret: keys and tokens go straight into your local .env file - never into chat, screenshots, commits or this guide. If a secret leaks, revoke and re-issue it.

5 Phase 1 - The core bot

Project layout

Copy-ready text

bot.py         Flask app: webhook, routing, sending
flows.py       Scripted journeys (menus, forms, booking)
cards.py       Builders for lists, buttons, tickets, images
knowledge.md   Everything Claude may say about the business
.env           Secrets and config (never committed)
data/          chats.json and other local state
assets/        Banner, brochures, PDFs, QR and ticket inputs

The webhook must do these jobs, in order

  1. Verify (GET): answer Meta's challenge only when the verify token matches your own WHATSAPP_VERIFY_TOKEN.
  2. Check the signature (POST): validate the request against the app secret before trusting its contents.
  3. Dedupe: Meta can retry deliveries. Store processed message IDs and ignore repeats, or customers get double replies.
  4. Acknowledge fast, then work: return 200 promptly and handle the reply without blocking the webhook.
  5. Show presence: mark the message read and show typing while Claude is thinking - it makes a 2-3 second wait feel normal.
  6. Route: interactive replies (list/button IDs) go to scripted flows; plain text goes to Claude unless a flow is mid-step and expecting typed input.
  7. Log with tags: log route, phone (masked in shared logs), latency and outcome so later bugs are diagnosable.

The Claude brain

Model comes from CLAUDE_MODEL in .env - never hard-code it.

  • System prompt is built from knowledge.md: services, prices, FAQs, tone, and what never to promise.
  • Prompt caching: cache the stable system/knowledge block so repeated conversations do not re-pay full price for it.
  • Low effort / short answers: WhatsApp replies should be brief. Long essays kill the chat experience and raise cost.
  • Refusals: if Claude declines or the request is out of scope, reply with a safe fallback and offer human handover - never forward a raw refusal.
  • Hidden lead capture: when a typed chat reveals name, need or budget, extract and save it quietly; do not interrogate the customer.

Memory, robustness and tests (Phase 1, continued)

Per-customer memory

  • Keep conversation history per phone number in data/chats.json (or a small database later). One customer's context must never leak into another's.
  • Do not persist thinking blocks. Store only user/assistant text and tool results you actually need. Saved thinking blocks are the root of a nasty recurring error (below).
  • Prefix context: prepend the current date/time to the model call so "tomorrow", "this evening" and slot questions resolve correctly.
  • Self-heal on the thinking-signature 400: if the API rejects a stored history with a thinking signature error, drop the offending history for that chat, start that customer fresh, and log it - do not crash the bot for everyone.

Test before you connect WhatsApp

Test What it proves
Terminal chat Talk to the Claude brain from your console - no Meta, no tunnel. Fix tone and knowledge here, where iteration is fast.
Persona tests Run scripted pretend customers: price-hunter, Hinglish speaker, confused first-timer, someone asking out-of-scope questions. Save these as rerunnable tests.
Flow tests Every button/list ID lands in the right flow; every flow can exit or hand over.
Definition of done for Phase 1:a test recipient can say "hi", tap through a menu, type one open question, and get a correct, in-tone answer - with no duplicate replies.

6 Phase 2 - Premium features, zero AI cost

Everything here is scripted - free, instant and reliable:

  • Welcome banner + interactive list: a branded image on first contact, then a list menu - maximum 10 rows per list.
  • Reply buttons: quick actions under a message - maximum 3 buttons. Design within the limit instead of fighting it.
  • Lead / brief form flow: step-by-step questions (one per message) that end in a saved, structured lead.
  • Booking flow: show slots → customer picks → hold the slot for about 10 minutes → payment step → ticket. In demos, any UPI QR must be clearly labelled as a demo.
  • File delivery: upload media once via the Media API, then send by media ID - faster and more reliable than re-uploading.
  • Waitlist: if slots fill, capture the lead instead of dead-ending the chat.
  • Human handover: a clear "talk to a person" path that pauses the bot for that chat and alerts the owner.
  • Local image generation: tickets, banners and QR images with Pillow + qrcode - no paid image API.

7 Phase 3 - Stand out: Claude takes real actions

Scripted menus break the moment a customer writes naturally: _"Kal shaam ko call ho sakta hai?"_ ("Can we do a call tomorrow evening?") should work just as well as the English version. That is what Claude tools are for.

The key tool: offer_call_slots

  • Define a tool such as offer_call_slots with inputs like date and part_of_day (morning / afternoon / evening).
  • Claude reads the typed request - in Hinglish or English - and calls the tool with normalised values. Your code, not the model, looks up real availability and renders the slot list.
  • The customer taps a slot and the normal scripted booking flow takes over. AI interprets; code executes.

The tool loop, safely

  1. Send the message + tool definitions to Claude.
  2. If Claude requests a tool, run it in your code, return the result, and call Claude again for the final wording.
  3. Cap the loop (a few iterations), validate every tool argument, and never let a tool do payments, deletions or messages to third parties without a deterministic check in code.
  4. Context follow-ups: keep enough history that "the later one" or "usi din" ("that same day") resolves to the slots just offered.

Optional upgrades, in value order

UpgradeValue
Returning-customer memoryGreet by context ("reorder?", "your last booking") using saved profile data - with consent and an easy opt-out.
Voice-note understandingTranscribe voice notes and feed the text into the same brain. Many customers prefer speaking.
Image understandingLet customers send a photo (a product, a document, a problem) and have Claude describe / route it.
Daily owner summaryOne scheduled message to the owner: new leads, bookings, handovers and unanswered questions.

8 Phase 4 - Local testing, end to end

  1. Start the bot locally (for example, the Flask app's serve command) and confirm the health / webhook route responds.
  2. Open the tunnel with cloudflared, forcing QUIC if the default protocol misbehaves on your network:

Copy-ready text

cloudflared tunnel --url http://localhost:PORT --protocol quic
  1. Configure the webhook in Meta: paste the tunnel's HTTPS callback URL, set the verify token to exactly your WHATSAPP_VERIFY_TOKEN, and complete verification.
  2. Subscribe to the messages field on the webhook - without this, Meta verifies you but sends nothing.
  3. Subscribe the app to the WABA - the step everyone misses:

Copy-ready text

POST /{WABA_ID}/subscribed_apps

Authorization: Bearer <access token>
  1. Send "hi" from an added test recipient. Expect: read ticks, the welcome, and the menu.
  2. Then test in this order: every menu tap, one form, one booking, one file, one typed Hinglish question, one handover.

Grey ticks and silence? Work the troubleshooting table (Section 13) in order - WABA subscription, token, webhook field, tunnel - before changing bot code.

9 Phase 5 - Production

  • Permanent token: create a Meta System User, give it only the WhatsApp assets it needs, and generate a token that does not expire. Replace the 24-hour token everywhere.
  • Real number: register the business's own number, set the display name, and complete business verification early - it can take time.
  • Templates: outside the 24-hour window you may only open with approved template messages. Submit utility templates (confirmations, reminders) before you need them.
  • Hosting: Render or Railway (always-on plan, persistent disk for data/ ) or a VPS running gunicorn with 1 worker if state lives in local files / memory - multiple workers with file state will disagree with each other.
  • Calendar: connect Google Calendar so offered slots are real and confirmed bookings create events.
  • Payments: integrate Razorpay (or the chosen provider) and confirm a booking only on the signed payment webhook - never because the customer says "paid".

Reliability and the go-live checklist

  • Retries: retry transient API failures with backoff; never retry by re-sending a customer message blindly - dedupe first.
  • Per-user rate limit: cap messages per customer per minute so one loop or one abusive user cannot burn your Claude credit.

Backups: back up data/ (chats, leads, bookings) on a schedule, and test a restore once.

  • Spend alerts: set Anthropic and hosting alerts so a runaway loop is a notification, not a bill shock.
  • Health check: an uptime check on the webhook URL; alert the owner if it fails.

Go-live checklist

  • System User (permanent) token in production .env; temporary token removed
  • Real number live, display name approved, business verification done
  • Utility templates approved for outside-24h messages
  • Always-on hosting, persistent disk, HTTPS webhook re-pointed from tunnel to production
  • App re-subscribed to the WABA on the production setup
  • Payment confirmation only via signed provider webhook; calendar events verified
  • Rate limits, backups, spend alerts and handover path tested with a real phone

10 Environment variables (.env)

Names only below - values are placeholders in your own file. Commit a .env.example with names and dummy values; never commit the real .env.

Copy-ready text

WHATSAPP_TOKEN=              # Meta access token
WHATSAPP_PHONE_NUMBER_ID=    # sender number ID (not the number itself)
WHATSAPP_VERIFY_TOKEN=       # a password YOU invent for webhook verify
WHATSAPP_APP_SECRET=         # for webhook signature checks
ANTHROPIC_API_KEY=           # Claude API key
CLAUDE_MODEL=                # model ID - change here, nowhere else
PORT=                        # local / host port for the bot
GRAPH_VERSION=               # Meta Graph API version, e.g. vXX.0

Add .env to .gitignore on day one, before the first commit.

11 What it costs

Only free-typed messages cost AI money. Figures are approximate planning numbers - verify current pricing before quoting a client.

Claude cost per 100 typed messages (approx.)

Model tierPer 100 typed messagesBest for
Opus (most capable)Highest - roughly $1.50-2.50 / Rs 130-210Complex reasoning, premium clients
Sonnet (balanced)Mid - roughly $0.50-0.90 / Rs 45-75Default choice for most businesses
Haiku (fastest, cheapest)Lowest - roughly $0.15-0.30 / Rs 13-25High volume, simple Q&A

Actual cost depends on message length, history size and caching.

Everything else

ItemCost
Scripted actions (menus, buttons,Free - no AI call
forms, files)
Replies inside the 24-hour windowFree on the Cloud API
Utility templates (outside 24h)A few paise per message in India
Marketing templates (India)Roughly Rs 0.8-0.9 per message
HostingRs 0-600 / month depending on platform and tier
Payment gateway (Razorpay)Roughly 2% + GST per transaction

Changing the model: edit CLAUDE_MODEL in .env, restart the bot, and re-run the persona tests. No code change. Step down a tier to cut cost; step up only if test answers actually improve.

12 Compliance - the non-negotiables

  • Official API only. No unofficial gateways, no automation of the personal WhatsApp app. Bans are real and numbers are hard to recover.
  • Business-scoped, not a general chatbot. Open-ended general assistants breach platform policy.
  • Disclose the AI and keep a human path available. Customers message first - reply inside the 24-hour window; outside it, only approved templates.
  • Human handover must work - complaints, sensitive cases and repeated failures go to a person.
  • Restricted categories decline and are routed per policy, not improvised around. Payments are confirmed only by the provider's signed webhook. Privacy: collect minimum lead data, store it securely, and honour deletion requests.

13 Troubleshooting

SymptomLikely causeFix
Messages sent, only grey ticks, bot silentApp not subscribed to the WABA, or messages field not subscribedPOST to /{WABA_ID}/subscribed_apps; check webhook subscriptions
401 errors from the APITemporary token expired (~24h)Re-copy the token for testing; use a System User token in production
Webhook verification failsVerify token mismatch, or wrong callback URLMake Meta's token character-identical to WHATSAPP_VERIFY_TOKEN; use the current tunnel URL
Tunnel errors /Default tunnel protocol blocked onRe-run cloudflared with --protocol quic;
unreachable webhookthe networkrestart after sleep/reconnect
Certificate errors (pip / downloads)Antivirus or network intercepting TLSFix the certificate store / AV setting properly; never disable verification permanently
400 error mentioning thinking / signatureSaved chat history contains thinking blocksStop persisting them; clear that chat's history (self-heal) and restart the conversation
"Recipient not allowed" on test numberTest numbers can only message 5 added recipientsAdd the number in Meta's setup screen, or go live with a real number
Message rejected outside business hoursOutside the 24-hour windowUse an approved utility/marketing template to reopen the conversation
Bot stops overnightThe laptop running it sleptFor real use, move to always-on hosting; tunnels and local bots die with the machine
Menu or button does nothing / is rejectedInteractive limits exceededMax 10 list rows, max 3 reply buttons - redesign the step within the limit

14 Start the build: the starter brief

The companion starter brief is a ready-made first message for Claude Code. Used well, it does most of the project setup for you:

  1. Create an empty project folder and open Claude Code in it.
  2. Open the starter brief and complete its "About my business" section - do not skip fields and hope the bot guesses:
Fill inWhy it matters
Business name and one-line descriptionSets identity, greetings and the system prompt
Services and pricesBecomes knowledge.md- the only facts Claude may quote
FAQs with approved answersStops improvisation on timings, areas served, policies
Handover rulesWhich topics or phrases immediately go to a human
Files to deliverBrochures / PDFs / images the bot should send, and when
Brand coloursUsed on the banner, ticket and generated images
  1. Paste the whole brief as the first message in Claude Code and let it scaffold the project (layout in Section 5).
  2. Then work phase by phase in this guide, testing as you go - do not ask for the whole production system in one prompt.

15 Deliverables - what "done" looks like

The hosted bot - live on the real business number, on always-on hosting, with the permanent token.

  • A README - how it is structured, how to run it locally, how to deploy, where secrets live (names, not values).
  • An owner's manual - in plain language: how to read leads and bookings, use handover, update prices/FAQs in knowledge.md, and what to do if the bot is silent.
  • Rerunnable tests - the terminal-chat and persona tests from Phase 1, kept in the repo so any future change can be checked in minutes.

Final check before handover: pick up a phone that is not a test recipient, message the business like a stranger, book a call, pay (test mode), and hand over to a human. If all four work, you are done.

By Praveen Jha | praveenjha.com. Pricing, limits and platform rules change; verify current figures in the Meta and Anthropic consoles before quoting or launching.

Related pages