Zalo
Zalo (Bot API)
Section titled “Zalo (Bot API)”Status: experimental. DMs are supported. The Capabilities section below reflects current Marketplace-bot behavior.
Plugin required
Section titled “Plugin required”Zalo ships as a plugin and is not bundled with the core install.
- Install via CLI:
openclaw plugins install @openclaw/zalo - Or select Zalo during setup and confirm the install prompt
- Details: Plugins
Quick setup (beginner)
Section titled “Quick setup (beginner)”- Install the Zalo plugin:
- From a source checkout:
openclaw plugins install ./path/to/local/zalo-plugin - From npm (if published):
openclaw plugins install @openclaw/zalo - Or pick Zalo in setup and confirm the install prompt
- From a source checkout:
- Set the token:
- Env:
ZALO_BOT_TOKEN=... - Or config:
channels.zalo.accounts.default.botToken: "...".
- Env:
- Restart the gateway (or finish setup).
- DM access is pairing by default; approve the pairing code on first contact.
Minimal config:
{ channels: { zalo: { enabled: true, accounts: { default: { botToken: "12345689:abc-xyz", dmPolicy: "pairing", }, }, }, },}What it is
Section titled “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.
This page reflects current OpenClaw behavior for Zalo Bot Creator / Marketplace bots. Zalo Official Account (OA) bots are a different Zalo product surface and may behave differently.
- 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.
- The Capabilities section below shows current Marketplace-bot support.
Setup (fast path)
Section titled “Setup (fast path)”1) Create a bot token (Zalo Bot Platform)
Section titled “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 full bot token (typically
numeric_id:secret). For Marketplace bots, the usable runtime token may appear in the bot’s welcome message after creation.
2) Configure the token (env or config)
Section titled “2) Configure the token (env or config)”Example:
{ channels: { zalo: { enabled: true, accounts: { default: { botToken: "12345689:abc-xyz", dmPolicy: "pairing", }, }, }, },}If you later move to a Zalo bot surface where groups are available, you can add group-specific config such as groupPolicy and groupAllowFrom explicitly. For current Marketplace-bot behavior, see Capabilities.
Env option: 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)
Section titled “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
Section titled “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)
Section titled “Access control (DMs)”DM access
Section titled “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:
openclaw pairing list zaloopenclaw 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)
Section titled “Access control (Groups)”For Zalo Bot Creator / Marketplace bots, group support was not available in practice because the bot could not be added to a group at all.
That means the group-related config keys below exist in the schema, but were not usable for Marketplace bots:
channels.zalo.groupPolicycontrols group inbound handling:open | allowlist | disabled.channels.zalo.groupAllowFromrestricts which sender IDs can trigger the bot in groups.- If
groupAllowFromis unset, Zalo falls back toallowFromfor sender checks. - Runtime note: if
channels.zalois missing entirely, runtime still falls back togroupPolicy="allowlist"for safety.
The group policy values (when group access is available on your bot surface) are:
groupPolicy: "disabled"— blocks all group messages.groupPolicy: "open"— allows any group member (mention-gated).groupPolicy: "allowlist"— fail-closed default; only allowed senders are accepted.
If you are using a different Zalo bot product surface and have verified working group behavior, document that separately rather than assuming it matches the Marketplace-bot flow.
Long-polling vs webhook
Section titled “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.
Note: getUpdates (polling) and webhook are mutually exclusive per Zalo API docs.
Supported message types
Section titled “Supported message types”For a quick support snapshot, see Capabilities. The notes below add detail where the behavior needs extra context.
- Text messages: Full support with 2000 character chunking.
- Plain URLs in text: Behave like normal text input.
- Link previews / rich link cards: See the Marketplace-bot status in Capabilities; they did not reliably trigger a reply.
- Image messages: See the Marketplace-bot status in Capabilities; inbound image handling was unreliable (typing indicator without a final reply).
- Stickers: See the Marketplace-bot status in Capabilities.
- Voice notes / audio files / video / generic file attachments: See the Marketplace-bot status in Capabilities.
- Unsupported types: Logged (for example, messages from protected users).
Capabilities
Section titled “Capabilities”This table summarizes current Zalo Bot Creator / Marketplace bot behavior in OpenClaw.
| Feature | Status |
|---|---|
| Direct messages | ✅ Supported |
| Groups | ❌ Not available for Marketplace bots |
| Media (inbound images) | ⚠️ Limited / verify in your environment |
| Media (outbound images) | ⚠️ Not re-tested for Marketplace bots |
| Plain URLs in text | ✅ Supported |
| Link previews | ⚠️ Unreliable for Marketplace bots |
| Reactions | ❌ Not supported |
| Stickers | ⚠️ No agent reply for Marketplace bots |
| Voice notes / audio / video | ⚠️ No agent reply for Marketplace bots |
| File attachments | ⚠️ No agent reply for Marketplace bots |
| Threads | ❌ Not supported |
| Polls | ❌ Not supported |
| Native commands | ❌ Not supported |
| Streaming | ⚠️ Blocked (2000 char limit) |
Delivery targets (CLI/cron)
Section titled “Delivery targets (CLI/cron)”- Use a chat id as the target.
- Example:
openclaw message send --channel zalo --target 123456789 --message "hi".
Troubleshooting
Section titled “Troubleshooting”Bot doesn’t respond:
- Check that the token is valid:
openclaw channels status --probe - Verify the sender is approved (pairing or allowFrom)
- Check gateway logs:
openclaw logs --follow
Webhook not receiving events:
- 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)
Section titled “Configuration reference (Zalo)”Full configuration: Configuration
The flat top-level keys (channels.zalo.botToken, channels.zalo.dmPolicy, and similar) are a legacy single-account shorthand. Prefer channels.zalo.accounts.<id>.* for new configs. Both forms are still documented here because they exist in the schema.
Provider options:
channels.zalo.enabled: enable/disable channel startup.channels.zalo.botToken: bot token from Zalo Bot Platform.channels.zalo.tokenFile: read token from a regular file path. Symlinks are rejected.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). Present in config; see Capabilities and Access control (Groups) for current Marketplace-bot behavior.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.
Multi-account options:
channels.zalo.accounts.<id>.botToken: per-account token.channels.zalo.accounts.<id>.tokenFile: per-account regular token file. Symlinks are rejected.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. Present in config; see Capabilities and Access control (Groups) for current Marketplace-bot behavior.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.
Related
Section titled “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