How to Connect an AI Agent to WhatsApp (Cloud API + Python)
Updated 2026-10-15
This guide connects an AI agent to WhatsApp through Meta’s official WhatsApp Business Platform Cloud API. Incoming messages hit your webhook, the agent writes a reply, and you send it back through the Graph API. Unofficial “WhatsApp Web” libraries can get numbers banned, so avoid them for anything real.
Prerequisites
- A Meta developer account and a Meta Business account
- A server reachable over HTTPS (for local testing, a tunnel such as
cloudflared tunnel --url http://localhost:8000or ngrok) - Python 3.10+ and an LLM API key
Steps
1. Create the WhatsApp app
- At developers.facebook.com, click Create app, choose the Business type, and add the WhatsApp product.
- Under WhatsApp → API Setup you get a free test number, its Phone number ID, and a temporary access token (valid ~24 hours). Add your personal phone as a recipient.
- For production, create a System User in Business Settings and generate a permanent token with
whatsapp_business_messagingandwhatsapp_business_managementpermissions.
2. Install dependencies
pip install fastapi uvicorn httpx openai
export WA_TOKEN="EAAG..." WA_PHONE_ID="1234567890" WA_VERIFY="pick-any-secret"
3. Write the webhook server
# app.py
import os, httpx
from fastapi import FastAPI, Request, Response
from openai import OpenAI
app, llm = FastAPI(), OpenAI()
GRAPH = f"https://graph.facebook.com/v21.0/{os.environ['WA_PHONE_ID']}/messages"
HISTORY: dict[str, list] = {} # per-user short-term memory (use a DB in production)
@app.get("/webhook") # Meta calls this once to verify your URL
def verify(request: Request):
p = request.query_params
if p.get("hub.mode") == "subscribe" and p.get("hub.verify_token") == os.environ["WA_VERIFY"]:
return Response(p.get("hub.challenge"), media_type="text/plain")
return Response(status_code=403)
@app.post("/webhook")
async def incoming(request: Request):
data = await request.json()
for entry in data.get("entry", []):
for change in entry.get("changes", []):
for msg in change["value"].get("messages", []):
if msg.get("type") == "text":
await handle(msg["from"], msg["text"]["body"])
return {"ok": True} # always 200 fast, or Meta retries
async def handle(user: str, text: str):
hist = HISTORY.setdefault(user, [{"role": "system",
"content": "You are a friendly assistant on WhatsApp. Keep replies under 80 words."}])
hist.append({"role": "user", "content": text})
reply = llm.chat.completions.create(model="gpt-4.1-mini", messages=hist[-20:]).choices[0].message.content
hist.append({"role": "assistant", "content": reply})
async with httpx.AsyncClient() as c:
r = await c.post(GRAPH, headers={"Authorization": f"Bearer {os.environ['WA_TOKEN']}"},
json={"messaging_product": "whatsapp", "to": user, "type": "text", "text": {"body": reply}})
r.raise_for_status()
Graph API versions change over time. Use the version shown in your app dashboard if v21.0 has been retired.
4. Run it and register the webhook
uvicorn app:app --port 8000
cloudflared tunnel --url http://localhost:8000 # prints an https URL
In WhatsApp → Configuration, set the Callback URL to https://YOUR-URL/webhook and the Verify token to your WA_VERIFY value, click Verify and save, then subscribe to the messages field.
5. Test
Send a WhatsApp message from your registered phone to the test number. The agent replies within a few seconds.
6. Add tools
Turn handle() into the tool-calling loop from Build your first AI agent in Python to let the agent book appointments, look up orders, etc.
Rules that matter
- You can send free-form replies only within 24 hours of the user’s last message. Outside that window you must use a pre-approved message template.
- Webhooks can be delivered more than once. De-duplicate on
msg["id"].
Common errors
Webhook verification fails: the verify token doesn’t match, or you returned JSON instead of the raw hub.challenge string.
(#131030) Recipient phone number not in allowed list: with a test number, add the recipient under API Setup first.
(#131047) Re-engagement message: more than 24 hours since the user wrote. Use a template message.
Error validating access token: Session has expired: the temporary token expired. Use a System User token.
Related
- Connect an AI agent to Slack
- n8n AI agent memory if you’d rather build this in n8n