Zalo (Bot API)
Zalo is the official bot path for teams or businesses that need to meet users inside the Zalo ecosystem. The plugin can long-poll by default or switch to a webhook model, while Fased keeps DM policy and group policy separate the same way it does on other channels. Status: experimental. DMs are supported, and groups are available behind explicit policy controls.Setup from Agent > Channels
Zalo ships with Fased as a local bundled channel extension. You do not need to download an npm package in a normal install. Open Agents, select the Agent, then use Agent > Channels > Zalo. Enter the bot token, save the channel, then restart the gateway if the UI reports that the runtime still needs to load.Quick setup (beginner)
If you are just starting, use long-polling first. Move to webhook mode only when you need it and can expose a dedicated HTTPS path safely.- Set the token:
- Env:
ZALO_BOT_TOKEN=... - Or Agent > Channels > Zalo.
- Env:
- Restart the gateway if the UI asks for it.
- DM access is pairing by default; approve the pairing code on first contact.
What it is
Zalo is a Vietnam-focused messaging app; its Bot API lets the Gateway run a bot for 1:1 conversations. It is a good fit for support or notifications where you want deterministic routing back to Zalo.- A Zalo Bot API channel owned by the Gateway.
- Deterministic routing: replies go back to Zalo; the model never chooses channels.
- DMs share the agent’s main session.
- Groups are supported with policy controls (
groupPolicy+groupAllowFrom) and default to fail-closed allowlist behavior.
Setup (fast path)
1) Create a bot token (Zalo Bot Platform)
- Go to https://bot.zaloplatforms.com and sign in.
- Create a new bot and configure its settings.
- Copy the bot token (format:
12345689:abc-xyz).
2) Configure the token (env or config)
Example:ZALO_BOT_TOKEN=... (works for the default account only).
Multi-account support: use channels.zalo.accounts with per-account tokens and optional name.
- Restart the gateway. Zalo starts when a token is resolved (env or config).
- DM access defaults to pairing. Approve the code when the bot is first contacted.
How it works (behavior)
- Inbound messages are normalized into the shared channel envelope with media placeholders.
- Replies always route back to the same Zalo chat.
- Long-polling by default; webhook mode available with
channels.zalo.webhookUrl.
Limits
- Outbound text is chunked to 2000 characters (Zalo API limit).
- Media downloads/uploads are capped by
channels.zalo.mediaMaxMb(default 5). - Streaming is blocked by default due to the 2000 char limit making streaming less useful.
Access control (DMs)
DM access
- Default:
channels.zalo.dmPolicy = "pairing". Unknown senders receive a pairing code; messages are ignored until approved (codes expire after 1 hour). - Approve via:
fased pairing list zalofased pairing approve zalo <CODE>
- Pairing is the default token exchange. Details: Pairing
channels.zalo.allowFromaccepts numeric user IDs (no username lookup available).
Access control (Groups)
channels.zalo.groupPolicycontrols group inbound handling:open | allowlist | disabled.- Default behavior is fail-closed:
allowlist. channels.zalo.groupAllowFromrestricts which sender IDs can trigger the bot in groups.- If
groupAllowFromis unset, Zalo falls back toallowFromfor sender checks. groupPolicy: "disabled"blocks all group messages.groupPolicy: "open"allows any group member (mention-gated).- Runtime note: if
channels.zalois missing entirely, runtime still falls back togroupPolicy="allowlist"for safety.
Long-polling vs webhook
- Default: long-polling (no public URL required).
- Webhook mode: set
channels.zalo.webhookUrlandchannels.zalo.webhookSecret.- The webhook secret must be 8-256 characters.
- Webhook URL must use HTTPS.
- Zalo sends events with
X-Bot-Api-Secret-Tokenheader for verification. - Gateway HTTP handles webhook requests at
channels.zalo.webhookPath(defaults to the webhook URL path). - Requests must use
Content-Type: application/json(or+jsonmedia types). - Duplicate events (
event_name + message_id) are ignored for a short replay window. - Burst traffic is rate-limited per path/source and may return HTTP 429.
Supported message types
- Text messages: Full support with 2000 character chunking.
- Image messages: Download and process inbound images; send images via
sendPhoto. - Stickers: Logged but not fully processed (no agent response).
- Unsupported types: Logged (e.g., messages from protected users).
Capabilities
| Feature | Status |
|---|---|
| Direct messages | ✅ Supported |
| Groups | ⚠️ Supported with policy controls (allowlist by default) |
| Media (images) | ✅ Supported |
| Reactions | ❌ Not supported |
| Threads | ❌ Not supported |
| Polls | ❌ Not supported |
| Native commands | ❌ Not supported |
| Streaming | ⚠️ Blocked (2000 char limit) |
Delivery targets (CLI/cron)
- Use a chat id as the target.
- Example:
fased message send --channel zalo --target 123456789 --message "hi".
Troubleshooting
Bot doesn’t respond:- Check that the token is valid:
fased channels status --probe - Verify the sender is approved (pairing or allowFrom)
- Check gateway logs:
fased logs --follow
- Ensure webhook URL uses HTTPS
- Verify secret token is 8-256 characters
- Confirm the gateway HTTP endpoint is reachable on the configured path
- Check that getUpdates polling is not running (they’re mutually exclusive)
Configuration reference (Zalo)
Full configuration: Configuration Provider options:channels.zalo.enabled: enable/disable channel startup.channels.zalo.botToken: bot token from Zalo Bot Platform.channels.zalo.tokenFile: read token from file path.channels.zalo.dmPolicy:pairing | allowlist | open | disabled(default: pairing).channels.zalo.allowFrom: DM allowlist (user IDs).openrequires"*". The wizard will ask for numeric IDs.channels.zalo.groupPolicy:open | allowlist | disabled(default: allowlist).channels.zalo.groupAllowFrom: group sender allowlist (user IDs). Falls back toallowFromwhen unset.channels.zalo.mediaMaxMb: inbound/outbound media cap (MB, default 5).channels.zalo.webhookUrl: enable webhook mode (HTTPS required).channels.zalo.webhookSecret: webhook secret (8-256 chars).channels.zalo.webhookPath: webhook path on the gateway HTTP server.channels.zalo.proxy: proxy URL for API requests.
channels.zalo.accounts.<id>.botToken: per-account token.channels.zalo.accounts.<id>.tokenFile: per-account token file.channels.zalo.accounts.<id>.name: display name.channels.zalo.accounts.<id>.enabled: enable/disable account.channels.zalo.accounts.<id>.dmPolicy: per-account DM policy.channels.zalo.accounts.<id>.allowFrom: per-account allowlist.channels.zalo.accounts.<id>.groupPolicy: per-account group policy.channels.zalo.accounts.<id>.groupAllowFrom: per-account group sender allowlist.channels.zalo.accounts.<id>.webhookUrl: per-account webhook URL.channels.zalo.accounts.<id>.webhookSecret: per-account webhook secret.channels.zalo.accounts.<id>.webhookPath: per-account webhook path.channels.zalo.accounts.<id>.proxy: per-account proxy URL.