Run mibyan gateway setup and pick WhatsApp for a guided walk-through.
Two Modes
Prerequisites
- Node.js v18+ and npm — the WhatsApp bridge runs as a Node.js process
- A phone with WhatsApp installed (for scanning the QR code)
Step 1: Run the Setup Wizard
- Ask which mode you want (bot or self-chat)
- Install bridge dependencies if needed
- Display a QR code in your terminal
- Wait for you to scan it
- Open WhatsApp on your phone
- Go to Settings → Linked Devices
- Tap Link a Device
- Point your camera at the terminal QR code
Step 2: Getting a Second Phone Number (Bot Mode)
For bot mode, you need a phone number that isn’t already registered with WhatsApp. Three options:
After getting the number:
- Install WhatsApp on a phone (or use WhatsApp Business app with dual-SIM)
- Register the new number with WhatsApp
- Run
mibyan whatsappand scan the QR code from that WhatsApp account
Step 3: Configure Mibyan
Add the following to your~/.mibyan/.env file:
~/.mibyan/config.yaml:
unauthorized_dm_behavior: pairis the global default. Unknown DM senders get a pairing code.whatsapp.unauthorized_dm_behavior: ignoremakes WhatsApp stay silent for unauthorized DMs, which is usually the better choice for a private number.
Group chats (bot mode)
Groups are gated by group policy, not by the DM allowlist.WHATSAPP_GROUP_POLICY / whatsapp.group_policy
defaults to pairing, which forwards nothing from groups. allowlist plus WHATSAPP_GROUP_ALLOWED_USERS /
whatsapp.group_allow_from (comma-separated group JIDs, e.g. 120363001234567890@g.us) admits the listed
groups; open admits every group the bot is a member of. The sender is then checked like any other gateway
principal: with WHATSAPP_ALLOWED_USERS set, a participant must be on it (or paired) — a sender WhatsApp
addresses by LID matches through the phone number Baileys supplies alongside it, so a first contact with no
lid-mapping file yet is not dropped; with no sender allowlist,
allowlist trusts the group-JID list alone and admits every participant of a listed group, while open still
needs the participant paired or WHATSAPP_ALLOW_ALL_USERS=true. By default the bot answers every admitted group
message; set require_mention: true / WHATSAPP_REQUIRE_MENTION=true to answer only @mentions, replies to the
bot, or /commands (groups in free_response_chats are exempt).
Then start the gateway:
Session Persistence
The Baileys bridge saves its session under~/.mibyan/platforms/whatsapp/session. This means:
- Sessions survive restarts — you don’t need to re-scan the QR code every time
- The session data includes encryption keys and device credentials
- Do not share or commit this session directory — it grants full access to the WhatsApp account
Re-pairing
If the session breaks (phone reset, WhatsApp update, manually unlinked), you’ll see connection errors in the gateway logs. To fix it:Voice Messages
Mibyan supports voice on WhatsApp:- Incoming: Voice messages (
.oggopus) are automatically transcribed using the configured STT provider: localfaster-whisper, Groq Whisper (GROQ_API_KEY), or OpenAI Whisper (VOICE_TOOLS_OPENAI_KEY) - Outgoing: TTS responses are sent as MP3 audio file attachments
- Agent responses are prefixed with ”☤ Mibyan” by default. You can customize or disable this in
config.yaml:
send_read_receipts is true, the adapter marks policy-accepted inbound messages as read after DM/group/mention filtering passes. Rejected messages (e.g., from non-allowlisted senders) are not marked read. Disabled by default for privacy. Changing this setting automatically restarts the bridge subprocess on the next connection.
Message Formatting & Delivery
WhatsApp supports streaming (progressive) responses — the bot edits its message in real-time as the AI generates text, just like Discord and Telegram. Internally, WhatsApp is classified as a TIER_MEDIUM platform for delivery capabilities.Chunking
Long responses are automatically split into multiple messages at 4,096 characters per chunk (WhatsApp’s practical display limit). You don’t need to configure anything — the gateway handles splitting and sends chunks sequentially.WhatsApp-Compatible Markdown
Standard Markdown in AI responses is automatically converted to WhatsApp’s native formatting:
Code blocks and inline code are preserved as-is since WhatsApp supports triple-backtick formatting natively.
Tool Progress
When the agent calls tools (web search, file operations, etc.), WhatsApp displays real-time progress indicators showing which tool is running. This is enabled by default — no configuration needed.Native Polls, Clarify-as-Poll, and Locations
The Baileys-bridge adapter (bot mode) supports several native WhatsApp message types:- Polls — the agent can send a native WhatsApp poll (question + options) via the bridge’s
/send-pollendpoint. Poll votes flow back into the conversation. - Clarify questions as polls — when the agent asks a multiple-choice clarify question, it’s rendered as a native single-select poll; tapping an option answers the question. If the poll fails to send, the adapter falls back to a plain text question. Approval prompts are never mapped onto polls — polls are only used for genuine multiple-choice clarifies.
- Location pins — the agent can send a native location pin (latitude/longitude, optional name/address) via
/send-location, and incoming shared locations (including live locations) are delivered to the agent as location messages.
Message Batching (Debounce)
WhatsApp delivers each message individually, so a rapid burst (forwarded batches, paste-splits, multi-line text) would otherwise trigger a separate agent invocation per fragment — wasting tokens and producing several disjointed replies. The adapter buffers successive text messages from the same chat and dispatches them as one combined request after a short quiet period (default 0.3s, extended to 1s for very long fragments; capped at 2s / 4s). Tune viaconfig.yaml:
text_batch_delay_seconds: 0 to dispatch each message immediately (disables batching).
Quoted Replies
Replying to (quoting) an earlier message gives the agent the quoted text as context. Quoting an image, voice note, video or document also attaches that file to the turn, so “what is this?” under a quoted image works — whether the attachment came from another person or from the bot itself (a cron-delivered chart, a generated image). WhatsApp only ships a thumbnail stub with a quote, so the file is resolved from the bridge’s download cache (inbound media, in-memory for the bridge’s lifetime) or from a local index of the bot’s own sends (last 1000 messages); quotes of anything older arrive without the attachment.Troubleshooting
Security
By default, unauthorized DMs still receive a pairing code reply. If you want a private WhatsApp number to stay completely silent to strangers, set:- The
~/.mibyan/platforms/whatsapp/sessiondirectory contains full session credentials — protect it like a password - Set file permissions:
chmod 700 ~/.mibyan/platforms/whatsapp/session - Use a dedicated phone number for the bot to isolate risk from your personal account
- If you suspect compromise, unlink the device from WhatsApp → Settings → Linked Devices
- Phone numbers in logs are partially redacted, but review your log retention policy

