การจัดการเซสชัน¶
- OpenClaw ถือว่า หนึ่งเซสชันแชตโดยตรงต่อเอเจนต์ เป็นหลัก OpenClaw ถือว่า หนึ่งเซสชันแชตตรงต่อหนึ่งเอเจนต์ เป็นหลัก แชตตรงจะถูกรวมเป็น
agent:<agentId>:<mainKey>(ค่าเริ่มต้นmain) ในขณะที่แชตกลุ่ม/ช่องทางจะมีคีย์ของตัวเอง และจะเคารพsession.mainKey. 41.session.mainKeyจะถูกนำไปใช้
ใช้ session.dmScope เพื่อควบคุมการจัดกลุ่ม ข้อความตรง(DMs):
main(ค่าเริ่มต้น): DMs ทั้งหมดใช้เซสชันหลักร่วมกันเพื่อความต่อเนื่องper-peer: แยกตาม sender id ข้ามช่องทางper-channel-peer: แยกตาม channel + sender (แนะนำสำหรับอินบ็อกซ์หลายผู้ใช้)-
per-account-channel-peer: แยกตามบัญชี + ช่องทาง + ผู้ส่ง (แนะนำสำหรับอินบ็อกซ์หลายบัญชี)per-account-channel-peer: แยกตาม account + channel + sender (แนะนำสำหรับอินบ็อกซ์หลายบัญชี) ใช้session.identityLinksเพื่อแมป peer id ที่มีคำนำหน้าผู้ให้บริการให้เป็นตัวตนมาตรฐาน เพื่อให้บุคคลเดียวกันใช้เซสชัน DM ร่วมกันข้ามช่องทางเมื่อใช้per-peer,per-channel-peer, หรือper-account-channel-peer.
โหมด DM ปลอดภัย (แนะนำสำหรับการตั้งค่าหลายผู้ใช้)¶
คำเตือนด้านความปลอดภัย: หากเอเจนต์ของคุณสามารถรับ DM จาก หลายคน ได้ ขอแนะนำอย่างยิ่งให้เปิดโหมด DM ปลอดภัย หากไม่เปิด ผู้ใช้ทุกคนจะใช้บริบทการสนทนาเดียวกัน ซึ่งอาจทำให้ข้อมูลส่วนตัวรั่วไหลระหว่างผู้ใช้ได้ 43. หากไม่มีสิ่งนี้ ผู้ใช้ทั้งหมดจะแชร์บริบทการสนทนาเดียวกัน ซึ่งอาจทำให้ข้อมูลส่วนตัวรั่วไหลระหว่างผู้ใช้
ตัวอย่างปัญหาด้วยการตั้งค่าเริ่มต้น:
- Alice (
<SENDER_A>) ส่งข้อความถึงเอเจนต์ของคุณเกี่ยวกับเรื่องส่วนตัว (เช่น การนัดหมายแพทย์) - Bob (
<SENDER_B>) ส่งข้อความถึงเอเจนต์ถามว่า “เราคุยอะไรกันอยู่?” - เนื่องจาก DM ทั้งสองใช้เซสชันเดียวกัน โมเดลอาจตอบ Bob โดยอ้างอิงบริบทก่อนหน้าของ Alice
วิธีแก้ไข: ตั้งค่า dmScope เพื่อแยกเซสชันต่อผู้ใช้:
// ~/.openclaw/openclaw.json
{
session: {
// Secure DM mode: isolate DM context per channel + sender.
dmScope: "per-channel-peer",
},
}
ควรเปิดเมื่อใด:
- คุณมีการอนุมัติการจับคู่สำหรับผู้ส่งมากกว่าหนึ่งราย
- คุณใช้ DM allowlist ที่มีหลายรายการ
- คุณตั้งค่า
dmPolicy: "open" - มีหลายหมายเลขโทรศัพท์หรือหลายบัญชีที่สามารถส่งข้อความถึงเอเจนต์ของคุณได้
หมายเหตุ:
- ค่าเริ่มต้นคือ
dmScope: "main"เพื่อความต่อเนื่อง (DM ทั้งหมดใช้เซสชันหลักร่วมกัน) เหมาะสำหรับการตั้งค่าผู้ใช้คนเดียว 44. สิ่งนี้เหมาะสำหรับการตั้งค่าแบบผู้ใช้เดียว - สำหรับอินบ็อกซ์หลายบัญชีในช่องทางเดียวกัน ควรใช้
per-account-channel-peer - หากบุคคลเดียวกันติดต่อคุณผ่านหลายช่องทาง ให้ใช้
session.identityLinksเพื่อรวมเซสชัน DM ของเขาเป็นตัวตนมาตรฐานเดียว - คุณสามารถตรวจสอบการตั้งค่า DM ได้ด้วย
openclaw security audit(ดู security)
Gateway คือแหล่งความจริงเพียงหนึ่งเดียว¶
- สถานะของเซสชันทั้งหมดเป็น กรรมสิทธิ์ของ gateway (OpenClaw “ตัวหลัก”) 46. ไคลเอนต์ UI (แอป macOS, WebChat ฯลฯ) 47. ต้องสอบถาม gateway เพื่อดูรายการเซสชันและจำนวนโทเค็น แทนการอ่านไฟล์ภายในเครื่อง
- ใน โหมดรีโมต ที่เก็บเซสชันที่สำคัญจะอยู่บนโฮสต์Gateway ระยะไกล ไม่ใช่บน Mac ของคุณ
- จำนวนโทเคนที่แสดงใน UI มาจากฟิลด์ในสโตร์ของ Gateway (
inputTokens,outputTokens,totalTokens,contextTokens) ไคลเอนต์จะไม่พาร์สทรานสคริปต์ JSONL เพื่อ “แก้ไข” ยอดรวม 48. ไคลเอนต์จะไม่แยกวิเคราะห์ทรานสคริปต์ JSONL เพื่อ “แก้ไข” ยอดรวม
ตำแหน่งที่เก็บสถานะ¶
- บน โฮสต์Gateway:
- ไฟล์สโตร์:
~/.openclaw/agents/<agentId>/sessions/sessions.json(ต่อเอเจนต์) - ทรานสคริปต์:
~/.openclaw/agents/<agentId>/sessions/<SessionId>.jsonl(เซสชันหัวข้อ Telegram ใช้.../<SessionId>-topic-<threadId>.jsonl) - สโตร์เป็นแมป
sessionKey -> { sessionId, updatedAt, ... 49. }. 50. การลบรายการปลอดภัย; ระบบจะสร้างใหม่เมื่อมีการร้องขอ - เอนทรีของกลุ่มอาจมี
displayName,channel,subject,room, และspaceเพื่อใช้ติดป้ายเซสชันใน UI - เอนทรีของเซสชันมีเมทาดาทา
origin(ป้ายกำกับ + คำใบ้การกำหนดเส้นทาง) เพื่อให้ UI อธิบายที่มาของเซสชันได้ - OpenClaw ไม่ อ่านโฟลเดอร์เซสชัน Pi/Tau แบบเดิม
การตัดแต่งเซสชัน¶
OpenClaw จะตัด ผลลัพธ์เครื่องมือเก่า ออกจากบริบทในหน่วยความจำก่อนเรียก LLM ตามค่าเริ่มต้น การทำเช่นนี้ ไม่ เขียนทับประวัติ JSONL ดู /concepts/session-pruning สิ่งนี้จะทำงานเฉพาะเมื่อ workspace สามารถเขียนได้ การคอมแพคชันเป็นแบบ คงอยู่ถาวร (ต่างจากการตัดแต่งเซสชัน) ดู /concepts/session-pruning.
การล้างหน่วยความจำก่อนการคอมแพ็กต์¶
เมื่อเซสชันใกล้ถึงการคอมแพ็กต์อัตโนมัติ OpenClaw สามารถรัน การล้างหน่วยความจำแบบเงียบ
เพื่อเตือนโมเดลให้เขียนบันทึกถาวรลงดิสก์ การทำงานนี้จะเกิดขึ้นเฉพาะเมื่อเวิร์กสเปซสามารถเขียนได้ ดู Memory และ
Compaction ดู Memory และ
Compaction รีเซ็ตเมื่อว่าง (ไม่บังคับ): idleMinutes จะเพิ่มหน้าต่างเวลาว่างแบบเลื่อน
การแมปทรานสปอร์ต → คีย์เซสชัน¶
- แชตตรงปฏิบัติตาม
session.dmScope(ค่าเริ่มต้นmain) main:agent:<agentId>:<mainKey>(ความต่อเนื่องข้ามอุปกรณ์/ช่องทาง)- หมายเลขโทรศัพท์และหลายช่องทางสามารถแมปไปยังคีย์หลักของเอเจนต์เดียวกันได้ โดยทำหน้าที่เป็นทรานสปอร์ตเข้าสู่การสนทนาเดียว
per-peer:agent:<agentId>:dm:<peerId>per-channel-peer:agent:<agentId>:<channel>:dm:<peerId>per-account-channel-peer:agent:<agentId>:<channel>:<accountId>:dm:<peerId>(accountId ค่าเริ่มต้นคือdefault)- หาก
session.identityLinksตรงกับ peer id ที่มีคำนำหน้าผู้ให้บริการ (เช่นtelegram:123) คีย์มาตรฐานจะมาแทนที่<peerId>เพื่อให้บุคคลเดียวกันใช้เซสชันร่วมกันข้ามช่องทาง - แชตกลุ่มจะแยกสถานะ:
agent:<agentId>:<channel>:group:<id>(ห้อง/ช่องทางใช้agent:<agentId>:<channel>:channel:<id>) - หัวข้อฟอรัม Telegram จะต่อท้าย
:topic:<threadId>เข้ากับ group id เพื่อแยกสถานะ - คีย์
group:<id>แบบเดิมยังคงถูกรับรู้เพื่อการย้ายข้อมูล - บริบทขาเข้าอาจยังใช้
group:<id>โดยอนุมานช่องทางจากProviderและปรับให้เป็นรูปแบบมาตรฐานagent:<agentId>:<channel>:group:<id> - แหล่งอื่นๆ:
- งาน Cron:
cron:<job.id> - Webhook:
hook:<uuid>(เว้นแต่จะตั้งค่าโดยฮุกอย่างชัดเจน) - การรันโหนด:
node-<nodeId>
วงจรชีวิต¶
- นโยบายรีเซ็ต: เซสชันจะถูกใช้ซ้ำจนกว่าจะหมดอายุ และการหมดอายุจะถูกประเมินเมื่อมีข้อความขาเข้าถัดไป
- รีเซ็ตรายวัน: ค่าเริ่มต้นคือ 04:00 น. ตามเวลาท้องถิ่นบนโฮสต์Gateway เซสชันจะถือว่าเก่าหากการอัปเดตล่าสุดก่อนเวลารีเซ็ตรายวันล่าสุด
/new <model>รองรับนามแฝงของโมเดล,provider/modelหรือชื่อผู้ให้บริการ (จับคู่แบบคลุมเครือ) เพื่อกำหนดโมเดลของเซสชันใหม่ รีเซ็ตเมื่อว่าง (ไม่บังคับ):idleMinutesเพิ่มหน้าต่างเวลาว่างแบบเลื่อน เมื่อกำหนดทั้งรีเซ็ตรายวันและรีเซ็ตเมื่อว่าง อย่างใดอย่างหนึ่งที่หมดก่อน จะบังคับเริ่มเซสชันใหม่- โหมดเดิมแบบว่างอย่างเดียว: หากคุณตั้งค่า
session.idleMinutesโดยไม่มีคอนฟิกsession.reset/resetByTypeใดๆ OpenClaw จะคงอยู่ในโหมดว่างอย่างเดียวเพื่อความเข้ากันได้ย้อนหลัง - การแทนที่ตามประเภท (ไม่บังคับ):
resetByTypeช่วยให้คุณแทนที่นโยบายสำหรับเซสชันdirect,groupและthread(thread = เธรดของ Slack/Discord, หัวข้อ Telegram, Matrix threads เมื่อคอนเนกเตอร์รองรับ) - การแทนที่ตามช่องทาง (ไม่บังคับ):
resetByChannelแทนที่นโยบายรีเซ็ตสำหรับช่องทางหนึ่งๆ (มีผลกับทุกประเภทเซสชันของช่องทางนั้น และมีลำดับความสำคัญเหนือreset/resetByType) - ทริกเกอร์การรีเซ็ต: ข้อความ
/newหรือ/resetแบบตรงตัว (รวมส่วนเพิ่มเติมในresetTriggers) จะเริ่ม session id ใหม่และส่งต่อข้อความที่เหลือ/new <model>ยอมรับนามแฝงโมเดล,provider/model, หรือชื่อผู้ให้บริการ (จับคู่แบบคลุมเครือ) เพื่อกำหนดโมเดลของเซสชันใหม่ หากส่ง/newหรือ/resetเพียงอย่างเดียว OpenClaw จะรันรอบทักทายสั้นๆ เพื่อยืนยันการรีเซ็ต หากส่ง/newหรือ/resetเพียงอย่างเดียว OpenClaw จะรันเทิร์นทักทายสั้น ๆ ว่า “hello” เพื่อยืนยันการรีเซ็ต ดู /concepts/compaction - รีเซ็ตด้วยตนเอง: ลบคีย์เฉพาะจากสโตร์หรือลบทรานสคริปต์ JSONL ข้อความถัดไปจะสร้างใหม่
- งาน Cron แบบแยกจะสร้าง
sessionIdใหม่เสมอในแต่ละรอบ (ไม่มีการใช้ซ้ำเมื่อว่าง)
นโยบายการส่ง (ไม่บังคับ)¶
บล็อกการส่งสำหรับประเภทเซสชันเฉพาะโดยไม่ต้องระบุ id รายตัว
{
session: {
sendPolicy: {
rules: [
{ action: "deny", match: { channel: "discord", chatType: "group" } },
{ action: "deny", match: { keyPrefix: "cron:" } },
],
default: "allow",
},
},
}
การแทนที่ขณะรัน (เฉพาะเจ้าของ):
/send on→ อนุญาตสำหรับเซสชันนี้/send off→ ปฏิเสธสำหรับเซสชันนี้/send inherit→ ล้างการแทนที่และใช้กฎคอนฟิก ส่งเป็นข้อความเดี่ยวเพื่อให้ระบบลงทะเบียน
การกำหนดค่า (ตัวอย่างการเปลี่ยนชื่อ ไม่บังคับ)¶
// ~/.openclaw/openclaw.json
{
session: {
scope: "per-sender", // แยกคีย์ของกลุ่มออกจากกัน
dmScope: "main", // ความต่อเนื่องของ DM (ตั้งค่าเป็น per-channel-peer/per-account-channel-peer สำหรับกล่องข้อความที่ใช้ร่วมกัน)
identityLinks: {
alice: ["telegram:123456789", "discord:987654321012345678"],
},
reset: {
// ค่าเริ่มต้น: mode=daily, atHour=4 (เวลาท้องถิ่นของโฮสต์เกตเวย์)
// หากตั้งค่า idleMinutes ด้วย ตัวที่หมดอายุก่อนจะถูกใช้
mode: "daily",
atHour: 4,
idleMinutes: 120,
},
resetByType: {
thread: { mode: "daily", atHour: 4 },
direct: { mode: "idle", idleMinutes: 240 },
group: { mode: "idle", idleMinutes: 120 },
},
resetByChannel: {
discord: { mode: "idle", idleMinutes: 10080 },
},
resetTriggers: ["/new", "/reset"],
store: "~/.openclaw/agents/{agentId}/sessions/sessions.json",
mainKey: "main",
},
}
การตรวจสอบ¶
openclaw status— แสดงพาธสโตร์และเซสชันล่าสุดopenclaw sessions --json— ดัมพ์ทุกเอนทรี (กรองด้วย--active <minutes>)openclaw gateway call sessions.list --params '{}'— ดึงเซสชันจาก Gateway ที่กำลังรันอยู่ (ใช้--url/--tokenสำหรับการเข้าถึง Gateway ระยะไกล)- ส่ง
/statusเป็นข้อความเดี่ยวในแชตเพื่อดูว่าเอเจนต์เข้าถึงได้หรือไม่ ใช้บริบทเซสชันไปเท่าใด การสลับโหมดคิด/ละเอียดปัจจุบัน และเวลาที่รีเฟรชข้อมูลรับรอง WhatsApp web ล่าสุด (ช่วยตรวจพบความจำเป็นต้องเชื่อมใหม่) - ส่ง
/context listหรือ/context detailเพื่อดูสิ่งที่อยู่ใน system prompt และไฟล์เวิร์กสเปซที่ถูกฉีดเข้าไป (รวมถึงตัวที่ใช้บริบทมากที่สุด) - ส่ง
/stopเป็นข้อความเดี่ยวเพื่อยกเลิกรันปัจจุบัน ล้างฟอลโลว์อัปที่ค้างคิวสำหรับเซสชันนั้น และหยุดการรันซับเอเจนต์ใดๆ ที่ถูกสร้างจากมัน (คำตอบจะรวมจำนวนที่หยุด) - ส่ง
/compact(คำสั่งเสริมไม่บังคับ) เป็นข้อความเดี่ยวเพื่อสรุปบริบทเก่าและคืนพื้นที่หน้าต่าง ดู /concepts/compaction หากตัวเชื่อมต่ออัปเดตเพียงการกำหนดเส้นทางการส่ง (เช่น เพื่อให้เซสชันหลักของ DM สดใหม่) ก็ควรส่งบริบทขาเข้าเพื่อให้เซสชันคงเมทาดาทาเชิงอธิบายไว้ - สามารถเปิดทรานสคริปต์ JSONL โดยตรงเพื่อทบทวนเทิร์นทั้งหมด
เคล็ดลับ¶
- รักษาคีย์หลักให้ใช้กับทราฟฟิกแบบ 1:1 ปล่อยให้กลุ่มใช้คีย์ของตนเอง
- เมื่อทำการล้างอัตโนมัติ ให้ลบคีย์รายตัวแทนการลบทั้งสโตร์เพื่อคงบริบทส่วนอื่นไว้
เมทาดาทาต้นกำเนิดเซสชัน¶
เอนทรีเซสชันแต่ละรายการจะบันทึกที่มา(ตามความพยายามที่ดีที่สุด)ไว้ใน origin:
label: ป้ายกำกับสำหรับมนุษย์ (แก้ไขจากป้ายการสนทนา + หัวข้อกลุ่ม/ช่องทาง)provider: channel id ที่ถูกปรับมาตรฐาน (รวมส่วนขยาย)from/to: routing id ดิบจากซองจดหมายขาเข้าaccountId: account id ของผู้ให้บริการ (เมื่อหลายบัญชี)threadId: thread/topic id เมื่อช่องทางรองรับ ฟิลด์ต้นกำเนิดจะถูกเติมสำหรับข้อความตรง ช่องทาง และกลุ่ม หากคอนเน็กเตอร์อัปเดตเฉพาะการกำหนดเส้นทางการส่งมอบ (เช่น เพื่อทำให้เซสชันหลักของ DM สดใหม่) ก็ควรส่งบริบทขาเข้าเพื่อให้เซสชันคงเมทาดาทาอธิบายที่มาไว้ ส่วนขยายสามารถทำได้โดยส่งConversationLabel,GroupSubject,GroupChannel,GroupSpace, และSenderNameในบริบทขาเข้า และเรียกrecordSessionMetaFromInbound(หรือส่งบริบทเดียวกันไปยังupdateLastRoute). ส่วนขยายสามารถทำได้โดยส่งConversationLabel,GroupSubject,GroupChannel,GroupSpaceและSenderNameในบริบทขาเข้า และเรียกrecordSessionMetaFromInbound(หรือส่งบริบทเดียวกันไปยังupdateLastRoute) Extensions can do this by sendingConversationLabel,GroupSubject,GroupChannel,GroupSpace, andSenderNamein the inbound context and callingrecordSessionMetaFromInbound(or passing the same context toupdateLastRoute).