Bạn không cần viết backend từ đầu. Với SME, n8n (tự host, chi phí thấp, kiểm soát dữ liệu) hoặc Make/Zapier (dễ nhưng tính phí theo lượt) là lựa chọn thực tế. Bài này dùng n8n vì rẻ và linh hoạt nhất cho thị trường Việt.
So sánh nhanh
| Tiêu chí | n8n (self-host) | Make | Zapier |
|---|---|---|---|
| Chi phí | ~150k/tháng VPS | Theo operation | Đắt nhất |
| Dữ liệu | Tự lưu, riêng tư | Trên cloud họ | Trên cloud họ |
| Độ linh hoạt | Rất cao (code node) | Trung bình | Thấp |
| Phù hợp SME Việt | Tốt nhất | Ổn | Ít dùng |
Kiến trúc luồng agent tối giản
[Webhook Zalo] → [Chuẩn hóa input] → [Router theo intent]
├─ Hỏi giá → [Tra Google Sheet] → [Soạn trả lời] → [Gửi Zalo]
├─ Đặt hàng → [Ghi đơn Sheet] → [Xác nhận] → [Gửi Zalo]
└─ Khác → [Gọi LLM] → [Gửi Zalo]
Các bước dựng luồng tiếp nhận
- Cài n8n: dùng Docker trên VPS. Đặt domain + HTTPS (Zalo yêu cầu webhook HTTPS).
docker run -d --name n8n -p 5678:5678 \
-e N8N_HOST=agent.tiembanh.vn \
-e WEBHOOK_URL=https://agent.tiembanh.vn/ \
-v n8n_data:/home/node/.n8n \
n8nio/n8n
- Tạo Webhook node: copy URL production của node → dán vào cấu hình Webhook Zalo (bài 2).
- Thêm node chuẩn hóa: trích
sender.id,message.text,event_namera biến sạch để các node sau dùng.
// Code node: chuẩn hóa input
const body = $json.body;
return [{
json: {
userId: body.sender.id,
text: (body.message?.text || '').trim(),
event: body.event_name,
receivedAt: Date.now()
}
}];
- Trả 200 ngay: Zalo cần webhook phản hồi nhanh (< vài giây). Nếu xử lý lâu (gọi LLM), hãy trả 200 trước, xử lý sau để tránh Zalo retry gây tin trùng.
- Thêm bước gửi trả lời: HTTP Request node gọi Send Message API với
access_tokenlưu trong Credentials của n8n. - Test end-to-end: nhắn OA một câu → xem execution log → thấy agent trả lời lại.
Khung tư duy: Ý tưởng → Luồng → Node
Đừng nghĩ bằng code, hãy nghĩ bằng luồng. Mỗi việc agent làm là một node. Mỗi rẽ nhánh là một điều kiện. Vẽ luồng ra giấy trước khi kéo thả — bạn sẽ tránh được rối node về sau.
Checklist luồng chạy được
- [ ] n8n chạy trên HTTPS domain riêng
- [ ] Webhook nhận sự kiện Zalo thật
- [ ] Node chuẩn hóa trả về
userId+text - [ ] Webhook trả 200 trong < 2 giây
- [ ] Gửi lại được tin qua Send Message API
- [ ] access_token lưu ở Credentials, không hardcode
Sai lầm thường gặp
- Webhook trả 200 chậm: vì gọi LLM/DB đồng bộ trước khi trả. Zalo retry → khách nhận tin trùng. Tách phản hồi khỏi xử lý.
- Dùng HTTP thay HTTPS: Zalo từ chối webhook không có SSL. Cài Let's Encrypt/Caddy.
- Không xử lý event lạ: sự kiện
follow,user_send_imagelàm luồng lỗi vì không cómessage.text. Luôn có nhánh mặc định. - Để n8n public không bảo vệ: ai cũng vào editor sửa luồng. Bật basic auth + firewall theo IP.
- Test bằng dữ liệu giả rồi tưởng xong: phải test bằng tin Zalo thật vì cấu trúc payload khác dữ liệu mẫu.
Học xong bài này rồi?
Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu,
và học hết khóa thì có chứng chỉ.
Lưu tiến độ của tôi