Appearance
WhatsApp Channel
Agentcy talks to WhatsApp through a local Node.js gateway (Baileys). The gateway handles the long-lived websocket to Meta; Agentcy handles the LLM side. Pairing uses the standard QR-code "Linked devices" flow — no WhatsApp Business API application required.
Prerequisites
- Node.js ≥ 18 on the host running the API.
- A WhatsApp account you control (the gateway pairs as a linked device).
- Enough disk space for the gateway's session state (
~/.openfang/whatsapp-gateway/).
Configure
From the UI (/channels → WhatsApp → Configure) or the API:
bash
curl -X POST http://localhost:8080/api/v1/channels/whatsapp/configure \
-H "authorization: Bearer $TOKEN" -H 'content-type: application/json' \
-d '{"fields":{"display_name":"Agentcy Assistant"}}'Configure auto-activates. The gateway is auto-extracted and started on the host.
Pair with QR
bash
# 1. Start a pairing session
curl -X POST http://…/channels/whatsapp/qr/start \
-H "authorization: Bearer $TOKEN"json
{
"session_id": "qr_01HABC…",
"qr_data_url": "data:image/png;base64,iVBORw0K…",
"expires_in": 60
}Render the qr_data_url as an image. Scan with WhatsApp on your phone: Settings → Linked devices → Link a device.
bash
# 2. Poll for completion
curl "http://…/channels/whatsapp/qr/status?session_id=qr_01HABC…" \
-H "authorization: Bearer $TOKEN"Responses: { "status":"pending" } → { "status":"connected", "phone":"+1…" } or {"status":"expired"}.
Bindings — route messages to agents
The channel is now connected, but no agent is listening yet. Create a binding:
bash
curl -X POST http://…/bindings \
-H "authorization: Bearer $TOKEN" -H 'content-type: application/json' \
-d '{
"agent":"incident-responder",
"match_rule":{
"channel":"whatsapp",
"group":"+972500000001"
}
}'match_rule fields (all optional; evaluated as AND):
channel:"whatsapp"group: a group id or participant phonefrom: a specific senderto: a specific number when you have multiple connected numberstext_regex: match against message text
Rules are evaluated top-to-bottom; first match wins. Unmatched messages are logged and ignored.
List bindings:
bash
curl "http://…/bindings?channel=whatsapp" -H "authorization: Bearer $TOKEN" | jqSend a message from an agent
Agents reply automatically when a message arrives via a binding. To send proactively:
bash
curl -X POST http://…/channels/whatsapp/send \
-H "authorization: Bearer $TOKEN" -H 'content-type: application/json' \
-d '{"to":"+972500000002","text":"deploy complete — prod is green"}'Supports text, media, and reaction payloads. See the schema at GET /channels/whatsapp/schema.
Test credentials
bash
curl -X POST http://…/channels/whatsapp/test -H "authorization: Bearer $TOKEN"Returns {"status":"ok","phone":"+1…"} or a clear error if the gateway can't reach Meta.
Reload
After editing config or bindings, reload the channel:
bash
curl -X POST http://…/channels/reload -H "authorization: Bearer $TOKEN"The gateway gracefully disconnects, reloads config, re-connects. Session state is preserved — no re-pairing.
Unpair
bash
curl -X DELETE http://…/channels/whatsapp/configure -H "authorization: Bearer $TOKEN"Or from your phone: Linked devices → remove the Agentcy session.
Gateway internals
- Binary:
@whiskeysockets/baileyswrapped in a small Node script. - Location:
~/.openfang/whatsapp-gateway/(extracted on first use). - Branding: the gateway's
browser:string is patched fromOpenFang→Agentcyat startup so the device shows up nicely in the "Linked devices" screen. - Persistence: auth state files in
~/.openfang/whatsapp-gateway/auth/<org_id>/.
Policies
Because WhatsApp messages can trigger tool calls, policies apply. A common pattern:
rego
deny[msg] {
input.subject.channel == "whatsapp"
input.action == "chat.tool.execute"
input.resource.tool_effect != "read"
not input.context.approval_granted
msg := "write tools require approval when triggered from whatsapp"
}The channel binding automatically populates subject.channel = "whatsapp" for evaluation.
Gotchas
- WhatsApp rate-limits aggressively. Bulk sends are a great way to get your account flagged. For broadcasts, use the official Business API.
- One session per account. If the account is already paired to the gateway from a stale session, unpair first or the QR will repeatedly expire.
- Group messages include mentions you need to handle. The binding matches on group id; your template should inspect whether the agent was mentioned before replying.
- Media is downloaded to the artifact store. On large volumes, point
AGENTCY_ARTIFACT_BACKEND=s3.
Next
- Concept: Channels & Triggers — the full model.
- How-To: Slack Channel — the other big channel.
- How-To: Approval Flows — gate risky actions from chat.