WhatsApp Channel Setup
This guide describes the WhatsApp integration currently implemented in this repo.
Architecture
JiuwenSwarm does not talk to WhatsApp directly from Python.
WhatsApp app <-> Baileys bridge (Node.js) <-> WhatsAppChannel (Python)
- Bridge WebSocket default:
ws://127.0.0.1:19600/ws - Bridge script:
jiuwenswarm/scripts/whatsapp-bridge.js - Python channel:
jiuwenswarm/channel/whatsapp_channel.py - Runtime config:
channels.whatsappinconfig.yaml
What This Repo Implements
- The Node bridge uses Baileys to log in to WhatsApp Web and send/receive messages.
- The Python channel connects to the local bridge over WebSocket and exchanges JSON frames.
- The Python side now tracks connection state from bridge events and only sends messages when WhatsApp is actually connected.
allow_fromfilters inbound WhatsApp senders by JID or by the number part.
What This Repo Does Not Implement
- There is no Python-to-bridge auth handshake or shared-secret token.
- The bridge is local-only by default because it binds to
127.0.0.1. - Media download and attachment forwarding are not implemented.
- Voice-message transcription is not implemented.
- Python-side inbound message deduplication is not implemented.
WebSocket Protocol
Python sends:
{
"type": "send",
"jid": "123456789@s.whatsapp.net",
"text": "hello",
"request_id": "msg-123"
}
Bridge sends:
status: bridge / WhatsApp connection state updatesqr: QR code is available for linkinginbound: inbound text message from WhatsAppsend_result: acknowledgement or error for asendpong: reply to bridge ping
Connection States
The Python channel tracks these states from bridge events:
stopped: channel is stoppedbridge_connected: Python is connected to the local bridge WebSocket, but WhatsApp may still be connectingconnecting: bridge is trying to connect Baileys to WhatsAppqr_pending: a QR code is waiting to be scannedopen: WhatsApp is connected and sending is allowedclose: WhatsApp connection closedlogged_out: WhatsApp session was logged out and needs relinkingbridge_disconnected: Python lost the local bridge WebSocket connection
The distinction matters:
bridge_connectedonly means Python can reach the local bridge.openmeans the bridge is actually logged in to WhatsApp and can send messages.
Channel Metadata
WhatsAppChannel.get_metadata() now exposes runtime state in extra:
bridge_statebridge_ws_connectedwhatsapp_connectedqr_pendinglast_status_ts_mslast_status_code
Prerequisites
- Python environment that can run
python -m jiuwenswarm.app - Node.js 20+ and npm
- A WhatsApp account with Linked Devices enabled
1. Install Bridge Dependencies
Run inside the inner project folder that contains jiuwenswarm/package.json:
cd C:\Users\chiak\OneDrive\Desktop\jiuwenswarm\jiuwenswarm
npm install
If you only want the bridge dependencies:
npm install @whiskeysockets/baileys ws pino qrcode-terminal
2. Configure WhatsApp
Edit your runtime config file:
C:\Users\chiak\.jiuwenswarm\config\config.yaml
Under channels: use:
whatsapp:
bridge_ws_url: ws://127.0.0.1:19600/ws
default_jid:
allow_from: []
enable_streaming: true
auto_start_bridge: false
bridge_command: node scripts/whatsapp-bridge.js
bridge_workdir: C:/Users/chiak/OneDrive/Desktop/jiuwenswarm/jiuwenswarm
enabled: true
Notes:
enable_streaming: trueforwards intermediate events such as token deltas and tool progress.enable_streaming: falsesuppresseschat.deltaevents and keeps output more final-only.default_jidis used as a fallback target for outbound sends.allow_fromaccepts either a full sender JID or the number part before@.auto_start_bridge: truelets Python start the Node bridge process automatically.
3. Start the Services
Open two terminals unless you use auto_start_bridge: true.
Terminal A, bridge:
cd C:\Users\chiak\OneDrive\Desktop\jiuwenswarm\jiuwenswarm
npm run whatsapp:bridge
Expected line:
[whatsapp-bridge] ws://127.0.0.1:19600/ws
Terminal B, app:
cd C:\Users\chiak\OneDrive\Desktop\jiuwenswarm
python -m jiuwenswarm.app
Expected behavior:
- The app logs that
WhatsAppChannelwas registered. - The channel first reaches
bridge_connected. - It then moves to
connecting,qr_pending, oropendepending on login state.
4. Link WhatsApp
When the bridge has no valid auth state, it prints a QR code in the bridge terminal.
In WhatsApp:
Settings -> Linked devices -> Link a device
Then scan the QR code from Terminal A.
Auth state is stored at:
jiuwenswarm/jiuwenswarm/workspace/.whatsapp-auth
If the account is already linked, QR may not appear.
5. Sending and Receiving
- Inbound text messages are forwarded from the bridge to the Python channel as
inbound. - Outbound messages are sent from Python as
send. - Python now blocks sends unless channel state is
open. - If the bridge replies with
send_result.ok=false, the Python channel logs the failure.
6. Security Notes
- The bridge listens on
127.0.0.1by default, which limits access to the local machine. - This repo currently does not implement bridge token auth.
- Do not expose the bridge port directly to other hosts without adding authentication or a trusted tunnel boundary.
7. LLM Config Still Matters
If inbound WhatsApp messages fail downstream with errors such as 405 Not Allowed, the model config is probably placeholder or invalid.
Example .env values:
MODEL_PROVIDER=OpenAI
MODEL_NAME=your-real-model
API_BASE=https://your-real-openai-compatible-endpoint/v1
API_KEY=your-real-key
Restart python -m jiuwenswarm.app after updating .env.
Troubleshooting
Missing script: "whatsapp:bridge"
You ran npm in the wrong folder. Use:
C:\Users\chiak\OneDrive\Desktop\jiuwenswarm\jiuwenswarm
Bridge starts but no QR
- Stop any old bridge processes that may still be holding the port or auth session.
- Delete auth state to force relinking:
jiuwenswarm/jiuwenswarm/workspace/.whatsapp-auth - Start the bridge again and wait for
QR received.
App connects to bridge but cannot send
Check the connection state in logs:
- If state is
bridge_connectedorconnecting, the local bridge is reachable but WhatsApp is not ready yet. - If state is
qr_pending, scan the QR code. - If state is
logged_out, delete the auth directory and relink. - Only state
openallows sends.
App says WhatsApp channel not configured
- Make sure the YAML key is
channels.whatsapp. - Make sure
enabled: trueis set. - Make sure
bridge_ws_urlis not empty.
Bluestacks or emulator linking issues
Scanning from a physical phone is usually more reliable than emulator camera passthrough.