Setting Up the WhatsApp Web Channel
I’ve found that managing chat integrations can be a real pain when the connection isn’t stable. You want something that stays linked and handles the reconnecting for you without a massive headache. If you are looking to get your logic onto WhatsApp, the built-in Web channel is the most direct path I recommend.
It uses a linked session via the Baileys library, meaning the gateway owns the connection. I suggest using a dedicated number for this to keep your personal chats and your bot logic separate. It makes the onboarding flow much cleaner and prevents you from accidentally talking to yourself.
What You’ll Need
Section titled “What You’ll Need”- A WhatsApp account (dedicated number recommended)
- The OpenClaw CLI
- A phone to scan a QR code
- Access to your configuration file
Quick Start
Section titled “Quick Start”Setting this up takes about five minutes. Here is the path to get your gateway running.
1. Configure WhatsApp access policy
Section titled “1. Configure WhatsApp access policy”First, you need to tell the gateway how to handle incoming messages. Open your config and add the WhatsApp channel settings.
{ channels: { whatsapp: { dmPolicy: "pairing", allowFrom: ["+15551234567"], groupPolicy: "allowlist", groupAllowFrom: ["+15551234567"], }, },}2. Link WhatsApp (QR)
Section titled “2. Link WhatsApp (QR)”Run the login command to generate a QR code. Scan this with your WhatsApp mobile app just like you would for WhatsApp Web.
openclaw channels login --channel whatsappIf you are managing multiple accounts, you can specify which one you are linking:
openclaw channels login --channel whatsapp --account work3. Start the gateway
Section titled “3. Start the gateway”Once linked, start the gateway process. This process owns the socket and handles the reconnect loop.
openclaw gateway4. Approve the pairing request
Section titled “4. Approve the pairing request”If you chose the pairing policy in step 1, you need to manually approve the first request from a new sender.
openclaw pairing list whatsappopenclaw pairing approve whatsapp <CODE>Troubleshooting
Section titled “Troubleshooting”If things aren’t working quite right, check these two common limits:
- Expired Requests: Pairing requests expire after 1 hour. If you miss the window, the sender will need to try again.
- Request Cap: The gateway caps pending requests at 3 per channel. You’ll need to approve or clear existing ones before new ones show up.
If you are using a personal number instead of a dedicated one, the system supports a selfChatMode: true setting. This helps the gateway identify your own number to prevent loops or confusion during runtime.
Need a hand with your specific configuration? Talk to the AI Setup Assistant.
What’s Next
Section titled “What’s Next”Managing bot interactions can get messy fast. I have often found myself in situations where a bot starts replying to everyone in a group or ignores my direct messages because of a misconfigured allowlist. It is frustrating when you just want the bot to talk to specific people or act a certain way when you message yourself.
I want to show you how to set up access control so your bot only responds when and where you want it to.
What You’ll Need
Section titled “What You’ll Need”- A linked WhatsApp account.
- Access to your configuration file (specifically the
channels.whatsappblock). - The E.164-style phone numbers you want to allow.
Quick Start
Section titled “Quick Start”- Set your DM Policy: In your config, define
channels.whatsapp.dmPolicy. Usepairingif you want it to remember users you’ve interacted with. - Define Allowlists: Add authorized numbers to
allowFromusing the E.164 format. - Configure Groups: Use
channels.whatsapp.groupsto limit which groups the bot joins. - Use Activation Commands: In any chat, type
/activation alwaysor/activation mentionto change how the bot triggers in that specific session.
Managing Direct Messages
Section titled “Managing Direct Messages”The channels.whatsapp.dmPolicy setting is your primary tool for controlling direct chat access. I recommend looking at these four options:
pairing(default): Remembers successful interactions.allowlist: Only numbers in yourallowFromlist get through.open: Everyone can message the bot (this requiresallowFromto include"*").disabled: Blocks all direct messages.
If you are using allowFrom, make sure your numbers are in E.164 format. The system normalizes these internally. A few things I’ve noticed about how this works at runtime:
- Pairings are saved in the channel allow-store and merged with your
allowFromconfig. - If you don’t configure an allowlist, your own linked number is allowed by default.
- Outbound
fromMeDMs do not trigger auto-pairing.
Group Access and Sender Policies
Section titled “Group Access and Sender Policies”Group access works in two distinct layers. First, there is the Group membership allowlist found at channels.whatsapp.groups. If you leave this out, the bot can join any group. If you include it, it acts as a filter (though you can use "*" to allow all).
Second, you have the Group sender policy via channels.whatsapp.groupPolicy and groupAllowFrom:
open: Anyone in the group can trigger the bot.allowlist: Only senders matchinggroupAllowFrom(or*) can trigger it.disabled: The bot ignores all inbound messages in groups.
If you don’t set groupAllowFrom, the system falls back to your standard allowFrom list. If you don’t have a channels.whatsapp block at all, the group policy defaults to open.
Mentions and Activation
Section titled “Mentions and Activation”By default, the bot expects a mention in group chats. It looks for a few specific things:
- Explicit WhatsApp mentions of the bot’s identity.
- Regex patterns defined in
agents.list[].groupChat.mentionPatterns(or the fallbackmessages.groupChat.mentionPatterns). - Implicit detection when you reply directly to one of the bot’s messages.
You can change this behavior on the fly using session-level activation commands. These are owner-gated, so only you can run them:
/activation mention/activation always
Note that these commands only update the state for that specific session; they do not change your global configuration file.
Personal Number Behavior
Section titled “Personal Number Behavior”If you add your own linked number to the allowFrom list, the system handles self-chats differently to avoid loops. It will skip read receipts for your own messages and ignore JID auto-triggers that would cause the bot to ping itself. Also, if you haven’t set a messages.responsePrefix, self-chat replies will default to using [{identity.name}] or [openclaw].
Troubleshooting
Section titled “Troubleshooting”The bot isn’t responding to my personal number in a group.
Check if you have restricted the groupAllowFrom list. If that is unset, it falls back to allowFrom. Ensure your number is correctly formatted in E.164.
The bot is replying to everyone in a new group.
If your channels.whatsapp block is missing, the policy defaults to open. Define a groupPolicy of allowlist and specify authorized senders to fix this.
My activation command didn’t save after a restart.
The /activation command only updates the session state. To make a change permanent across all sessions, you must update your global configuration file.
Self-chat replies have a strange prefix.
This happens by design when messages.responsePrefix is unset. You can customize this by defining your own prefix in the messages config block.
For more help setting up your environment, check out the AI Setup Assistant.
What’s Next
Section titled “What’s Next”Parsing raw message data is often a nightmare. When you are building a bot, you want clean text, not a pile of complex metadata that varies every time someone sends a photo or replies to a thread. I found that having a consistent format makes life much easier because you don’t have to write custom logic for every possible message type.
Here is how we handle message normalization and context to keep your bot’s logic simple and predictable.
What You’ll Need
Section titled “What You’ll Need”- An active WhatsApp channel integration.
- Access to your configuration settings (JSON5).
Quick Start
Section titled “Quick Start”Inbound messages are wrapped in a shared envelope to keep things uniform. Here is how to handle the most common scenarios.
1. Handling Quoted Replies
Section titled “1. Handling Quoted Replies”When a user replies to a specific message, we append the context directly to the body. You will see it formatted like this:
[Replying to <sender> id:<stanzaId>]<quoted body or media placeholder>[/Replying]Beyond the text markers, the system populates metadata fields like ReplyToId, ReplyToBody, ReplyToSender, and the sender JID/E.164. This gives you two ways to track the conversation thread.
2. Media and Location Data
Section titled “2. Media and Location Data”If someone sends a file or a location, we don’t leave the message body empty. We use specific placeholders:
<media:image><media:video><media:audio><media:document>
Stickers are marked as <media:sticker>. If a user sends a location or a contact, those payloads are converted into textual context before they even reach your routing logic.
3. Managing Group History
Section titled “3. Managing Group History”For group chats, you can provide the bot with previous messages so it understands the conversation flow. We buffer unprocessed messages and inject them using these markers:
[Chat messages since your last reply - for context][Current message - respond to this]
You can control how many messages are sent by adjusting the history limit. The default is 50. Use channels.whatsapp.historyLimit in your config, or the fallback messages.groupChat.historyLimit. Setting this to 0 will disable the feature.
4. Configuring Read Receipts
Section titled “4. Configuring Read Receipts”By default, the system sends read receipts for accepted messages. If you want to change this, you have two options.
To disable them for everyone:
{ channels: { whatsapp: { sendReadReceipts: false, }, },}If you only want to disable them for a specific account (like a “work” account), use an override:
{ channels: { whatsapp: { accounts: { work: { sendReadReceipts: false, }, }, } }}Note that self-chat turns always skip read receipts, even if you have them turned on globally.
Troubleshooting
Section titled “Troubleshooting”The bot is receiving too much context in group chats
If the message history is overwhelming your logic, check your channels.whatsapp.historyLimit. You can lower this from the default 50 to a smaller number or 0 to stop history injection entirely.
Read receipts are still appearing in self-chats
Actually, the system is designed to skip read receipts for self-chats automatically. If you see them elsewhere and want them gone, ensure your sendReadReceipts flag is set to false in the correct account block.
If you have questions about specific parameters or need help with your configuration, check out the AI Setup Assistant.
What’s Next
Section titled “What’s Next”I have spent a lot of time watching bots fail because a message was too long or a media file was just a bit too heavy. It is frustrating when a response simply disappears because of a technical limit you didn’t see coming. Dealing with message delivery shouldn’t feel like guesswork, so I want to walk you through how to handle text chunking and media properly.
What You’ll Need
Section titled “What You’ll Need”- WhatsApp account IDs added to
channels.whatsapp.accounts - Credentials stored in
~/.openclaw/credentials/whatsapp/ - Access to your agent configuration file
Quick Start
Section titled “Quick Start”You can get your delivery settings dialed in by following these four steps:
- Set your chunking preference: Choose between
lengthornewlinein your config. - Configure reactions: Add the
ackReactionblock to give users immediate feedback. - Define media limits: Set your
mediaMaxMbvalues for both inbound and outbound content. - Verify auth paths: Ensure your account credentials are in the correct subfolders.
Handling Long Text
Section titled “Handling Long Text”WhatsApp has limits on how much text you can send in one go. By default, the limit is 4000 characters, set via channels.whatsapp.textChunkLimit.
I recommend looking at channels.whatsapp.chunkMode. You have two choices:
length: Cuts the text strictly based on the character count.newline: This is usually the better experience. It tries to break messages at paragraph boundaries (blank lines) first. If it can’t find a good break point, it falls back to the length limit.
Media and Optimization
Section titled “Media and Optimization”When you send media, you can use HTTP(S) links, file:// URIs, or local paths. The system handles images, video, audio (PTT voice-notes), and documents.
Here are a few specific behaviors to keep in mind:
- Voice Notes: If you send
audio/ogg, it is automatically rewritten toaudio/ogg; codecs=opusfor better compatibility. - GIFs: If you want a video to play as an animated GIF, set
gifPlayback: true. - Captions: When you send multiple media items in one payload, the caption attaches to the first item.
- Auto-Optimization: Images are resized and quality-adjusted automatically to fit size limits.
The default size limits are 50MB for inbound media (channels.whatsapp.mediaMaxMb) and 5MB for outbound auto-replies (agents.defaults.mediaMaxMb).
Acknowledgment Reactions
Section titled “Acknowledgment Reactions”You can make your bot feel more responsive by using immediate “ack” reactions. These happen as soon as the message is received, before the bot even finishes generating a reply.
{ channels: { whatsapp: { ackReaction: { emoji: "👀", direct: true, group: "mentions", // always | mentions | never }, }, },}This uses channels.whatsapp.ackReaction. Note that the legacy messages.ackReaction is ignored here. If you are in a group, you can set the mode to mentions so it only reacts when the bot is tagged, or always to bypass that check.
Account Management
Section titled “Account Management”If you have multiple accounts, the system looks at channels.whatsapp.accounts. It defaults to the account named default, or the first one it finds if you haven’t specified a default.
Your credentials live at ~/.openclaw/credentials/whatsapp/<accountId>/creds.json. If you ever need to start fresh, you can use the CLI:
openclaw channels logout --channel whatsapp [--account <id>]This clears the authentication state for that specific account. It removes the Baileys auth files but keeps your oauth.json if you are using legacy directories.
Tools and Gates
Section titled “Tools and Gates”The agent can use a react tool to send reactions as an action. You can control these capabilities with specific gates:
channels.whatsapp.actions.reactionschannels.whatsapp.actions.polls
By default, the channel can write configuration changes. If you want to stop this, set channels.whatsapp.configWrites=false.
Troubleshooting
Section titled “Troubleshooting”- Media Send Failures: If a media file fails to send, the system doesn’t just stay silent. It triggers a fallback that sends a text warning instead.
- Reaction Failures: If an acknowledgment reaction fails, it is logged, but it won’t block the actual reply from being delivered.
If you hit a wall with your configuration, check the AI Setup Assistant for help.
What’s Next
Section titled “What’s Next”I’ve been there—you spend time setting up your gateway, you’re ready to see those messages fly, and then nothing happens. Debugging communication tools can be frustrating because there are so many moving parts between your code and the actual chat platform.
I want to help you get past these hurdles quickly. Most of the time, the fix is just a single CLI command or a small tweak in your configuration file. Let’s look at how to get your gateway back on track.
What You’ll Need
Section titled “What You’ll Need”- The
openclawCLI installed and configured. - An active WhatsApp or Telegram gateway setup.
- Access to your terminal to run diagnostic commands.
Quick Start
Section titled “Quick Start”If things aren’t working, follow this 5-minute path to find the cause:
- Check your link status: Run
openclaw channels statusto see if your account is actually connected. - Run the diagnostic tool: Execute
openclaw doctorto identify environment or runtime issues. - Watch the logs: Use
openclaw logs --followto see real-time errors when you try to send or receive messages.
Troubleshooting
Section titled “Troubleshooting”Not linked (QR required)
Section titled “Not linked (QR required)”If your channel status reports that you are “not linked,” the gateway can’t communicate with the provider. You usually need to scan a QR code to fix this.
Fix:
openclaw channels login --channel whatsappopenclaw channels statusLinked but disconnected or in a reconnect loop
Section titled “Linked but disconnected or in a reconnect loop”You might see that your account is linked, but it keeps dropping the connection or attempting to reconnect repeatedly.
Fix: First, check your environment health, then watch the logs for specific error codes:
openclaw doctoropenclaw logs --followIf the loop persists, try re-linking your account using channels login.
No active listener when sending
Section titled “No active listener when sending”If your outbound sends are failing immediately, it usually means there is no active gateway listener for that specific account. Ensure the gateway process is actually running and that the account is properly linked.
Group messages unexpectedly ignored
Section titled “Group messages unexpectedly ignored”If your gateway is working for direct messages but ignoring groups, check your configuration fields in this specific order:
groupPolicygroupAllowFrom/allowFromgroupsallowlist entries- Mention gating settings (
requireMentionand your mention patterns)
Bun runtime warning
Section titled “Bun runtime warning”If you are trying to run the WhatsApp gateway using Bun, you will run into stability issues. The WhatsApp gateway runtime should use Node. Bun is currently flagged as incompatible for stable WhatsApp or Telegram gateway operations.
Configuration Reference Pointers
Section titled “Configuration Reference Pointers”When you need to fine-tune your setup, these are the high-signal fields in your Configuration reference - WhatsApp:
- Access Control:
dmPolicy,allowFrom,groupPolicy,groupAllowFrom,groups - Delivery Settings:
textChunkLimit,chunkMode,mediaMaxMb,sendReadReceipts,ackReaction - Multi-account:
accounts.<id>.enabled,accounts.<id>.authDir, and various account-level overrides - Operations:
configWrites,debounceMs,web.enabled,web.heartbeatSeconds,web.reconnect.* - Session Behavior:
session.dmScope,historyLimit,dmHistoryLimit,dms.<id>.historyLimit
If you are still stuck, you can get help from the AI Setup Assistant.
What’s Next
Section titled “What’s Next”OpenClaw Expert
Still stuck?
If this page didn't answer your case, ask OpenClaw Expert for step-by-step guidance.