WhatsApp AI Agent: A Complete Guide using Gemini

Jamie89 Intermediate 1h ago 362 views 10 likes 2 min read

Integrating an LLM into a company's communication channel usually starts with a request from management to "automate customer queries." My team recently tackled this by building a WhatsApp bot powered by Gemini. The interesting part wasn't just the deployment, but using Gemini as the actual pair-programmer to write the integration code. It essentially acted as both the engine of the bot and the architect of the system.

The Technical Architecture

The data flow is straightforward but requires a reliable bridge between Meta's infrastructure and Google's model.

  • WhatsApp Cloud API (Meta): This handles the inbound messages via webhooks and outbound replies via the Graph API.
  • Flask Server: A lightweight Python middleman that receives the webhook POST requests and triggers the AI.
  • Gemini API: The reasoning engine that processes the user's text and generates a response.

To get this running, you need a Meta for Developers account, a Google AI Studio API key, and ngrok to tunnel your local environment to a public URL so Meta can actually hit your webhook.

Deployment Step-by-Step

1. Environment Configuration


First, get your API keys from Google AI Studio and set up your Meta Business app. Once you have your Phone Number ID and temporary access token, initialize your project:

mkdir whatsapp-gemini-agent && cd whatsapp-gemini-agent
python -m venv .venv && source .venv/bin/activate
pip install flask google-genai requests python-dotenv

Store your credentials in a .env file to keep them out of version control:

GEMINI_API_KEY=your_gemini_key
WHATSAPP_TOKEN=your_whatsapp_access_token
WHATSAPP_PHONE_NUMBER_ID=your_phone_number_id
VERIFY_TOKEN=pick_any_random_string

2. Building the Webhook Server


The core of the agent is a Flask app. Meta requires a GET endpoint for the initial verification handshake and a POST endpoint to receive actual messages.

import os
import requests
from flask import Flask, request
from google import genai
from dotenv import load_dotenv

load_dotenv()

GEMINI_API_KEY = os.environ["GEMINI_API_KEY"]
WHATSAPP_TOKEN = os.environ["WHATSAPP_TOKEN"]
PHONE_NUMBER_ID = os.environ["WHATSAPP_PHONE_NUMBER_ID"]
VERIFY_TOKEN = os.environ["VERIFY_TOKEN"]

app = Flask(__name__)
client = genai.Client(api_key=GEMINI_API_KEY)

SYSTEM_PROMPT = (
 "You are a friendly, concise WhatsApp assistant. "
 "Keep replies short and clear — this is a chat app, not email."
)

def ask_gemini(user_text: str) -> str:
    response = client.models.generate_content(
        model="gemini-2.0-flash",
        contents=f"{SYSTEM_PROMPT}\n\nUser: {user_text}"
    )
    return response.text

@app.route("/webhook", methods=["GET"])
def verify():
    # Meta verification logic
    if request.args.get("hub.verify_token") == VERIFY_TOKEN:
        return request.args.get("hub.challenge")
    return "Verification failed", 403

@app.route("/webhook", methods=["POST"])
def webhook():
    data = request.get_json()
    try:
        # Extract message text from WhatsApp JSON structure
        message = data["entry"][0]["changes"][0]["value"]["messages"][0]["text"]["body"]
        sender = data["entry"][0]["changes"][0]["value"]["messages"][0]["from"]
        
        ai_response = ask_gemini(message)
        
        # Send reply back to WhatsApp
        requests.post(
            f"https://graph.facebook.com/v17.0/{PHONE_NUMBER_ID}/messages",
            headers={"Authorization": f"Bearer {WHATSAPP_TOKEN}"},
            json={"messaging_product": "whatsapp", "to": sender, "type": "text", "text": {"body": ai_response}}
        )
    except Exception as e:
        print(f"Error: {e}")
        
    return "EVENT_RECEIVED", 200

if __name__ == "__main__":
    app.run(port=5000)

Real-World Implementation Notes

When rolling this out to my colleagues, the biggest hurdle wasn't the code—it was the prompt engineering. Standard LLM responses are too wordy for WhatsApp. I had to iterate on the SYSTEM_PROMPT several times to ensure the agent didn't send "walls of text" that users would just ignore.

For those looking for a more robust AI workflow, I recommend moving from temporary Meta tokens to a Permanent System User token via the Meta Business Suite, otherwise, your bot will die every 24 hours. Using Gemini as a copilot during this process significantly cut down the time spent debugging the nested JSON structure of Meta's webhooks.

pythonWorkflowAI ImplementationAI Agent

All Replies (3)

M
MicroPanda Intermediate 9h ago
I'd recommend adding a Redis cache for session state; otherwise, context windows get messy fast.
0 Reply
S
Sam64 Advanced 9h ago
Tried this with an API wrapper once; managing the token costs was the real headache.
0 Reply
N
NovaOwl Intermediate 9h ago
Did you use a specific framework for the webhook, or just a basic Express server?
0 Reply

Write a Reply

Markdown supported