การโอนแชทให้เจ้าหน้าที่
ภาพรวม
เมื่อบอทตอบคำถามไม่ได้ หรือผู้ใช้พิมพ์ข้อความอย่าง "คุยกับเจ้าหน้าที่" ระบบต้องสลับจากโหมด "บอทตอบ" ไปเป็น "คนตอบ" โดยส่งบทสนทนาต่อไปยัง Mbox ซึ่งเป็นระบบ live chat แบบ Chatwoot และต้องกันไม่ให้ระบบตอบอัตโนมัติเข้าไปแทรกระหว่างที่เจ้าหน้าที่กำลังสนทนาอยู่
สถานะ "กำลังคุยกับเจ้าหน้าที่" ถูกเก็บใน Redis ด้วยคีย์รูปแบบ agent_mode:<lineOaId>:<userId>
คู่กับ sorted set agent_sessions ที่ทำหน้าที่เป็นนาฬิกาจับเวลาหมดอายุของแต่ละ session
Business Flow
โหมด handoff — เข้าสู่โหมดเจ้าหน้าที่
- รับ
MboxHandoffPayloadที่มีmboxConfigภายใน ประกอบด้วย base URL, API token, account ID, inbox ID, LINE webhook URL, ระยะเวลา timeout และ warning, ชุดข้อความ greeting / warning / end / timeout รวมถึงรายการ exit keyword - ตรวจสอบซ้ำ — หากคีย์
agent_mode:<lineOaId>:<userId>มีอยู่แล้ว แปลว่าอยู่ในโหมดเจ้าหน้าที่ อยู่ก่อนแล้ว จึงข้ามการทำงาน - Forward webhook เข้า Mbox เพื่อให้เกิด conversation ขึ้นทางฝั่งนั้น
- ระบบจะใช้ webhook ที่เก็บค้างไว้ในคีย์
mbox_pending_webhook:<lineOaId>:<userId>ก่อน เนื่องจาก postback event ไม่สามารถสร้าง conversation ใน Mbox ได้ แต่ข้อความต้นทางที่ทำให้เกิดtalk_to_agentสร้างได้ - หากไม่มีค่าเก็บไว้ จะใช้ webhook ปัจจุบันแทน และหากการ forward ล้มเหลวจะไม่ถือเป็นข้อผิดพลาดร้ายแรง ระบบจะบันทึก log แล้วทำงานต่อ โดยตั้ง HTTP timeout ไว้ที่ 5 วินาที
- ระบบจะใช้ webhook ที่เก็บค้างไว้ในคีย์
- เขียน Redis hash
agent_modeเก็บ config ทั้งชุด พร้อมตั้งค่าwarningSentเป็น 0 และเวลาเริ่มต้น - เพิ่มสมาชิกลง sorted set
agent_sessionsโดยใช้ score เป็นเวลา epoch ที่ควรส่งข้อความเตือน - ส่งข้อความ greeting ให้ผู้ใช้ผ่าน LINE push API
โหมด department_picker — ให้ผู้ใช้เลือกแผนก
ระบบส่ง flex message รายการแผนกให้ผู้ใช้เลือก และเก็บ webhook ปัจจุบันไว้ที่
mbox_pending_webhook เพื่อนำไปใช้ตอน handoff จริงหลังผู้ใช้กดเลือกแผนกแล้ว
โหมด exit — ออกจากโหมดเจ้าหน้าที่
เมื่อผู้ใช้พิมพ์คำที่อยู่ในรายการ exit keyword ระบบจะสั่ง resolve conversation ที่ Mbox
ลบคีย์ agent_mode ถอนสมาชิกออกจาก agent_sessions แล้วส่งข้อความปิดการสนทนา
Cron ตรวจ timeout (profile cron-scheduler ทุก 1 นาที)
MboxTimeoutService.Run ดึงสมาชิกใน agent_sessions ที่ score ถึงกำหนดแล้ว จากนั้นดำเนินการเป็น 2 ระยะ
- ระยะที่ 1 (
warningSentเป็น 0) — ส่งข้อความเตือนว่ายังรอเจ้าหน้าที่อยู่ ตั้งwarningSentเป็น 1 แล้วเลื่อน score ออกไปอีกเท่ากับ(timeoutMinutes - warningMinutes) * 60วินาที - ระยะที่ 2 (
warningSentเป็น 1) — ถือว่าหมดเวลาจริง ระบบจะปิด conversation ที่ Mbox ลบคีย์agent_modeถอนออกจาก sorted set แล้วส่งข้อความแจ้ง timeout - หากพบสถานะที่ไม่สมบูรณ์หรือ hash หายไปแล้ว จะเก็บกวาดรายการนั้นออกจาก sorted set
ไฟล์และฟังก์ชันหลัก
| ไฟล์ | หน้าที่ |
|---|---|
internal/mbox/service_handoff.go | MboxHandoffService.HandleHandoff, HandleDepartmentPicker, HandleExit, ResolveMboxConversation, forwardWebhook, sendFlexMessage, sendLineMessage, channelAccessToken รวมถึงโครงสร้าง MboxConfig, MboxHandoffPayload และค่าคงที่ forwardTimeout 5 วินาที |
internal/mbox/consumer.go | Consumer.HandleMboxHandoff — dispatch ตามฟิลด์ประเภทใน payload ระหว่าง exit, department_picker และโหมด handoff ปกติ |
internal/cronscheduler/mbox_timeout.go | MboxTimeoutService.Run, processExpiredMember, sendLineMessage |
internal/mboxx/mboxx.go | REST client ของ Mbox ใช้ header api_access_token |
cmd/worker/main.go | runCronScheduler — ผูก consumer และ cron job เข้าด้วยกัน |
คิวที่เกี่ยวข้อง: mbox_handoff บน profile cron-scheduler
จุดเชื่อมต่อกับ Service อื่น
- line-management-webhook-go — ตรวจ keyword จาก cache
webhook_configแล้ว publish งานเข้าคิว - action-execute — action ประเภท
talk_to_agentเป็นอีกต้นทางหนึ่งของงานนี้ - Redis (มีบทบาทสำคัญมาก) —
agent_mode:<lineOaId>:<userId>เก็บสถานะแบบ hash,agent_sessionsเป็น sorted set จับเวลา,mbox_pending_webhook:<lineOaId>:<userId>,mbox_inbox:<inboxId>และwebhook_config:<webhookId> - ตาราง
line_oa— ใช้channel_access_tokenและmessage_handling_config.mbox - Mbox REST API — สร้างและปิด conversation รวมถึง assign team โดยตั้ง timeout ไว้ 5 วินาที
- LINE API —
POST /v2/bot/message/pushสำหรับข้อความ greeting, warning, end, timeout และ flex message เลือกแผนก - ทำงานคู่กับ การรับ Callback จากระบบ Live Chat ซึ่งรับเหตุการณ์ย้อนกลับจาก Mbox