Build a Task-Specific WhatsApp AI Agent (Cloud API + Claude + RAG, 2026) — Cesar Ayala
← All posts

Build a Task-Specific WhatsApp AI Agent (Cloud API + Claude + RAG, 2026)

Build a task-specific WhatsApp agent for customer service, orders, or appointments. Receive messages via the Cloud API webhook, ground each reply in your business data with RAG so Claude never invents prices, reply inside the 24-hour window, and hand off to a human when confidence is low. That's exactly what Meta now allows.

Did Meta really ban chatbots on WhatsApp? (and why that’s good news)

If you sell anything in Mexico, WhatsApp is your storefront, your phone line, and your checkout counter all at once. So when Meta changes the rules of the WhatsApp Business Platform, it matters here more than almost anywhere.

Short answer: Meta banned general-purpose chatbots on WhatsApp effective January 15, 2026, but task-specific business agents — customer service, order status, appointment booking — are explicitly allowed and encouraged. So the agent a Mexican PyME actually wants is the compliant one. This guide shows you how to build it: a narrow, RAG-grounded WhatsApp agent that never invents a price and hands off to a human when unsure.

Here’s what happened. In October 2025 Meta updated its Business Platform terms to ban general-purpose chatbots, effective January 15, 2026. The target is AI providers distributing their general-purpose assistants on WhatsApp — think OpenAI’s ChatGPT, Perplexity, Luzia, or Poke. Meta’s reasoning, in its own words, is that these bots generated enormous message volume and system load while the platform was built for business-to-customer communication, not as a distribution channel for AI products. New API accounts registering on or after October 15, 2025 were subject immediately; existing accounts had until January 15, 2026 to comply (TechCrunch, WhatsApp Business policy).

Now read the other half of the same policy, because this is the part that matters for you: AI bots built for specific, structured business tasks — customer service, order inquiries and status, appointment booking — are not just allowed, they’re explicitly encouraged. A travel company’s customer-service bot is the kind of example Meta itself uses as permitted.

One honest caveat so you have the full picture: enforcement is contested. Brazil’s competition regulator (CADE) ordered Meta to suspend the policy with an injunction on January 12, 2026, Italy did the same, and Meta carved out exemptions in those markets while antitrust investigations proceed.

My take as someone who ships these for a living: this policy is a green light, not a roadblock. The thing you actually want to build for a Mexican PyME — a narrow agent that answers questions, checks orders, and books appointments — is precisely the category Meta wants on the platform. The “banned” headline is scary; the reality is that the right way to build was already the compliant way to build.

The Jan 15, 2026 WhatsApp policy at a glance

BannedGeneral-purpose AI assistants (ChatGPT, Perplexity, Luzia, Poke)
Allowed and encouragedTask-specific business agents: service, orders, appointments
EffectiveJan 15, 2026 (new accounts since Oct 15, 2025)
Meta's reasonGeneral bots drove huge volume and load without platform revenue
Honest nuanceBrazil (CADE, Jan 12, 2026) and Italy ordered a suspension; Meta exempted both
As of 2026. Enforcement is contested in some markets — see Brazil/Italy below.

What are we building? A grounded agent for service, orders, and appointments

The single most important design decision is scope. Pick one or two concrete jobs — for example, answer FAQs plus check order status, with appointment booking as a stretch. Narrow scope is what keeps you compliant (it’s unmistakably task-specific) and what keeps you reliable (less surface area to get wrong).

The agent has four moving parts:

  1. A WhatsApp Cloud API webhook to receive and send messages.
  2. A RAG knowledge base holding your real business data — FAQ, catalog, prices, hours, policies.
  3. Claude as the brain, grounded strictly on the retrieved context.
  4. A confidence-gated human handoff for anything out of scope or low-confidence.

The runtime flow is linear: a customer message hits your Cloud API webhook, RAG retrieves the relevant business context, Claude drafts an answer grounded in only that context, a confidence check decides whether to send the reply inside the 24-hour window or hand off to a human.

For Mexico and LATAM, build it Spanish-first: your system prompt and knowledge base are in Spanish, and the agent simply answers in whatever language the customer writes in. In the examples below I use Node.js for the webhook, pgvector for retrieval, and the Anthropic Messages API for Claude.

How do you connect the WhatsApp Cloud API webhook?

The Cloud API is Meta’s official API. It’s free to start, needs no third-party BSP, and is built on the Graph API. Use the current version — v23.0 is a reasonable example as of 2026, but always confirm the latest in Meta’s changelog before you ship.

Two things happen at your webhook. First, verification: when you register the webhook, Meta sends a GET request with hub.mode, hub.verify_token, and hub.challenge. You check that hub.verify_token equals the token you configured, then echo back the hub.challenge value with HTTP 200. If it doesn’t match, return 403.

Second, receiving: Meta POSTs inbound messages to the same URL. The message lives at entry[].changes[].value.messages[], and value.metadata.phone_number_id tells you which of your numbers received it.

The one rule you cannot break: return 200 fast and process async. If you’re slow, Meta retries and you’ll handle the same message twice.

import express from "express";
const app = express();
app.use(express.json());

const VERIFY_TOKEN = process.env.VERIFY_TOKEN;

// 1. Webhook verification (GET)
app.get("/webhook", (req, res) => {
  const mode = req.query["hub.mode"];
  const token = req.query["hub.verify_token"];
  const challenge = req.query["hub.challenge"];
  if (mode === "subscribe" && token === VERIFY_TOKEN) {
    return res.status(200).send(challenge);
  }
  return res.sendStatus(403);
});

// 2. Receive messages (POST) — ack fast, work later
app.post("/webhook", (req, res) => {
  res.sendStatus(200); // respond first so Meta does not retry
  const value = req.body.entry?.[0]?.changes?.[0]?.value;
  // The same webhook also delivers value.statuses[] (sent/delivered/read)
  // events, which have no value.messages — this branch correctly skips them.
  const msg = value?.messages?.[0];
  if (msg?.type === "text") {
    queueReply({
      phoneNumberId: value.metadata.phone_number_id,
      from: msg.from,
      text: msg.text.body,
    });
  }
});

Step 2: The 24-hour window — your one hard constraint

WhatsApp messaging revolves around a single rule, and once you internalize it the whole design falls into place.

An inbound message from a customer opens a 24-hour customer service window. Inside that window you can send free-form messages — exactly what a conversational AI agent needs. Better still, every new inbound message resets the 24-hour timer, so an active conversation stays open as long as the customer keeps replying.

Outside the window, you may only send pre-approved Message Templates (categories: Authentication, Utility, Marketing). No free-form text.

The design implication is clean: the agent thrives inside the window, so reply promptly and keep the conversation alive. Use templates only to re-open a conversation you initiate — an appointment reminder, an order-ready notice. On billing, WhatsApp moved to per-message pricing in July 2025; rates change, so confirm current numbers in your Meta dashboard (as of 2026).

End-to-end runtime flow

Customer messageInbound WhatsApp text opens the 24h window
Cloud API webhookAck 200 fast, process async
RAG retrievalTop-k chunks from your business data
Grounded Claude replyAnswers only from retrieved context
Confidence checkBranch on confidence + scope
Send or hand offFree-form reply in window, or human takeover
Every inbound message resets the 24h window, so prompt replies stay free-form.

How do you stop the agent from inventing prices? Ground it with RAG

This is the part that earns trust, and it’s where most homemade bots fail. A bare LLM will happily invent a price, a return policy, or store hours that sound plausible and are completely wrong. The fix is retrieval-augmented generation.

Embed your business knowledge — FAQ, catalog, prices, hours, policies — into a vector store like pgvector. For each incoming message, retrieve the top-k relevant chunks and pass only that context to Claude. Then put the grounding rule in the system prompt, not the user turn:

Answer strictly from the provided context. If the answer isn’t in it, do not guess — say you’ll connect a human.

That one rule does double duty. It stops the bot from inventing a price or a policy (trust), and it keeps the bot firmly inside its task-specific lane (compliance). Trust and compliance come from the same discipline. I go deeper on this in How to build an AI chatbot without hallucinations, and on why retrieval — not fine-tuning — is the right tool for a business agent in RAG vs fine-tuning.

import anthropic

client = anthropic.Anthropic()

def answer(user_text, top_k_chunks):
    context = "\n\n".join(top_k_chunks)  # retrieved from pgvector
    system = (
        "Eres el asistente de atención de la tienda. "
        "Responde SOLO con la información del contexto. "
        "Si no está en el contexto, no inventes: di que conectarás "
        "a una persona. Responde en el idioma del cliente.\n\n"
        f"CONTEXTO:\n{context}"
    )
    resp = client.messages.create(
        model="claude-haiku-4-5",   # high-volume, cost-efficient
        max_tokens=400,
        system=system,
        messages=[{"role": "user", "content": user_text}],
    )
    return resp.content[0].text

On model choice: Claude Haiku 4.5 is my default for high-volume customer chat because the economics matter when you’re answering thousands of messages — and Haiku is plenty for grounded retrieval Q&A. Reach for Sonnet 4.6 only when a conversation needs harder reasoning. For real actions like looking up an order, checking availability, or creating an appointment, wire them as Claude tool-use functions against your systems; connecting an agent to your data and tools covers that pattern end to end.

Step 4: Reply through the Cloud API (inside the window)

Sending is a single POST. Hit https://graph.facebook.com/<version>/{phone-number-id}/messages with a Bearer token and a small JSON body.

async function sendText(phoneNumberId, to, body) {
  await fetch(
    `https://graph.facebook.com/v23.0/${phoneNumberId}/messages`,
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${process.env.WHATSAPP_TOKEN}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        messaging_product: "whatsapp",
        to,
        type: "text",
        text: { body },
      }),
    }
  );
}

Because we’re replying inside the 24-hour window the customer opened, this free-form text needs no template approval — you just send it. That’s the whole reason promptness matters: stay in the window and you keep the natural, conversational experience without template overhead.

Step 5: Hand off to a human when confidence drops

A good agent knows what it doesn’t know. Escalate to a human when: the agent is low-confidence, the request is out of scope, the customer sounds frustrated, or the customer explicitly asks for a person.

The mechanism is straightforward: notify a human agent, pause the bot for that conversation so it stops replying, and hand over the transcript and context so the person has full continuity and the customer never repeats themselves.

RAG makes the handoff natural rather than bolted-on. If retrieval returns nothing relevant, the agent has already been told not to guess — so the no-answer path is the handoff trigger. My opinion, plainly stated: the handoff is not a failure mode, it’s the feature that earns customer trust and keeps your agent firmly in the permitted, task-specific lane. A bot that gracefully says “let me get a person for that” beats a bot that confidently lies, every single time.

Build it end to end

  1. Cloud API + webhookGET verify, POST receive, ack 200 fast
  2. RAG knowledge baseEmbed FAQ/catalog/prices into pgvector
  3. Grounded Claude replyTop-k context + strict system prompt
  4. Human handoffConfidence-gated escalation with transcript
Ship in this order; each step is independently testable.

FAQ

Is my business agent banned by the January 15, 2026 policy? No. The ban targets general-purpose AI assistants. A task-specific agent for customer service, orders, or appointments is exactly what Meta allows and encourages.

What’s the deal with Brazil and Italy? Brazil’s CADE ordered Meta to suspend the policy with an injunction on January 12, 2026, Italy did the same, and Meta exempted both markets amid antitrust scrutiny. Enforcement is genuinely contested — but building a task-specific, grounded agent keeps you safe regardless of how that shakes out.

Do I need a paid BSP like Twilio or 360dialog? No. The Cloud API is free to start and you can build directly on it. A BSP is optional convenience, not a requirement.

How much does it cost to send messages? WhatsApp uses per-message billing (since July 2025), plus your Claude API tokens. Confirm current WhatsApp rates in the Meta dashboard, since pricing is time-sensitive. I break down the chat-volume math in how much it costs to add AI to your app.

Which Claude model should I use? Claude Haiku 4.5 for high-volume cost efficiency; Sonnet 4.6 when a conversation needs harder reasoning.

How do I stop it from inventing prices? RAG grounding plus the strict system-prompt rule: answer only from retrieved context, otherwise hand off to a human. No retrieved fact, no claimed fact.

Can it actually book appointments or check orders? Yes. Wire those as Claude tool-use functions that call your booking system or order database, so the agent takes real action instead of just talking about it.

General-purpose chatbot vs task-specific grounded agent

General-purpose chatbot

  • Banned by Meta as of Jan 15, 2026
  • Invents prices, policies, and hours
  • Unbounded scope, hard to trust
  • Built to distribute an AI product

Task-specific grounded agent

  • Allowed and encouraged by Meta
  • Answers only from retrieved context
  • Narrow scope: service, orders, appointments
  • Hands off to a human when unsure
The compliant build and the trustworthy build are the same build.

Ship the compliant agent your customers will trust

Here’s the through-line: a narrow, RAG-grounded WhatsApp agent is both trustworthy — it never invents a price — and compliant — it’s unmistakably task-specific. The same discipline buys you both. You don’t trade one for the other.

For Mexican and LATAM PyMEs, the timing is good. WhatsApp is the business channel here, the permitted pattern is now crystal clear, and the tooling is free to start. Begin with one job — FAQ plus order status — ground it in your real data, add the handoff, then expand. And before you go live, always confirm the current Graph API version and WhatsApp pricing in Meta’s dashboard and changelog.

Want more builder guides on shipping agents that actually work in production? They’re all in AI agents.