Commands, package names, and image names on this page come from the open-source project that Mibyan Desktop is built on, and can differ from the Mibyan Desktop installer. For the supported Mibyan install and update path, see Install and update.
- You need a Meta Business account (not personal WhatsApp).
- The bot operates on a dedicated business phone number, not your personal number.
- The Mibyan gateway needs a public HTTPS URL so Meta can deliver inbound messages via webhook.
- Replies more than 24 hours after the user’s last message require a pre-approved template (this is Meta’s “customer service window” rule, not a Mibyan limit).
Quick start
Prerequisites
- A Meta Business account. Create one at business.facebook.com.
- A Meta app with WhatsApp enabled. See “Creating the Meta app” below.
- A way to expose a local port to the public internet with HTTPS. Cloudflare Tunnel (
cloudflared) is recommended — free, no port forwarding, no domain required. ngrok, your own domain with a reverse proxy + TLS, or a VPS with the gateway directly bound to a public IP all work too. - Optional but recommended: ffmpeg on
PATHso outbound voice messages render as native WhatsApp voice-note bubbles (green waveform) instead of MP3 audio attachments. Mibyan degrades gracefully if absent.
Creating the Meta app
- Go to developers.facebook.com/apps → Create App.
- Choose use case: “Connect with customers through WhatsApp” → Next.
- Pick or create a business portfolio. Review the publishing requirements. Confirm → Create app.
- After creation you’ll land on Customize use case → Connect on WhatsApp → Quickstart. Click Start using the API → you’re now on the API Setup page.
- Make sure a WhatsApp Business Account (WABA) is linked. If you created a new portfolio in step 3, one was auto-created. Verify in the API Setup page.
Permanent token (production)
Temporary access tokens expire after 24 hours, which means a token generated today stops working tomorrow. For production deployments use a System User permanent token:- Go to business.facebook.com/latest/settings → System users (left sidebar).
- Add → name (e.g.
mibyan-bot) → role: Admin. - Select the new user → Assign Assets:
- Select your app → toggle Manage app under Full control.
- Select your WhatsApp account → toggle Manage WhatsApp Business Accounts under Full control.
- Click Assign assets.
- Generate token with these permissions:
business_managementwhatsapp_business_messagingwhatsapp_business_management
- Set token expiration: Never.
- Copy the token → update
WHATSAPP_CLOUD_ACCESS_TOKENin~/.mibyan/.env→ restart the gateway.
Exposing Mibyan to the internet
The Cloud API delivers inbound messages by HTTPS POST to your webhook URL — that means the Mibyan gateway has to be reachable from Meta’s servers. Three common ways:Cloudflare Tunnel (recommended)
Free, no port forwarding, works on Windows / macOS / Linux. Runs as a separate process alongside the gateway. Install:https://<random>.trycloudflare.com URL):
ngrok
Your own domain + reverse proxy
If you already have a server with a TLS cert (Caddy, nginx, etc.), point a route atlocalhost:8090. This is the most stable option for production but requires existing infrastructure.
Configuring the webhook on Meta’s side
Once your tunnel is running:- Note the public URL printed by your tunnel — say
https://abc123.trycloudflare.com. - Generate a Verify Token — the wizard does this for you with
secrets.token_urlsafe(32); if you’re configuring manually, run:Save it asWHATSAPP_CLOUD_VERIFY_TOKENin~/.mibyan/.env. - Start the Mibyan gateway:
mibyan gateway. - In the Meta App Dashboard → WhatsApp → Configuration (or Use cases → Customize → Configuration depending on UI version) → click Edit on the Webhook section.
- Fill in:
- Callback URL:
https://abc123.trycloudflare.com/whatsapp/webhook - Verify Token: the string from step 2 (must match exactly)
- Callback URL:
- Click Verify and save. Meta hits your URL with a GET request, the gateway echoes back the challenge, and Meta marks the webhook as verified.
- Under Webhook fields, click Manage → subscribe to the messages field. This is what tells Meta to actually deliver inbound messages to your webhook.
Recipient whitelist (Meta-side)
In development mode (before your app goes through App Review), Meta restricts which numbers your bot can message:- App Dashboard → WhatsApp → API Setup → To dropdown.
- Click Manage phone number list.
- Add the phone numbers you want to message (yours, your team’s, friendly testers). Meta sends each one a 6-digit verification code via SMS or WhatsApp.
Allowlist (Mibyan-side)
In addition to Meta’s recipient whitelist, Mibyan has its own per-platform allowlist that controls which incoming messages the agent processes. Add to~/.mibyan/.env:
Polishing your bot’s WhatsApp profile
WhatsApp displays a name and profile picture for your bot in the chat header and contact list. These can’t be set via the Cloud API — they live in Meta’s Business Manager. Once your bot is working, head to business.facebook.com/wa/manage/phone-numbers, click your phone number, and you’ll find:
The
mibyan whatsapp-cloud wizard prints these links at the end of setup. None of this is required for the bot to work — it’s pure polish for how your bot appears to users.
Configuration reference
All settings live in~/.mibyan/.env. Required values are in bold.
You can have both the Baileys (
whatsapp) and Cloud (whatsapp_cloud) adapters enabled simultaneously, targeting different phone numbers.
Features
Inbound
- Text messages — passed straight to the agent.
- Images — auto-downloaded and attached to the agent’s input. Models with native vision (Claude, GPT-4o, Gemini, etc.) read the image directly; non-vision models receive an auto-generated text description.
- Voice notes — auto-downloaded as
.ogg, transcribed via your configured STT provider (local faster-whisper, OpenAI/Nous, Groq, etc.), then handed to the agent as text. - Documents — auto-downloaded. Small text-readable files (
.txt,.md,.json,.py,.csv, etc.) up to 100KB get inlined into the agent’s input so it can read them without a tool call. Larger files are cached locally for the agent’s other tools to access. - Button taps — when the user taps a button the bot sent earlier (clarify choice, command approval, slash-command confirm), the tap is routed directly to the right handler. Stale taps fall back to being treated as regular text input.
- Reply context — when the user replies to a previous message, the agent sees the original text as context. Quoting an image, voice note, video or document (yours or one the bot sent, e.g. a cron-delivered chart) also attaches that file to the turn, so “what is this?” under a quoted image works. Meta’s webhook carries only the quoted message id, so this resolves from a local index of recent sends/receives (last 1000 messages per gateway); older quotes arrive without the attachment.
Outbound
- Text — markdown is auto-converted to WhatsApp’s flavored syntax (
**bold**→*bold*,~~strike~~→~strike~, headers → bold,[link](https://github.com/NousResearch/hermes-agent/tree/main/website/docs/user-guide/messaging/url)→link (url)). Long messages split at 4096 chars per chunk. - Images — agent-generated images and local image files both supported, delivered as native photo attachments.
- Voice messages — text-to-speech output is converted via ffmpeg into the native WhatsApp voice-note bubble (green waveform). Without ffmpeg installed, falls back to an MP3 audio attachment. See “Voice messages” below.
- Video / documents — both supported, sent as native attachments.
Interactive UX
When the agent invokes any of these flows, Mibyan uses WhatsApp’s native interactive messages — tap-to-answer buttons instead of “reply with the number” prompts:clarifytool — multi-choice questions render as quick-reply buttons (1–3 choices) or a tap-to-open list sheet (4+ choices). Picking “✏️ Other” lets the user type a free-form answer that the agent receives as the resolution.- Dangerous-command approvals — when the agent’s terminal/code execution hits a gated command, the user sees
✅ Approve/❌ Denybuttons instead of needing to type/approveor/deny. - Slash-command confirmations — privileged commands like
/reload-mcpshow✅ Approve Once/🔒 Always/❌ Cancelbuttons.
Read receipts and typing indicator
Mibyan acknowledges inbound messages immediately:- Your message shows blue double-checkmarks as soon as the gateway receives it.
- The bot’s name in your WhatsApp chat shows “typing…” while the agent is preparing a reply.
- The typing indicator auto-dismisses when the bot’s first response message arrives.
Voice messages
WhatsApp distinguishes between a “voice note” (the green waveform bubble) and a generic audio file attachment. The difference is purely codec: voice notes need to beaudio/ogg with opus encoding.
Mibyan TTS produces MP3. Two paths:
- With ffmpeg on PATH (recommended) — outbound TTS is converted and arrives as a proper voice note. Install:
- Windows:
winget install Gyan.FFmpeg - macOS:
brew install ffmpeg - Linux: package manager
- Windows:
- Without ffmpeg — outbound TTS arrives as an MP3 audio attachment. Plays fine, just doesn’t look like a voice note. A one-time warning fires in the gateway log so you know.
Known limitations
24-hour conversation window
Meta only allows free-form messages within a 24-hour window after the user’s last inbound message. Outside that window, the only thing Meta’s API accepts is a pre-approved message template. What this means in practice:- Reactive chat (user DMs → bot replies within 24h → user replies → …) works forever. This covers >95% of normal bot use.
- Cron jobs that deliver to WhatsApp after a gap > 24h will fail with Graph error code
131047(“Re-engagement message”). - Long-running
delegate_taskasync results that take longer than 24h fail the same way. - Webhook subscribers that route external events to WhatsApp fail when the user hasn’t DM’d the bot recently.
Group chats
The Cloud API has limited group support (capability-tier gated by Meta). Mibyan’swhatsapp_cloud adapter currently handles direct messages only in v1. If you need group chats, use the Baileys bridge.
Outbound rate limit
Meta’s default throughput is 80 messages/second per business phone number, with upgrades available. Mibyan doesn’t currently enforce this client-side — extremely high-volume sends could hit Meta’s limit.Troubleshooting
Setup verification fails (“URL couldn’t be validated”) in Meta dashboard
Almost always one of:- Tunnel URL is wrong or stale — cloudflared quick tunnels rotate. Get a fresh URL and update both
.envand Meta’s dashboard. - Verify token mismatch — the token in
~/.mibyan/.env’sWHATSAPP_CLOUD_VERIFY_TOKENmust match exactly what you typed into Meta’s dashboard. Run the curl probe above to confirm the gateway’s verify handshake works locally first. - Gateway not running — check
mibyan gatewayis up. - App Secret not set — without it, Mibyan refuses inbound POSTs with 503. Meta interprets that as “can’t validate.”
graph error 100: Object with ID ’…’ does not exist
You pasted your phone number (10-11 digits) into WHATSAPP_CLOUD_PHONE_NUMBER_ID instead of the Phone Number ID (Meta’s 15-17 digit internal ID). Re-check the API Setup page — the Phone Number ID is shown below the “From” dropdown.
The wizard catches this with a validator now, but it’s worth knowing if you’re configuring manually.
graph error 190: Authentication Error
Your access token is invalid. Subcodes:
subcode 463— token expired. Temp tokens last 24h. Regenerate, or switch to a System User permanent token (see above).subcode 467— token invalidated (revoked or password changed).- Other 190 — token didn’t have the required permissions when generated. Make sure all three (
business_management,whatsapp_business_messaging,whatsapp_business_management) were selected.
graph error 131047: Re-engagement message
The 24-hour conversation window expired (see “Known limitations”). Either:
- Ask the user to DM the bot first to reopen the window.
- Wait for template support to land in Mibyan.
Inbound message: media metadata fetch failed (status=401)
Same 401 root causes as outbound (graph error 190) — the access token is invalid or expired. Fix the token.
Bot replies appear as raw JSON / tool-call leakage
Common cause: the toolset configured forwhatsapp_cloud is missing the tools the agent wants to call. Check mibyan tools list and verify the platform is using mibyan-whatsapp (the default Cloud adapter toolset, same as Baileys).
If the model emits tool-call-shaped text instead of a structured call, it usually means the toolset was effectively empty. See mibyan_cli/platforms.py for the platform → default toolset mapping.
STT (voice note transcription) returns empty / “could not transcribe”
The defaultstt.provider: local requires python -c "import pm; pm.sync_venv(['stt-whisper'], explicit=True)". If you’re a Nous subscriber, you can route STT through the managed gateway instead — select Nous Subscription for speech-to-text in mibyan tools, or set it directly:
stt.use_gateway true — that flag is legacy; the provider selection alone controls routing now.)
Security notes
- Treat the App Secret like a password — anyone with it can forge webhook payloads that Mibyan will accept as authentic.
- The verify token is a shared secret — leaks are lower-stakes (worst case someone could re-subscribe Meta’s webhook to a different URL of theirs), but still avoid committing it.
- The access token is your bot’s identity — System User tokens are equivalent to long-lived API keys. Rotate immediately if a deployment is compromised.
- The webhook endpoint accepts only signed requests when
WHATSAPP_CLOUD_APP_SECRETis set — leave it set even in development. Without it, the gateway refuses inbound delivery with HTTP 503. - The
/healthendpoint is unauthenticated — it’s safe to expose because it only reports config-presence booleans, not the values themselves. But if you’d rather not surface it, restrict access at the reverse proxy / tunnel layer.
Comparison to the Baileys bridge
Most users running Mibyan for personal projects prefer Baileys. Most users running customer-facing bots prefer Cloud API.
See also
- Meta’s official WhatsApp Business Cloud API docs — authoritative reference for the underlying platform, pricing, App Review, and Meta-side rate limits.
- WhatsApp (Baileys bridge) Setup — the alternative integration for personal projects.
- Messaging Platforms overview — all messaging integrations at a glance.

