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. It can also reference static sender access groups (accessGroup:<name>). 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; static sender access groups can be referenced with accessGroup:<name>)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" },
},
},
},
}
The Zalo Personal plugin can also read profile selection from environment variables:
ZALOUSER_PROFILE: profile name to use when no profile is set in channel or account config.ZCA_PROFILE: legacy fallback profile name, used only when ZALOUSER_PROFILE is not set.Profile names select the saved Zalo login credentials in OpenClaw state. Resolution order is:
profile in config.ZALOUSER_PROFILE.ZCA_PROFILE.default for the default account.For multi-account setups, prefer setting profile on each account in config so
one environment variable does not make multiple accounts share the same login
session.
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.