Plugin thêm kênh Zalo Bot Platform cho Hermes Agent gateway, tương tự Telegram nhưng dùng API của Zalo Bot.
| Tính năng | Trạng thái |
|---|---|
Nhận tin (getUpdates polling) / Gửi text (sendMessage) |
✅ |
Webhook mode (setWebhook) |
✅ |
Typing indicator / Ảnh public URL / Voice HTTPS .aac 1-1 |
✅ |
| Local media file (qua built-in media server) | ✅ cần ZALO_PUBLIC_URL |
| Chat nhóm (allowlist + mention/reply/command safety) | ✅ |
| Cron delivery / Markdown fallback / Dedup / Token redaction | ✅ |
- Python 3.10+, Hermes Agent,
httpx(ưu tiên) hoặcaiohttp - Webhook/media server cần
aiohttp(pip install aiohttp)
git clone https://github.com/dongphuongman/hermes-zalo-bot /tmp/zalo
mkdir -p "$HERMES_HOME/plugins/platforms/zalo"
cp -R /tmp/zalo/{adapter.py,plugin.yaml,__init__.py,README.md,tests} \
"$HERMES_HOME/plugins/platforms/zalo/"$HERMES_HOME mặc định là ~/.hermes.
hermes plugins list # phải thấy: zalo | 1.2.0 | ... | user
hermes plugins enable zalo # hỏi replace built-in tools → trả lời nBa đường ghi khác nhau — chọn sai thì lệnh báo OK mà không có tác dụng.
Token → tự vào .env:
hermes config set zalo_bot_token <token>Platform + tuỳ chọn → config.yaml nested:
hermes config set platforms.zalo.enabled true
hermes config set platforms.zalo.extra.mode polling
hermes config set platforms.zalo.extra.poll_timeout 30
hermes config set platforms.zalo.extra.group_require_mention true
hermes config set platforms.zalo.extra.allowed_groups "<gid1>,<gid2>"Biến top-level → config.yaml top-level, bắt buộc VIẾT HOA (viết thường là no-op im lặng):
hermes config set ZALO_ALLOW_ALL_USERS false
hermes config set ZALO_HOME_CHANNEL <chat-id>Thứ tự ưu tiên:
os.getenv()(.env) > khoá top-level VIẾT HOA (config.yaml) >platforms.zalo.extra.*
| Biến | Bắt buộc | Mặc định | Mô tả |
|---|---|---|---|
ZALO_BOT_TOKEN |
✅ | Token từ Zalo Bot Creator | |
ZALO_MODE |
polling |
polling hoặc webhook |
|
ZALO_PUBLIC_URL |
Public HTTPS URL — bật webhook và/hoặc media server | ||
ZALO_WEBHOOK_SECRET_TOKEN |
Secret cho webhook header (bắt buộc khi webhook) | ||
ZALO_WEBHOOK_PORT |
8648 |
Port HTTP server | |
ZALO_WEBHOOK_HOST |
0.0.0.0 |
Bind address HTTP server | |
ZALO_ALLOW_ALL_USERS |
false |
Cho tất cả user dùng bot (chỉ khi dev) | |
ZALO_ALLOWED_USERS |
CSV user ID cho phép | ||
ZALO_HOME_CHANNEL |
Chat ID cho cron delivery | ||
ZALO_ALLOWED_GROUPS |
CSV group ID cho phép | ||
ZALO_GROUP_REQUIRE_MENTION |
true |
Yêu cầu mention/reply/command trong group | |
ZALO_API_BASE |
https://bot-api.zaloplatforms.com |
Override API URL | |
ZALO_TEXT_LIMIT |
2000 |
Giới hạn ký tự / tin nhắn | |
ZALO_SAFE_TEXT_LIMIT |
1900 |
Giới hạn chunk text | |
ZALO_POLL_TIMEOUT |
30 |
Timeout mỗi poll (giây) | |
ZALO_POLL_INTERVAL |
0 |
Khoảng cách giữa poll (giây) | |
ZALO_AUTO_DELETE_WEBHOOK_FOR_POLLING |
Tự xoá webhook khi chuyển polling |
Polling (mặc định):
hermes gateway run --replaceWebhook:
hermes config set platforms.zalo.extra.mode webhook
hermes config set ZALO_PUBLIC_URL https://your-domain.com
hermes config set zalo_webhook_secret_token <secret>
hermes gateway run --replaceBot sẽ start HTTP server trên port 8648, đăng ký webhook {ZALO_PUBLIC_URL}/webhook với Zalo, và nhận event qua POST. Dùng reverse proxy (nginx/caddy) hoặc ngrok trỏ HTTPS tới port 8648.
Health check: GET {ZALO_PUBLIC_URL}/health
Khi ZALO_PUBLIC_URL được set (cả polling lẫn webhook), plugin tự dựng HTTP
76BD
file server. Local image/voice được copy vào thư mục temp, serve qua {ZALO_PUBLIC_URL}/media/{hash}, rồi gọi sendPhoto/sendVoice với URL đó.
| Loại | Hỗ trợ |
|---|---|
Ảnh public URL (.png/.jpg/.jpeg/.webp/.gif) |
✅ sendPhoto |
Ảnh local file + ZALO_PUBLIC_URL |
✅ qua media server |
Voice public HTTPS .aac (chat 1-1) |
✅ sendVoice |
Voice local .aac + ZALO_PUBLIC_URL (chat 1-1) |
✅ qua media server |
| Voice non-aac / voice group | |
Không có ZALO_PUBLIC_URL + local file |
File tự cleanup sau 1 giờ.
Không cần mò user ID, không cần restart gateway:
- User nhắn cho bot → bot DM mã pairing (ví dụ
G7P5Q7A7) - Admin duyệt:
hermes pairing approve zalo G7P5Q7A7- User nhắn lại → bot trả lời.
hermes pairing list # xem hàng chờ / đã duyệt
hermes pairing revoke zalo <user-id>
ZALO_ALLOWED_USERSvẫn dùng được nhưng pairing tốt hơn. Đừng dùng cả hai cùng lúc.
ZALO_GROUP_REQUIRE_MENTION=true # bot chỉ trả lời khi mention/reply/slash-command
ZALO_ALLOWED_GROUPS=zgr-abc,zgr-defBot trả lời khi: mention (@Bot Hermes david ...) · reply/quote tin bot · slash command (/help).
Lấy group ID từ log: Zalo group event: group=<group-id> ...
- Không commit token — đặt ở
.env(quyền600) - Token tự redact trong log (
/bot<redacted>/) - Webhook verify
X-Bot-Api-Secret-Tokenheader (constant-time compare) - Production:
ZALO_ALLOW_ALL_USERS=false+ZALO_GROUP_REQUIRE_MENTION=true
36 test (23 upstream + 5 hồi quy + 8 webhook/media server).
cd /path/to/hermes-agent
mkdir -p plugins/platforms/zalo
cp /path/to/this-repo/{adapter.py,plugin.yaml,__init__.py} plugins/platforms/zalo/
python -m pytest /path/to/this-repo/tests/ -q
rm -rf plugins/platforms/zalo- Zalo không chuyển nội dung tin chứa link/URL — plugin báo rõ cho user nhưng không lấy lại được nội dung
- Voice chỉ dùng được
.aactrong chat 1-1 - Local media cần
ZALO_PUBLIC_URLvà port accessible từ internet
Xác thực · Gọi API · getMe · getUpdates · sendMessage · sendPhoto · sendVoice · setWebhook · Polling bot · Group chat