Skip to main content

การโอนแชทให้เจ้าหน้าที่

ภาพรวม

เมื่อบอทตอบคำถามไม่ได้ หรือผู้ใช้พิมพ์ข้อความอย่าง "คุยกับเจ้าหน้าที่" ระบบต้องสลับจากโหมด "บอทตอบ" ไปเป็น "คนตอบ" โดยส่งบทสนทนาต่อไปยัง Mbox ซึ่งเป็นระบบ live chat แบบ Chatwoot และต้องกันไม่ให้ระบบตอบอัตโนมัติเข้าไปแทรกระหว่างที่เจ้าหน้าที่กำลังสนทนาอยู่

สถานะ "กำลังคุยกับเจ้าหน้าที่" ถูกเก็บใน Redis ด้วยคีย์รูปแบบ agent_mode:<lineOaId>:<userId> คู่กับ sorted set agent_sessions ที่ทำหน้าที่เป็นนาฬิกาจับเวลาหมดอายุของแต่ละ session

Business Flow

โหมด handoff — เข้าสู่โหมดเจ้าหน้าที่

  1. รับ MboxHandoffPayload ที่มี mboxConfig ภายใน ประกอบด้วย base URL, API token, account ID, inbox ID, LINE webhook URL, ระยะเวลา timeout และ warning, ชุดข้อความ greeting / warning / end / timeout รวมถึงรายการ exit keyword
  2. ตรวจสอบซ้ำ — หากคีย์ agent_mode:<lineOaId>:<userId> มีอยู่แล้ว แปลว่าอยู่ในโหมดเจ้าหน้าที่ อยู่ก่อนแล้ว จึงข้ามการทำงาน
  3. Forward webhook เข้า Mbox เพื่อให้เกิด conversation ขึ้นทางฝั่งนั้น
    • ระบบจะใช้ webhook ที่เก็บค้างไว้ในคีย์ mbox_pending_webhook:<lineOaId>:<userId> ก่อน เนื่องจาก postback event ไม่สามารถสร้าง conversation ใน Mbox ได้ แต่ข้อความต้นทางที่ทำให้เกิด talk_to_agent สร้างได้
    • หากไม่มีค่าเก็บไว้ จะใช้ webhook ปัจจุบันแทน และหากการ forward ล้มเหลวจะไม่ถือเป็นข้อผิดพลาดร้ายแรง ระบบจะบันทึก log แล้วทำงานต่อ โดยตั้ง HTTP timeout ไว้ที่ 5 วินาที
  4. เขียน Redis hash agent_mode เก็บ config ทั้งชุด พร้อมตั้งค่า warningSent เป็น 0 และเวลาเริ่มต้น
  5. เพิ่มสมาชิกลง sorted set agent_sessions โดยใช้ score เป็นเวลา epoch ที่ควรส่งข้อความเตือน
  6. ส่งข้อความ 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.goMboxHandoffService.HandleHandoff, HandleDepartmentPicker, HandleExit, ResolveMboxConversation, forwardWebhook, sendFlexMessage, sendLineMessage, channelAccessToken รวมถึงโครงสร้าง MboxConfig, MboxHandoffPayload และค่าคงที่ forwardTimeout 5 วินาที
internal/mbox/consumer.goConsumer.HandleMboxHandoff — dispatch ตามฟิลด์ประเภทใน payload ระหว่าง exit, department_picker และโหมด handoff ปกติ
internal/cronscheduler/mbox_timeout.goMboxTimeoutService.Run, processExpiredMember, sendLineMessage
internal/mboxx/mboxx.goREST client ของ Mbox ใช้ header api_access_token
cmd/worker/main.gorunCronScheduler — ผูก 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 APIPOST /v2/bot/message/push สำหรับข้อความ greeting, warning, end, timeout และ flex message เลือกแผนก
  • ทำงานคู่กับ การรับ Callback จากระบบ Live Chat ซึ่งรับเหตุการณ์ย้อนกลับจาก Mbox