Sessions and memory

การรับรู้สถานะเซสชัน

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

องค์ประกอบสามส่วนทำงานร่วมกัน:

  1. บันทึกสัญญาณแบบคงทน บันทึกการเปลี่ยนแปลงสถานะที่เลือกไว้แยกตามเซสชัน
  2. ตัวเฝ้าดู เก็บเคอร์เซอร์แยกตามเป้าหมายและรับการแจ้งเตือนสถานะล้าสมัยแบบรวมเพียงหนึ่งครั้ง
  3. การปรับสถานะให้สอดคล้อง ดึงเฉพาะส่วนต่างที่แน่นอนผ่าน session_status โดยใช้ changesSince

บันทึกสัญญาณ

OpenClaw เพิ่มเหตุการณ์ที่มีชนิดกำกับลงในฐานข้อมูลสถานะที่ใช้ร่วมกัน (session_state_events) เมื่อเซสชันที่ถูกเฝ้าดูมีการเปลี่ยนแปลงอย่างมีนัยสำคัญ เหตุการณ์ประกอบด้วยข้อมูลเมตาและข้อมูลสรุปหนึ่งบรรทัด โดยไม่มีเนื้อหาข้อความรวมอยู่ด้วยเด็ดขาด

ชนิด บันทึกเมื่อ แจ้งตัวเฝ้าดู
human_direct_message มนุษย์ส่งรอบสนทนาโดยตรงไปยังเซสชันที่ถูกเฝ้าดู ใช่
upstream_missing แหล่งต้นทางของเซสชันที่รับเข้ามาหายไป ใช่
goal_changed สถานะเป้าหมายของเซสชันถูกสร้าง อัปเดต หรือล้าง ใช่
child_spawned มีการสร้างเซสชันลูกของเอเจนต์ย่อยหรือ ACP ไม่ (ตั้งค่าเริ่มต้นให้เคอร์เซอร์)
run_completed การเรียกใช้เซสชันลูกสิ้นสุดโดยสำเร็จ ไม่ (บันทึกเท่านั้น)
run_failed การเรียกใช้เซสชันลูกล้มเหลว หมดเวลา หรือถูกยกเลิก ไม่ (บันทึกเท่านั้น)
compacted ประวัติของเซสชันถูกย่อ ไม่ (บันทึกเท่านั้น)
adopted เซสชันแค็ตตาล็อกถูกรับเข้ามาใน OpenClaw ไม่ (บันทึกเท่านั้น)

แต่ละเหตุการณ์ระบุผู้ดำเนินการ (human, agent หรือ system) การเรียกใช้เซสชันลูกที่ถูกยกเลิกและหมดเวลาจะถูกบันทึกเป็นความล้มเหลว โดยคงผลลัพธ์ที่แน่นอน (cancelled, timeout หรือ error) ไว้ในเพย์โหลดของเหตุการณ์

เวอร์ชันสถานะ ของเซสชันคือหมายเลขลำดับสูงสุดในบันทึกของเซสชันนั้น โดยติดตามไว้ในส่วนหัวแบบคงทนประจำเซสชันซึ่งยังคงอยู่หลังการตัดทอน แถว sessions_list จะมี stateVersion เมื่อเซสชันบันทึกการเปลี่ยนแปลงแล้ว ส่วน session_status จะรายงานค่านี้เสมอ

ชนิดที่ใช้บันทึกเท่านั้นมีไว้สำหรับประวัติการปรับสถานะให้สอดคล้อง ไม่ใช่การแจ้งเตือน การส่งการแจ้งเตือนตามปกติเมื่อการเรียกใช้เซสชันลูกเสร็จสมบูรณ์ยังคงเป็นหน้าที่ของ การประกาศจากเอเจนต์ย่อย และบันทึกสัญญาณจะไม่สร้างรายการซ้ำ

ตัวเฝ้าดู

ตัวเฝ้าดูคือเซสชันที่เก็บเคอร์เซอร์ (session_watch_cursors) ของเป้าหมาย เคอร์เซอร์มาจากสองแหล่ง:

  • โดยนัย (ขอบเขตการสร้างเซสชัน) เมื่อเซสชันสร้างเอเจนต์ย่อยหรือเซสชันลูกของ ACP เคอร์เซอร์ของเซสชันแม่จะได้รับค่าเริ่มต้นโดยอัตโนมัติเป็นเวอร์ชันขณะสร้างเซสชันลูก เซสชันแม่ไม่ต้องสมัครรับข้อมูลด้วยตนเอง
  • โดยชัดแจ้ง (sessions_send watch: true) ผู้ประสานงานใดๆ สามารถเฝ้าดูเป้าหมายที่ไม่ได้สร้างขึ้นจากตนเองได้ โดยส่ง watch: true ให้กับ sessions_send และหลังจากส่งข้อความสำเร็จ ผู้ส่งจะได้รับการลงทะเบียนเป็นตัวเฝ้าดูเซสชันที่ได้รับข้อความจริง การลงทะเบียนเริ่มต้นที่เวอร์ชันสถานะปัจจุบันของเป้าหมาย ประวัติก่อนหน้านั้นจะไม่ก่อให้เกิดการแจ้งเตือน ผลลัพธ์ของเครื่องมือจะรายงาน watched: true|false เมื่อตั้งค่าพารามิเตอร์นี้

ข้อมูลประจำตัวของตัวเฝ้าดูต้องเป็นคีย์เซสชันที่ระบุเอเจนต์ ภายใต้ session.scope="global" คีย์ global ที่ใช้ร่วมกันมีความกำกวมระหว่างเอเจนต์ ดังนั้นเซสชันดังกล่าวจะมีบันทึกแบบคงทนและ changesSince แต่ไม่มีการแจ้งเตือนเชิงรุก

การเฝ้าดูจะล้างตัวเอง แถวเคอร์เซอร์จะหมดอายุตามระยะเวลาเก็บรักษาบันทึกสัญญาณ ถูกนำออกเมื่อเซสชันตัวเฝ้าดูรีเซ็ต และถูกลบเมื่อเซสชันฝ่ายใดฝ่ายหนึ่งถูกลบ ไม่มีคำสั่งยกเลิกการเฝ้าดูใน v1

เซสชันที่ถูกเฝ้าดูซึ่งรับมาจากแค็ตตาล็อกเซสชันจะได้รับการตรวจสอบกิจกรรมโดยตรงจากมนุษย์ในแหล่งต้นทางตามรอบเวลาคงที่ กิจกรรมที่ตรวจพบจะเข้าสู่บันทึกสัญญาณและกระบวนการของตัวเฝ้าดูเช่นเดียวกับรอบสนทนาโดยตรงอื่นๆ จากมนุษย์

หากแหล่งต้นทางของเซสชันที่รับเข้ามาถูกลบจากภายนอก การตรวจสอบว่าไม่พบติดต่อกันสามครั้ง (ประมาณสามรอบการตรวจสอบ) จะสร้างสัญญาณ upstream_missing หนึ่งครั้งให้ตัวเฝ้าดูและนำลิงก์ต้นทางออก เมื่อดำเนินเซสชันแค็ตตาล็อกต่ออีกครั้ง ระบบจะสร้างลิงก์ใหม่

การแจ้งเตือน: หนึ่งครั้ง ไม่ใช่หลายครั้ง

เมื่อเกิดเหตุการณ์ที่เข้าเกณฑ์การแจ้งเตือนและเคอร์เซอร์ของตัวเฝ้าดูล้าหลัง ตัวเฝ้าดูจะได้รับการแจ้งเตือนจากระบบหนึ่งครั้งในรอบสนทนาถัดไป:

Code
เซสชัน "agent:main:subagent:child" มีการเปลี่ยนแปลง (ผู้ดำเนินการรายอื่น) ปรับสถานะให้สอดคล้องก่อนดำเนินการ: session_status sessionKey "agent:main:subagent:child" changesSince 12

ตัวเฝ้าดูที่เป็นเซสชันหลักจะถูกปลุกทันทีผ่านการปลุกด้วย Heartbeat ส่วนตัวเฝ้าดูที่เป็นเอเจนต์ย่อยซ้อนกันจะได้รับการแจ้งเตือนในรอบสนทนาถัดไป

โปรโตคอลนี้ออกแบบมาเพื่อป้องกันสแปมโดยเจตนา:

  • การแจ้งเตือนที่รอดำเนินการหนึ่งรายการต่อคู่ตัวเฝ้าดู/เป้าหมาย ข้อความแจ้งเตือนจะคงค่าแบบไบต์ต่อไบต์ขณะรอดำเนินการ และคิวเหตุการณ์ระบบจะกำจัดรายการซ้ำตามข้อความนั้น ดังนั้นแม้เป้าหมายเดียวกันจะเปลี่ยนแปลงอย่างรวดเร็วถึงยี่สิบครั้ง ก็ยังสร้างเพียงหนึ่งบรรทัดในพรอมต์ของตัวเฝ้าดู
  • วอเตอร์มาร์กที่ตรึงไว้ เคอร์เซอร์จะตรึงตำแหน่งที่แจ้งเตือนเมื่อการแจ้งเตือนถูกเพิ่มลงในคิว เหตุการณ์สำคัญที่เกิดขึ้นต่อจากนั้นจะเลื่อนเฉพาะวอเตอร์มาร์กของเหตุการณ์สำคัญ โดยไม่แจ้งเตือนซ้ำ
  • รับทราบเมื่อดึงออกจากคิว และเปิดใหม่เฉพาะเมื่อมีงานแทรกเข้ามา เมื่อรอบสนทนาของตัวเฝ้าดูใช้การแจ้งเตือนแล้ว เคอร์เซอร์จะเลื่อนไปข้างหน้า หากมีเหตุการณ์สำคัญเพิ่มเติมเกิดขึ้นระหว่างการเพิ่มลงในคิวและการดึงออกจากคิว ระบบจะเปิดการแจ้งเตือนใหม่เพียงหนึ่งรายการสำหรับส่วนที่เหลือ
  • ระงับการแจ้งเตือนตนเอง ตัวเฝ้าดูจะไม่ได้รับการแจ้งเตือนเกี่ยวกับเหตุการณ์ที่ตนเองเป็นผู้ก่อ
  • การกู้คืนหลังรีสตาร์ต การแจ้งเตือนที่รอดำเนินการอยู่ในคิวในหน่วยความจำ การกวาดตรวจเมื่อเริ่มต้นระบบจะสร้างการแจ้งเตือนเหล่านั้นขึ้นใหม่จากเคอร์เซอร์แบบคงทนหลัง Gateway รีสตาร์ต

การปรับสถานะให้สอดคล้อง

การแจ้งเตือนระบุสิ่งที่ตัวเฝ้าดูต้องทำอย่างชัดเจน session_status พร้อม changesSince: <version> จะส่งคืนเหตุการณ์ที่มีชนิดกำกับหลังจากเวอร์ชันนั้น (สูงสุด 200 รายการ) โดยไม่เลื่อนเคอร์เซอร์ใดๆ:

json
{  "stateVersion": 19,  "stateChanges": {    "events": [      {        "sequence": 14,        "kind": "human_direct_message",        "actorType": "human",        "summary": "ข้อความจากมนุษย์ผ่าน Telegram"      },      { "sequence": 19, "kind": "goal_changed", "actorType": "human", "summary": "อัปเดตเป้าหมายแล้ว" }    ],    "historyGap": false  }}

historyGap: true หมายความว่าเวอร์ชันที่ร้องขออยู่ก่อนประวัติที่ยังเก็บรักษาไว้ ให้รีเฟรชสถานะทั้งหมดของเซสชัน (sessions_history, session_status) แทนการถือว่าการตอบกลับเป็นส่วนต่างที่แน่นอน สัญญาณช่องว่างนี้แม่นยำ เพราะมาจากวอเตอร์มาร์กที่ถูกตัดทอนประจำเซสชัน ไม่ได้อนุมานจากการคำนวณเลขลำดับ

พื้นที่จัดเก็บและขีดจำกัด

ประวัติอยู่ในฐานข้อมูลสถานะที่ใช้ร่วมกัน โดยจำกัดไว้ที่ 30 วันและ 50,000 แถว ส่วนหัวประจำเซสชันยังคงเพิ่มขึ้นทางเดียวหลังการตัดทอน การบันทึกเป็นแบบพยายามให้ดีที่สุด การเพิ่มข้อมูลที่ล้มเหลวจะถูกบันทึกไว้และจะไม่ทำให้รอบสนทนาต้นทางล้มเหลว ดังนั้น stateVersion จึงเป็นส่วนหัวของบันทึกสัญญาณ ไม่ใช่เวอร์ชันการบันทึกข้อมูลการเปลี่ยนแปลงแบบทรานแซกชัน

ขีดจำกัดปัจจุบัน:

  • การส่งการแจ้งเตือนถือว่ามีกระบวนการ Gateway หนึ่งกระบวนการเป็นเจ้าของฐานข้อมูลสถานะที่ใช้ร่วมกัน Gateway หลายตัวใช้บันทึกแบบคงทนและ changesSince ร่วมกันได้ แต่ v1 จะไม่ส่งการแจ้งเตือนข้ามกระบวนการ
  • เหตุการณ์ Compaction ครอบคลุมเจ้าของ Compaction ของรันไทม์แบบฝัง แต่ Compaction ที่เกิดขึ้นเฉพาะในเนทีฟฮาร์เนสยังไม่ได้รับการบันทึกอย่างครบถ้วน
  • รายละเอียดเพย์โหลดของผลลัพธ์ที่ถูกยกเลิกในปัจจุบันสร้างโดยการเรียกใช้เซสชันลูกของ ACP ส่วนการยกเลิกเอเจนต์ย่อยแบบเนทีฟจะแสดงเป็นความล้มเหลวทั่วไป
  • การตรวจจับเสียงสะท้อนจากตนเองในแหล่งต้นทางจะเปรียบเทียบข้อความผู้ใช้ที่ปรับรูปแบบแล้ว พรอมต์ภายนอกที่ตรงกับหนึ่งใน 10 ข้อความล่าสุดจากผู้ใช้ฝั่ง OpenClaw ของเซสชันจะถือว่าเป็นเสียงสะท้อนจากตนเอง
  • แถว JSONL ภายในเครื่องของ Claude เพียงแถวเดียวที่มีขนาดใหญ่กว่าขีดจำกัดการสแกน 1 MiB ต่อรอบ จะขัดขวางเคอร์เซอร์ของเซสชันนั้นใน v1 ระบบจะไม่ข้ามไบต์ที่ยังไม่ได้จำแนกเด็ดขาด
  • การตรวจสอบ Claude บน Node ที่จับคู่กันจะจำแนกรายการทรานสคริปต์ล่าสุด 50 รายการต่อรอบ ข้อมูลจำนวนมากกว่านี้อาจอยู่นอกหน้าต่างการสแกนของ v1
  • การอ่านประวัติ Claude บน Node ที่จับคู่กันจะไม่แสดงผลลัพธ์ที่ยืนยันได้ว่าไม่พบเธรด ดังนั้นการลบ Claude ระยะไกลจึงไม่ถูกจำแนกเป็น upstream_missing ใน v1
  • เซสชันแค็ตตาล็อกที่ยังไม่ได้รับเข้ามาจะยังคงอยู่นอกชั้นการรับรู้ใน v1
  • เซสชันที่รับเข้ามาก่อนมีฟีเจอร์นี้จะไม่มีลิงก์ต้นทาง ให้ดำเนินเซสชันเหล่านั้นต่อจากแค็ตตาล็อกหนึ่งครั้งเพื่อเริ่มการตรวจสอบต้นทาง
  • ลิงก์ต้นทางถือว่าคีย์ของแต่ละเซสชันที่รับเข้ามาจับคู่กับเอเจนต์เจ้าของเพียงหนึ่งตัว (การรับเข้ามาใช้เอเจนต์ของพื้นที่จัดเก็บเริ่มต้น) v1 จะไม่ตรวจสอบการรับเธรดภายนอกเดียวกันเข้ามาโดยเอเจนต์หลายตัว

ที่เกี่ยวข้อง

Was this useful?
On this page

On this page