إدارة الجلسات والضغط (شرح متعمق)
يوضح هذا المستند كيف يدير OpenClaw الجلسات من البداية إلى النهاية:- توجيه الجلسات (كيف تُطابَق الرسائل الواردة مع
sessionKey) - مخزن الجلسات (
sessions.json) وما الذي يتتبعه - استمرار حفظ النصوص التفريغية (
*.jsonl) وبنيته - نظافة النصوص التفريغية (إصلاحات خاصة بموفر الخدمة قبل التشغيل)
- حدود السياق (نافذة السياق مقابل الرموز المتتبعة)
- الضغط (الضغط اليدوي + الضغط التلقائي) وأين يمكنك ربط أعمال ما قبل الضغط
- الصيانة الصامتة (مثلًا عمليات كتابة الذاكرة التي يجب ألا تنتج مخرجات مرئية للمستخدم)
- /concepts/session
- /concepts/compaction
- /concepts/memory
- /concepts/memory-search
- /concepts/session-pruning
- /reference/transcript-hygiene
مصدر الحقيقة: Gateway
تم تصميم OpenClaw حول عملية Gateway واحدة تملك حالة الجلسة.- يجب على واجهات المستخدم (تطبيق macOS، واجهة التحكم على الويب، TUI) الاستعلام من Gateway عن قوائم الجلسات وعدد الرموز.
- في الوضع البعيد، تكون ملفات الجلسات على المضيف البعيد؛ لذا فإن “التحقق من ملفات Mac المحلية” لن يعكس ما يستخدمه Gateway.
طبقتا الاستمرار
يحفظ OpenClaw الجلسات في طبقتين:-
مخزن الجلسات (
sessions.json)- خريطة مفتاح/قيمة:
sessionKey -> SessionEntry - صغير، قابل للتغيير، وآمن للتحرير (أو حذف الإدخالات)
- يتتبع بيانات تعريف الجلسة (معرّف الجلسة الحالي، آخر نشاط، المفاتيح التبديلية، عدادات الرموز، وغير ذلك)
- خريطة مفتاح/قيمة:
-
النص التفريغي (
<sessionId>.jsonl)- نص تفريغي بإضافة فقط مع بنية شجرية (تحتوي الإدخالات على
id+parentId) - يخزن المحادثة الفعلية + استدعاءات الأدوات + ملخصات الضغط
- يُستخدم لإعادة بناء سياق النموذج للأدوار المستقبلية
- نص تفريغي بإضافة فقط مع بنية شجرية (تحتوي الإدخالات على
المواقع على القرص
لكل وكيل، على مضيف Gateway:- المخزن:
~/.openclaw/agents/<agentId>/sessions/sessions.json - النصوص التفريغية:
~/.openclaw/agents/<agentId>/sessions/<sessionId>.jsonl- جلسات موضوعات Telegram:
.../<sessionId>-topic-<threadId>.jsonl
- جلسات موضوعات Telegram:
src/config/sessions.ts.
صيانة المخزن وعناصر التحكم في القرص
تتضمن استمرارية الجلسات عناصر تحكم صيانة تلقائية (session.maintenance) لملف sessions.json وملفات النصوص التفريغية:
mode: warn(الافتراضي) أوenforcepruneAfter: حد عمر الإدخالات القديمة للحذف (الافتراضي30d)maxEntries: حد أقصى للإدخالات فيsessions.json(الافتراضي500)rotateBytes: تدويرsessions.jsonعند زيادة حجمه (الافتراضي10mb)resetArchiveRetention: مدة الاحتفاظ بأرشيفات النصوص التفريغية*.reset.<timestamp>(الافتراضي: نفسها مثلpruneAfter؛ وتعطيل التنظيف باستخدامfalse)maxDiskBytes: ميزانية اختيارية لدليل الجلسات على القرصhighWaterBytes: الهدف الاختياري بعد التنظيف (الافتراضي80%منmaxDiskBytes)
mode: "enforce"):
- إزالة أقدم ملفات النصوص التفريغية المؤرشفة أو اليتيمة أولًا.
- إذا ظل الاستخدام أعلى من الهدف، تُزال أقدم إدخالات الجلسات وملفات النصوص التفريغية الخاصة بها.
- الاستمرار حتى يصبح الاستخدام عند
highWaterBytesأو أقل.
mode: "warn"، يبلّغ OpenClaw عن عمليات الإزالة المحتملة لكنه لا يغيّر المخزن أو الملفات.
شغّل الصيانة عند الطلب:
جلسات Cron وسجلات التشغيل
تنشئ تشغيلات Cron المعزولة أيضًا إدخالات جلسات/نصوص تفريغية، ولها عناصر تحكم احتفاظ مخصصة:cron.sessionRetention(الافتراضي24h) يحذف جلسات تشغيل Cron المعزولة القديمة من مخزن الجلسات (استخدمfalseللتعطيل).cron.runLog.maxBytes+cron.runLog.keepLinesيختصران ملفات~/.openclaw/cron/runs/<jobId>.jsonl(الافتراضيات:2_000_000بايت و2000سطر).
مفاتيح الجلسات (sessionKey)
يحدّد sessionKey أي حاوية محادثة أنت فيها (التوجيه + العزل).
الأنماط الشائعة:
- الدردشة الرئيسية/المباشرة (لكل وكيل):
agent:<agentId>:<mainKey>(الافتراضيmain) - المجموعة:
agent:<agentId>:<channel>:group:<id> - الغرفة/القناة (Discord/Slack):
agent:<agentId>:<channel>:channel:<id>أو...:room:<id> - Cron:
cron:<job.id> - Webhook:
hook:<uuid>(ما لم يُتجاوز)
معرّفات الجلسات (sessionId)
يشير كل sessionKey إلى sessionId حالي (ملف النص التفريغي الذي يواصل المحادثة).
قواعد عامة:
- إعادة الضبط (
/new,/reset) تنشئsessionIdجديدًا لذلكsessionKey. - إعادة الضبط اليومية (الافتراضي الساعة 4:00 صباحًا بالتوقيت المحلي على مضيف gateway) تنشئ
sessionIdجديدًا عند الرسالة التالية بعد حد إعادة الضبط. - انتهاء المهلة بسبب الخمول (
session.reset.idleMinutesأوsession.idleMinutesالقديم) ينشئsessionIdجديدًا عندما تصل رسالة بعد نافذة الخمول. عند ضبط اليومي + الخمول معًا، يُطبّق ما ينتهي أولًا. - حارس تشعّب الأصل للخيط (
session.parentForkMaxTokens, الافتراضي100000) يتجاوز تشعيب النص التفريغي الأصل عندما تكون جلسة الأصل كبيرة جدًا بالفعل؛ ويبدأ الخيط الجديد من جديد. اضبطه إلى0لتعطيله.
initSessionState() داخل src/auto-reply/reply/session.ts.
مخطط مخزن الجلسات (sessions.json)
نوع قيمة المخزن هو SessionEntry في src/config/sessions.ts.
الحقول الأساسية (ليست شاملة):
sessionId: معرّف النص التفريغي الحالي (يُشتق اسم الملف من هذا ما لم يتم ضبطsessionFile)updatedAt: الطابع الزمني لآخر نشاطsessionFile: تجاوز اختياري صريح لمسار النص التفريغيchatType: direct | group | room(يساعد واجهات المستخدم وسياسة الإرسال)provider,subject,room,space,displayName: بيانات تعريف لتسمية المجموعات/القنوات- المفاتيح التبديلية:
thinkingLevel,verboseLevel,reasoningLevel,elevatedLevelsendPolicy(تجاوز خاص بكل جلسة)
- اختيار النموذج:
providerOverride,modelOverride,authProfileOverride
- عدادات الرموز (على أفضل جهد / وتعتمد على موفر الخدمة):
inputTokens,outputTokens,totalTokens,contextTokens
compactionCount: عدد مرات اكتمال الضغط التلقائي لهذا مفتاح الجلسةmemoryFlushAt: الطابع الزمني لآخر تفريغ ذاكرة قبل الضغطmemoryFlushCompactionCount: عدد مرات الضغط وقت آخر تشغيل للتفريغ
بنية النص التفريغي (*.jsonl)
تُدار النصوص التفريغية بواسطة SessionManager من @mariozechner/pi-coding-agent.
الملف بصيغة JSONL:
- السطر الأول: رأس الجلسة (
type: "session"، ويشملid,cwd,timestamp, وparentSessionاختياريًا) - ثم: إدخالات الجلسة مع
id+parentId(شجرة)
message: رسائل المستخدم/المساعد/نتيجة الأداةcustom_message: رسائل تحقنها الإضافات وتدخل في سياق النموذج (ويمكن إخفاؤها من واجهة المستخدم)custom: حالة إضافات لا تدخل في سياق النموذجcompaction: ملخص ضغط محفوظ معfirstKeptEntryIdوtokensBeforebranch_summary: ملخص محفوظ عند التنقل في فرع من الشجرة
SessionManager لقراءتها وكتابتها.
نوافذ السياق مقابل الرموز المتتبعة
هناك مفهومان مختلفان مهمان:- نافذة سياق النموذج: حد أقصى صارم لكل نموذج (الرموز المرئية للنموذج)
- عدادات مخزن الجلسات: إحصاءات متدرجة تُكتب في
sessions.json(تُستخدم في /status ولوحات المعلومات)
- تأتي نافذة السياق من فهرس النماذج (ويمكن تجاوزها عبر الإعدادات).
- القيمة
contextTokensفي المخزن هي قيمة تقديرية/للتقارير أثناء التشغيل؛ فلا تتعامل معها على أنها ضمان صارم.
الضغط: ما هو
يلخّص الضغط المحادثة الأقدم في إدخالcompaction محفوظ داخل النص التفريغي ويُبقي الرسائل الحديثة كما هي.
بعد الضغط، ترى الأدوار المستقبلية:
- ملخص الضغط
- الرسائل بعد
firstKeptEntryId
حدود مقاطع الضغط وإقران الأدوات
عندما يقسم OpenClaw نصًا تفريغيًا طويلًا إلى مقاطع ضغط، فإنه يُبقي استدعاءات أدوات المساعد مقترنة بإدخالاتtoolResult المطابقة لها.
- إذا وقع تقسيم حصة الرموز بين استدعاء أداة ونتيجتها، فإن OpenClaw ينقل الحد إلى رسالة استدعاء أداة المساعد بدلًا من فصل الزوج.
- إذا كانت كتلة نتائج أدوات في النهاية ستدفع المقطع فوق الهدف لولا ذلك، فإن OpenClaw يحتفظ بكتلة الأدوات المعلّقة هذه ويبقي الذيل غير الملخّص كما هو.
- كتل استدعاءات الأدوات الملغاة/التي تحتوي على أخطاء لا تُبقي تقسيمًا معلّقًا مفتوحًا.
متى يحدث الضغط التلقائي (بيئة تشغيل Pi)
في وكيل Pi المضمّن، يُفعّل الضغط التلقائي في حالتين:- التعافي من التجاوز: يعيد النموذج خطأ تجاوز سياق
(
request_too_large,context length exceeded,input exceeds the maximum number of tokens,input token count exceeds the maximum number of input tokens,input is too long for the model,ollama error: context length exceeded، ومتغيرات مشابهة بصياغة موفر الخدمة) ← ضغط ← إعادة المحاولة. - الصيانة عند العتبة: بعد دور ناجح، عندما:
contextTokens > contextWindow - reserveTokens
حيث:
contextWindowهي نافذة سياق النموذجreserveTokensهي مساحة احتياطية مخصصة للمطالبات + مخرجات النموذج التالية
إعدادات الضغط (reserveTokens, keepRecentTokens)
توجد إعدادات الضغط في Pi داخل إعدادات Pi:
- إذا كانت
compaction.reserveTokens < reserveTokensFloor، يرفعها OpenClaw. - الحد الأدنى الافتراضي هو
20000رمز. - اضبط
agents.defaults.compaction.reserveTokensFloor: 0لتعطيل الحد الأدنى. - إذا كانت أعلى بالفعل، يتركها OpenClaw كما هي.
ensurePiCompactionReserveTokens() في src/agents/pi-settings.ts
(ويُستدعى من src/agents/pi-embedded-runner.ts).
الأسطح المرئية للمستخدم
يمكنك ملاحظة الضغط وحالة الجلسة عبر:/status(في أي جلسة دردشة)openclaw status(CLI)openclaw sessions/sessions --json- الوضع المطوّل:
🧹 Auto-compaction complete+ عدد مرات الضغط
الصيانة الصامتة (NO_REPLY)
يدعم OpenClaw الأدوار “الصامتة” للمهام الخلفية حيث يجب ألا يرى المستخدم مخرجات وسيطة.
الاصطلاح:
- يبدأ المساعد مخرجاته بالرمز الصامت الدقيق
NO_REPLY/no_replyللإشارة إلى “لا تُرسل ردًا إلى المستخدم”. - يزيل OpenClaw هذا أو يمنعه في طبقة التسليم.
- يكون منع الرمز الصامت الدقيق غير حساس لحالة الأحرف، لذا فإن
NO_REPLYوno_replyكلاهما يُحسبان عندما تكون الحمولة بالكامل هي الرمز الصامت فقط. - هذا مخصص فقط للأدوار الخلفية الحقيقية/التي لا تتطلب تسليمًا؛ وليس اختصارًا لطلبات المستخدم العادية القابلة للتنفيذ.
2026.1.10، يمنع OpenClaw أيضًا البث المتدفق للمسودات/الكتابة عندما
يبدأ مقطع جزئي بـ NO_REPLY، بحيث لا تُسرّب العمليات الصامتة مخرجات جزئية أثناء الدور.
”تفريغ الذاكرة” قبل الضغط (مطبّق)
الهدف: قبل حدوث الضغط التلقائي، تشغيل دور وكيل صامت يكتب حالة دائمة إلى القرص (مثلmemory/YYYY-MM-DD.md في مساحة عمل الوكيل) حتى لا
يمحو الضغط السياق الحرج.
يستخدم OpenClaw نهج التفريغ قبل العتبة:
- مراقبة استخدام سياق الجلسة.
- عندما يتجاوز “عتبة مرنة” (أقل من عتبة الضغط في Pi)، شغّل توجيهًا صامتًا إلى الوكيل يقول “اكتب الذاكرة الآن”.
- استخدم الرمز الصامت الدقيق
NO_REPLY/no_replyحتى لا يرى المستخدم أي شيء.
agents.defaults.compaction.memoryFlush):
enabled(الافتراضي:true)softThresholdTokens(الافتراضي:4000)prompt(رسالة المستخدم لدور التفريغ)systemPrompt(مطالبة نظام إضافية تُلحق بدور التفريغ)
- تتضمن المطالبة الافتراضية/مطالبة النظام تلميح
NO_REPLYلمنع التسليم. - يُشغَّل التفريغ مرة واحدة لكل دورة ضغط (ويُتتبَّع ذلك في
sessions.json). - يعمل التفريغ فقط لجلسات Pi المضمّنة (تتجاوزها الواجهات الخلفية لـ CLI).
- يُتجاوز التفريغ عندما تكون مساحة عمل الجلسة للقراءة فقط (
workspaceAccess: "ro"أو"none"). - راجع Memory لتخطيط ملفات مساحة العمل وأنماط الكتابة.
session_before_compact في API الخاصة بالإضافات، لكن
منطق التفريغ في OpenClaw يوجد اليوم في جهة Gateway.
قائمة التحقق لاستكشاف الأخطاء وإصلاحها
- مفتاح الجلسة غير صحيح؟ ابدأ من /concepts/session وأكّد
sessionKeyفي/status. - عدم تطابق بين المخزن والنص التفريغي؟ أكّد مضيف Gateway ومسار المخزن من
openclaw status. - ضغط متكرر بشكل مزعج؟ تحقّق من:
- نافذة سياق النموذج (صغيرة جدًا)
- إعدادات الضغط (قد يؤدي ارتفاع
reserveTokensجدًا بالنسبة إلى نافذة النموذج إلى ضغط أبكر) - تضخم نتائج الأدوات: فعّل/اضبط تقليم الجلسات
- تسرّب الأدوار الصامتة؟ أكّد أن الرد يبدأ بـ
NO_REPLY(رمز دقيق غير حساس لحالة الأحرف) وأنك تستخدم إصدارًا يتضمن إصلاح منع البث المتدفق.