docs/channels/zalouser.md
Status: experimental. This integration automates a personal Zalo account via native zca-js inside OpenClaw.
Zalo Personal ships as a bundled plugin in current OpenClaw releases, so normal packaged builds do not need a separate install.
If you are on an older build or a custom install that excludes Zalo Personal, install the npm package directly:
openclaw plugins install @openclaw/zalouseropenclaw plugins install @openclaw/[email protected]openclaw plugins install ./path/to/local/zalouser-pluginNo external zca/openzca CLI binary is required.
openclaw channels login --channel zalouser{
channels: {
zalouser: {
enabled: true,
dmPolicy: "pairing",
},
},
}
zca-js.Channel id is zalouser to make it explicit this automates a personal Zalo user account (unofficial). We keep zalo reserved for a potential future official Zalo API integration.
Use the directory CLI to discover peers/groups and their IDs:
openclaw directory self --channel zalouser
openclaw directory peers list --channel zalouser --query "name"
openclaw directory groups list --channel zalouser --query "work"
channels.zalouser.dmPolicy supports: pairing | allowlist | open | disabled (default: pairing).
channels.zalouser.allowFrom should use stable Zalo user IDs. During interactive setup, entered names can be resolved to IDs using the plugin's in-process contact lookup.
If a raw name remains in config, startup resolves it only when channels.zalouser.dangerouslyAllowNameMatching: true is enabled. Without that opt-in, runtime sender checks are ID-only and raw names are ignored for authorization.
Approve via:
openclaw pairing list zalouseropenclaw pairing approve zalouser <code>channels.zalouser.groupPolicy = "open" (groups allowed). Use channels.defaults.groupPolicy to override the default when unset.channels.zalouser.groupPolicy = "allowlist"channels.zalouser.groups (keys should be stable group IDs; names are resolved to IDs on startup only when channels.zalouser.dangerouslyAllowNameMatching: true is enabled)channels.zalouser.groupAllowFrom (controls which senders in allowed groups can trigger the bot)channels.zalouser.groupPolicy = "disabled".channels.zalouser.dangerouslyAllowNameMatching: true is enabled.channels.zalouser.dangerouslyAllowNameMatching: true is enabled.channels.zalouser.dangerouslyAllowNameMatching: true is a break-glass compatibility mode that re-enables mutable startup name resolution and runtime group-name matching.groupAllowFrom is unset, runtime falls back to allowFrom for group sender checks./new, /reset).Example:
{
channels: {
zalouser: {
groupPolicy: "allowlist",
groupAllowFrom: ["1471383327500481391"],
groups: {
"123456789": { allow: true },
"Work Chat": { allow: true },
},
},
},
}
channels.zalouser.groups.<group>.requireMention controls whether group replies require a mention.* -> default (true)./new) can bypass mention gating.messages.groupChat.historyLimit (fallback 50). You can override per account with channels.zalouser.historyLimit.Example:
{
channels: {
zalouser: {
groupPolicy: "allowlist",
groups: {
"*": { allow: true, requireMention: true },
"Work Chat": { allow: true, requireMention: false },
},
},
},
}
Accounts map to zalouser profiles in OpenClaw state. Example:
{
channels: {
zalouser: {
enabled: true,
defaultAccount: "default",
accounts: {
work: { enabled: true, profile: "work" },
},
},
},
}
react is supported for zalouser in channel actions.
remove: true to remove a specific reaction emoji from a message.Login doesn't stick:
openclaw channels status --probeopenclaw channels logout --channel zalouser && openclaw channels login --channel zalouserAllowlist/group name didn't resolve:
allowFrom/groupAllowFrom and stable group IDs in groups. If you intentionally need exact friend/group names, enable channels.zalouser.dangerouslyAllowNameMatching: true.Upgraded from old CLI-based setup:
zca process assumptions.