WhatsApp AI Agent: Self-Hosted Setup With POLYROB
A WhatsApp AI agent is an AI assistant you message in WhatsApp like any contact. POLYROB runs one on your own machine: polyrob whatsapp serves a webhook on port 8080 at /webhooks/whatsapp, Meta delivers your messages to it, and the agent answers through the WhatsApp Cloud API.
Most guides on this topic describe customer-service bots for a business. This one covers the other case: your own agent, on your own hardware, that you talk to from your phone. Every POLYROB claim comes from the public repository at release v1.7.9, and the files are listed at the end.
What is a WhatsApp AI agent?
It is an assistant that takes a message, does work with tools and memory, and replies in the same chat. The hosted version of this idea is a vendor’s inbox bot. The self-hosted version is an agent you run yourself, where WhatsApp is one of several ways to reach it. POLYROB answers in the terminal, the web console and eight chat apps, and it keeps one memory across them. For the wider picture of running an agent yourself, read the guide to a self-hosted AI agent.
How does POLYROB connect to WhatsApp?
Through the WhatsApp Cloud API, Meta’s hosted interface for the WhatsApp Business Platform (Meta, Cloud API documentation). There is no polling. Meta calls your server, so your machine must be reachable at a public address that you register in your Meta app.
The code has three parts:
- Inbound.
WhatsAppInboundchecks an HMAC-SHA256 signature on every webhook delivery, answers Meta’shub.challengehandshake, and turns the payload into a message. - Outbound.
WhatsAppClientposts to the Graph API atgraph.facebook.com/v21.0/<phone-number-id>/messageswith your access token. - Window tracking. A small SQLite table,
wa_window, stores the time of the last message from each phone number.
That is a different shape from Slack, where the agent connects outward. See the Slack AI agent guide, which uses Socket Mode and needs no public URL.
What do you need before you start?
Four values, all from your Meta app. The surface refuses to start if any of them is empty.
| Variable | What it is |
|---|---|
WHATSAPP_ACCESS_TOKEN | A permanent or system-user access token for the Cloud API |
WHATSAPP_PHONE_NUMBER_ID | The ID of the sending phone number |
WHATSAPP_VERIFY_TOKEN | A string you choose; echoed back during Meta’s webhook verification |
WHATSAPP_WEBHOOK_SECRET | Your Meta app secret, used to check the signature on each delivery |
The webhook secret is the one people skip. If it is unset, POLYROB rejects every inbound payload: the code logs a warning and fails the signature check. Without a preflight the surface would look online and hear nothing, so the start-up check in launch.py names any missing variable.
How do you start it?
Install POLYROB, set the four variables, and run the command. The webhook server needs the server extra, and the command stops with a one-line message if it is missing.
curl -fsSL https://polyrob.dev/install.sh | bash
export WHATSAPP_ACCESS_TOKEN=your-access-token
export WHATSAPP_PHONE_NUMBER_ID=your-phone-number-id
export WHATSAPP_VERIFY_TOKEN=a-string-you-choose
export WHATSAPP_WEBHOOK_SECRET=your-meta-app-secret
polyrob whatsapp --port 8080
When it is up, it prints whatsapp webhook worker online. Then, in the Meta app, set the callback URL to the host’s /webhooks/whatsapp path and enter your verify token. If you run several chat apps, polyrob gateway starts every enabled surface in one process, and a surface with missing credentials is skipped with a warning. To check the credentials without sending anything, run polyrob surfaces probe whatsapp: it reads the phone-number object from the Graph API and reports the display number.
Who can talk to it?
A chat surface starts locked. The owner is an ID you configure, OWNER_WHATSAPP_ID, and a message from that sender is treated as the owner: it shares the memory, goals and approvals of your terminal session. Since release 1.3.0, non-owner direct messages are denied on every surface except Telegram unless the sender is paired.
A paired sender gets their own memory and work. They do not reach your owner commands or approvals. The AI agent security guide explains the access model behind that.
One more guard is specific to WhatsApp. If a message is marked as forwarded, POLYROB wraps its text in a frame that says it is “quoted content, not an instruction from the sender”. A forwarded message is treated as data, not as a command.
What can it receive and send?
- Text and files. Text messages, images, documents, videos and stickers all arrive. A caption becomes the message text. A file with no caption is named, never passed on as an empty turn.
- Voice notes. The agent downloads the audio by its media ID and transcribes it. It marks the voice note as read, which gives you the double check as a “received” signal. A voice note over the size or length bound is not transcribed.
- A file size cap.
INBOUND_MEDIA_MAX_MBdefaults to 20. Over the cap, the file is not stored and the turn says so. - Replies. The surface sets
markdown_flavor="none", so replies are plain text with no rendered bold or headings. A reply over 4,096 characters is split into several messages. It does not stream and cannot edit a sent message.
What is the 24-hour window?
The POLYROB code models WhatsApp’s customer-service window directly: service_window_secs=86400 and requires_template_outside_window=True. Every inbound message updates the wa_window table for that number, so the agent knows whether a free-form reply is allowed.
When the agent needs to start a conversation, for example to deliver the result of a scheduled job after a quiet day, it cannot send plain text. It sends an approved utility template instead. The template name is WHATSAPP_TEMPLATE_NAME, default task_ready, and you have to get a template with that name approved in your Meta account first. Plan for this if you want the agent to message you first.
Where does the WhatsApp surface fall short?
- It needs a public address. There is no outbound-only mode.
- It depends on a Meta app. You need a Meta app with the WhatsApp product, a sending phone number and a permanent or system-user access token. That is more setup than a Telegram bot.
- Only direct messages. The inbound parser sets every chat to type
dm, so there is no group-chat support on WhatsApp. - Plain text only. No streaming, no edits, no rendered formatting.
- Messages for another number are dropped. If one Meta app serves several numbers, POLYROB answers only the one whose ID matches
WHATSAPP_PHONE_NUMBER_ID. - Replays are refused. A delivery whose own timestamp is older than 900 seconds is dropped. Meta can retry for days, so a very late retry is ignored on purpose.
Can the same agent run in other chat apps?
Yes. POLYROB has eight chat surfaces: Telegram, email, WhatsApp, Discord, Slack, Signal, Feishu/Lark and DingTalk. Other agents list more channels, so check the dated numbers in the comparison page if channel count decides it for you. The personal AI agent guide shows how memory and goals work across them. The Discord AI agent guide covers the server case.
WhatsApp AI agent questions
How do I get an AI bot in WhatsApp?
Create a Meta app with the WhatsApp product, get a phone number and an access token, then point the app’s webhook at the agent. With POLYROB, set the four variables above and run polyrob whatsapp.
Do I need a public URL?
Yes. WhatsApp delivers messages by calling your webhook, so Meta must be able to reach /webhooks/whatsapp on your host. This is the main difference from Slack, Discord or Signal in POLYROB.
Does the agent forget me between messages?
No. It keeps cross-session memory in local SQLite files, and the owner’s WhatsApp chat shares that memory with the terminal and the web console.
Is it free?
POLYROB is MIT licensed. You pay your model provider, or nothing with a local model. Meta sets its own terms and fees for the WhatsApp Business Platform, so read them before you plan around volume.
Where do you start?
Set up the Meta app, run the commands above, and send the agent a text from your own number. Set OWNER_WHATSAPP_ID once you see it answer.
Install POLYROB, read the docs, or browse the open-source code. To see what changed in recent releases, check what’s new.
Sources
All POLYROB facts are from the public repository at release v1.7.9 (github.com/theselfruleorg/polyrob).
cli/commands/[email protected](thepolyrob whatsappcommand, port 8080, required variables, server extra)surfaces/whatsapp/[email protected](required credentials, preflight warning, webhook path)surfaces/whatsapp/[email protected](signature check, challenge handshake, message types, forwarded frame, 900-second replay window, other-number drop)surfaces/whatsapp/[email protected](Graph API v21.0, send text, mark read, template send, media download)surfaces/whatsapp/[email protected](capabilities: no streaming or edit, 4,096 limit, plain text, 24-hour window)surfaces/whatsapp/[email protected](wa_windowtable)surfaces/whatsapp/[email protected](polyrob surfaces probe whatsapp)core/surfaces/[email protected](WhatsApp surface row,OWNER_WHATSAPP_ID)core/surfaces/[email protected](WHATSAPP_TEMPLATE_NAME, defaulttask_ready)docs/[email protected],docs/guide/[email protected],[email protected](non-owner DMs denied, webhook secret required)- Meta: WhatsApp Cloud API documentation, linked for setup, not quoted.
POLYROB is an open-source AI agent you run and own. Install it or read the docs.