Source-grounded rewrite of 529 published docs pages with per-unit information-loss verification: 1,713 factual corrections cited to src/**, generated surfaces regenerated, frontmatter titles preserved for i18n, release notes pages untouched. All docs gates green. Closes #100141
9.7 KiB
summary, read_when, title
| summary | read_when | title | |
|---|---|---|---|
| Zalo bot support status, capabilities, and configuration |
|
Zalo |
Status: experimental. Direct messages and group chats are both implemented; the Capabilities table below reflects verified behavior on Zalo Bot Creator / Marketplace bots.
Bundled plugin
Zalo ships as a bundled plugin in current OpenClaw releases, so packaged builds do not need a separate install.
On an older build or a custom install that excludes Zalo, install the npm package directly:
- Install:
openclaw plugins install @openclaw/zalo - Pinned version:
openclaw plugins install @openclaw/zalo@2026.6.11 - From a local checkout:
openclaw plugins install ./path/to/local/zalo-plugin - Details: Plugins
Quick setup
- Create a bot token at https://bot.zaloplatforms.com (sign in, create a bot, configure settings). The token is
numeric_id:secret; for Marketplace bots the usable runtime token may appear in the bot's welcome message. - Set the token, either as env
ZALO_BOT_TOKEN=...(default account only) or in config. - Restart the gateway.
- Approve the pairing code on first DM contact (default DM policy is pairing).
Minimal config:
{
channels: {
zalo: {
enabled: true,
accounts: {
default: {
botToken: "12345689:abc-xyz",
dmPolicy: "pairing",
},
},
},
},
}
Multi-account: add more entries under channels.zalo.accounts.<id>, each with its own botToken/name. channels.zalo.botToken (flat, no accounts) is a legacy single-account shorthand; prefer accounts.<id>.* for new configs.
What it is
Zalo is a Vietnam-focused messaging app. Its Bot API lets the Gateway run a bot for both 1:1 conversations and group chats, with deterministic routing back to Zalo (the model never chooses channels).
This page covers Zalo Bot Creator / Marketplace bots. Zalo Official Account (OA) bots are a different product surface and may behave differently; this page does not cover them.
How it works
- Inbound messages are normalized into the shared channel envelope with media placeholders.
- Replies always route back to the same Zalo chat; quote-reply is not used (
replyToModeis fixed off). - Long-polling (
getUpdates) by default; webhook mode available viachannels.zalo.webhookUrl. - Groups require an @mention to trigger the bot; this is not configurable per channel.
Limits
| Limit | Value |
|---|---|
| Outbound text chunk size | 2000 characters (Zalo API limit) |
| Media size (inbound/outbound) | channels.zalo.mediaMaxMb, default 5 MB |
| Webhook request body | 1 MB, 30s read timeout |
| Webhook rate limit | 120 requests / 60s per path+client IP, then HTTP 429 |
| Webhook duplicate-event window | 5 minutes (keyed on path + account + event name + chat + sender + message id) |
Access control
Direct messages
channels.zalo.dmPolicy:pairing(default) |allowlist|open|disabled.- Pairing: unknown senders get a pairing code; messages are ignored until approved. Codes expire after 1 hour.
openclaw pairing list zaloopenclaw pairing approve zalo <CODE>- Details: Pairing
channels.zalo.allowFromaccepts numeric Zalo user IDs (no username lookup).openrequires"*".
Groups
Group chats are supported by the plugin (chatTypes: ["direct", "group"]) and gated by mention plus group policy:
channels.zalo.groupPolicy:open|allowlist|disabled.channels.zalo.groupAllowFromrestricts which sender IDs can trigger the bot in groups; falls back toallowFromwhen unset.- Default resolution: when
channels.zalois configured, an unsetgroupPolicyresolves toopen. Whenchannels.zalois missing entirely, runtime fails closed toallowlist. - Reported real-world caveat: on some Marketplace-bot setups the bot could not be added to a group at all. If you hit that, verify with your bot's Zalo Bot Platform settings; it is a platform-side constraint, not an OpenClaw policy.
Long-polling vs webhook
- Default: long-polling (no public URL required).
- Webhook mode: set
channels.zalo.webhookUrlandchannels.zalo.webhookSecret.- Webhook URL must use HTTPS.
- Webhook secret must be 8-256 characters.
- Zalo sends events with an
X-Bot-Api-Secret-Tokenheader, checked with a constant-time comparison. - Gateway HTTP handles webhook requests at
channels.zalo.webhookPath(defaults to the webhook URL's path). - Requests must use
Content-Type: application/json(or a+jsonmedia type). - getUpdates polling and webhook are mutually exclusive per Zalo API docs.
Supported message types
- Text: full support, chunked to 2000 characters.
- Media: inbound/outbound, capped by
mediaMaxMb. - Reactions, threads, polls, native commands: not supported by the plugin.
- Streaming: the plugin declares block-streaming capability, but Zalo has no dedicated outbound queue/merge-text tuning knobs (unlike some other regional channels); verify current behavior in your environment if this matters for your use case.
Capabilities
| Feature | Status |
|---|---|
| Direct messages | Supported |
| Groups | Supported (mention-gated) |
| Media (inbound/outbound) | Supported, capped by mediaMaxMb |
| Reactions | Not supported |
| Threads | Not supported |
| Polls | Not supported |
| Native commands | Not supported |
| Reply-to / quote | Not used (fixed off) |
Delivery targets (CLI/cron)
Use a chat ID as the target:
openclaw message send --channel zalo --target 123456789 --message "hi"
Troubleshooting
Bot does not respond:
- Check the token:
openclaw channels status --probe - Verify the sender is approved (pairing or
allowFrom) - Check gateway logs:
openclaw logs --follow
Webhook not receiving events:
- Confirm the webhook URL uses HTTPS
- Confirm the secret is 8-256 characters
- Confirm the gateway HTTP endpoint is reachable on the configured path
- Confirm getUpdates polling is not also running (they are mutually exclusive)
- A burst of requests can return HTTP 429 (120 requests / 60s per path+IP); back off and retry
Configuration reference
Full configuration: Configuration
| Setting | Description | Default |
|---|---|---|
channels.zalo.enabled |
Enable/disable channel startup | true |
channels.zalo.accounts.<id>.botToken |
Bot token from Zalo Bot Platform | - |
channels.zalo.accounts.<id>.tokenFile |
Read token from a file (symlinks rejected) | - |
channels.zalo.accounts.<id>.name |
Display name | - |
channels.zalo.accounts.<id>.enabled |
Enable/disable this account | true |
channels.zalo.accounts.<id>.dmPolicy |
Per-account DM policy | pairing |
channels.zalo.accounts.<id>.allowFrom |
DM allowlist (user IDs) | - |
channels.zalo.accounts.<id>.groupPolicy |
Per-account group policy | see Groups |
channels.zalo.accounts.<id>.groupAllowFrom |
Group sender allowlist; falls back to allowFrom |
- |
channels.zalo.accounts.<id>.mediaMaxMb |
Inbound/outbound media cap (MB) | 5 |
channels.zalo.accounts.<id>.webhookUrl |
Enable webhook mode (HTTPS required) | - |
channels.zalo.accounts.<id>.webhookSecret |
Webhook secret (8-256 chars) | - |
channels.zalo.accounts.<id>.webhookPath |
Webhook path on the gateway HTTP server | webhook URL path |
channels.zalo.accounts.<id>.proxy |
Proxy URL for API requests | - |
channels.zalo.accounts.<id>.responsePrefix |
Outbound response prefix override | - |
channels.zalo.defaultAccount |
Default account when multiple are configured | default |
channels.zalo.botToken, channels.zalo.dmPolicy, and other flat top-level keys are the legacy single-account shorthand for the fields above; both forms are supported.
Env option: ZALO_BOT_TOKEN=... resolves the default account's token only.
Related
- Channels Overview - all supported channels
- Pairing - DM authentication and pairing flow
- Groups - group chat behavior and mention gating
- Channel Routing - session routing for messages
- Security - access model and hardening