Technical reference
بررسی عمیق مدیریت نشستها
یک فرایند Gateway بهتنهایی مالک سرتاسری وضعیت نشست است. رابطهای کاربری (برنامه macOS، رابط وب Control UI و TUI) فهرست نشستها و شمارندههای توکن را از Gateway دریافت میکنند. در حالت راهدور، فایلهای نشست روی میزبان راهدور قرار دارند؛ بنابراین بررسی فایلهای Mac محلی، آنچه Gateway استفاده میکند را نشان نمیدهد.
ابتدا مستندات کلی را ببینید: مدیریت نشست، Compaction، نمای کلی حافظه، جستوجوی حافظه، هرس نشست، بهداشت رونوشت، و مرجع کامل پیکربندی در پیکربندی عامل.
دو لایه ماندگاری
- ردیفهای نشست (SQLite بهازای هر عامل) - نگاشت کلید/مقدار
sessionKey -> SessionEntry. وضعیت زماناجرای تغییرپذیر که مالک آن Gateway است. فرادادههایی مانند شناسه نشست فعلی، آخرین فعالیت، گزینههای روشن/خاموش و شمارندههای توکن را ردیابی میکند. - رویدادهای رونوشت (SQLite بهازای هر عامل) - فقطافزودنی و با ساختار درختی (ورودیها دارای
id+parentIdهستند). مکالمه، فراخوانی ابزارها و خلاصههای Compaction را ذخیره میکند و زمینه مدل را برای نوبتهای آینده بازسازی میکند. نقاط وارسی Compaction فرادادهای روی رونوشت جانشین فشردهشده هستند؛ یک Compaction جدید نسخه دوم.checkpoint.*.jsonlرا نمینویسد.
نصبهای قدیمیتر ممکن است همچنان فایلهای sessions.json را در پوشه
sessions/ عامل داشته باشند. این فایلها را ورودیهای قدیمی مهاجرت ردیف نشست یا اهداف صریح
نگهداری آفلاین در نظر بگیرید. راهاندازی Gateway و openclaw doctor --fix،
ردیفهای قدیمی فعال و تاریخچه رونوشت را بهطور خودکار به مخزن SQLite هر عامل
وارد میکنند. هنگامی که به بازرسی صریح یا شواهد اعتبارسنجی نیاز دارید،
openclaw doctor --session-sqlite inspect --session-sqlite-all-agents را اجرا کنید و سپس توالی مهاجرت
Doctor را دنبال کنید. اگر مهاجرت پس از بایگانیشدن
مصنوعات قدیمی رونوشت شکست خورد، از حالت بازیابی Doctor در همان توالی استفاده کنید.
بازیابی از مانیفستهای مهاجرت استفاده میکند، فقط مصنوعات پشتیبان بایگانیشده آسیبدیده را
بازمیگرداند، در صورت درخواست گزارشی پاکسازیشده برای یک issue در GitHub آماده میکند و
باعث نمیشود زماناجرای فعال دوباره فایلهای JSONL را بخواند.
خوانشگرهای تاریخچه Gateway از بارگذاری کل رونوشت خودداری میکنند، مگر اینکه سطح موردنظر به دسترسی دلخواه به تاریخچه نیاز داشته باشد. تاریخچه صفحه اول، تاریخچه گفتوگوی تعبیهشده، بازیابی پس از راهاندازی مجدد و بررسی توکن/مصرف، از خواندن محدود انتهای SQLite استفاده میکنند. پیمایش کامل رونوشتها از شاخص ناهمگام رونوشت عبور میکند و میان خوانشگرهای همزمان بهاشتراک گذاشته میشود.
مکانهای روی دیسک
برای هر عامل، روی میزبان Gateway (حلشده از طریق src/config/sessions.ts):
- مخزن ردیف نشست زماناجرا:
~/.openclaw/agents/<agentId>/agent/openclaw-agent.sqlite - ردیفهای رونوشت زماناجرا:
~/.openclaw/agents/<agentId>/agent/openclaw-agent.sqlite - مصنوعات قدیمی/بایگانی رونوشت:
~/.openclaw/agents/<agentId>/sessions/ - ورودی قدیمی مهاجرت ردیف:
~/.openclaw/agents/<agentId>/sessions/sessions.json
نگهداری مخزن و کنترلهای دیسک
session.maintenance نگهداری خودکار ردیفهای نشست SQLite، ردیفهای رونوشت SQLite، مصنوعات بایگانی و فایلهای جانبی مسیر حرکت را کنترل میکند:
| کلید | پیشفرض | توضیحات |
|---|---|---|
mode |
"enforce" |
یا "warn" (فقط گزارش، بدون تغییر) |
pruneAfter |
"30d" |
آستانه سن ورودیهای کهنه |
maxEntries |
500 |
سقف تعداد ورودیهای نشست |
resetArchiveRetention |
نگهداری (بدون آستانه سن) | آستانه سن بایگانیهای رونوشت *.reset.*/*.deleted.*؛ تعیین مدتزمان، حذف را فعال میکند |
maxDiskBytes |
10gb |
بودجه دیسک نشستها برای هر عامل؛ false آن را غیرفعال میکند |
highWaterBytes |
80% از maxDiskBytes |
هدف پس از پاکسازی بودجه |
بازنشانی نگاشت زنده sessionKey -> sessionId را جلو میبرد، اما نشست SQLite قبلی، رونوشت، مسیر حرکت و ردیفهای جستوجو را نگه میدارد. آن تاریخچه با همان کلید نشست قابل جستوجو باقی میماند؛ فهرستهای عادی ورودی و نشست فقط نگاشت زنده جدید را نشان میدهند. تاریخچه بازنشانیِ نگهداریشده با بودجه دیسک محدود میشود، نه با resetArchiveRetention که فقط مصنوعات بایگانی را بر اساس سن حذف میکند. حذف صریح متفاوت است: پیش از حذف ردیفهای نشست حذفشده، یک بایگانی فشرده رونوشت مینویسد و صحت آن را بررسی میکند (در صورت در دسترسبودن zstd، با *.jsonl.deleted.<timestamp>.zst).
اعمال maxDiskBytes از بایتهای فیزیکی استفاده میکند: فایل اصلی SQLite هر عامل، فایل -wal آن و فایلهای شمارششده در پوشه نشستهای عامل. این سازوکار هرگز اندازه JSON ردیفها را تخمین نمیزند یا اندازه منطقی ردیفها را از آن مجموع کم نمیکند.
نشستهای کاوش اجرای مدل Gateway (کلیدهای مطابق agent:*:explicit:model-run-<uuid>) دوره نگهداری ثابت و جداگانه 24h دارند. این هرس وابسته به فشار است: فقط هنگامی اجرا میشود که فشار نگهداری/سقف ورودی نشست ایجاد شده باشد و تنها پیش از مرحله پاکسازی/سقف سراسری ورودیهای کهنه انجام میشود. سایر نشستهای صریح از این دوره نگهداری استفاده نمیکنند.
هنگامی که مجموع مصرف فیزیکی از maxDiskBytes فراتر میرود، mode: "enforce" ابتدا فضای قابلبازیابی پایگاه داده را آزاد میکند و سپس قدیمیترین بایگانیهای نگهداریشده بازنشانی/حذف را برمیدارد. اگر مصرف همچنان بالاتر از highWaterBytes باشد، نشستهای تاریخی SQLite را بر اساس sessions.updated_at از قدیمیترین مورد پیمایش میکند. تاریخی یعنی شناسه نشست توسط هیچ ورودی زنده نشست، مقصد مسیر یا اجرای پذیرفتهشده/درحالاجرا ارجاع داده نمیشود. برای هر قربانی، پاکسازی پیش از آنکه یک تراکنش نوشتن ردیف نشست و رونوشت، مسیر حرکت، وضعیت فعال، شاخص و تصویرهای FTS آن را حذف کند، بایگانی فشرده را مینویسد، fsync میکند و دوباره میخواند. این شامل نشستهایی نیز میشود که رویدادهای مسیر حرکت دارند اما رویداد رونوشت ندارند. پاکسازی هنگام حذف، ارجاعهای مسیر، ورودی و پذیرش را دوباره بررسی میکند، پس از هر بایگانی یا نشست قربانی مصرف فیزیکی را دوباره اندازه میگیرد و در highWaterBytes متوقف میشود.
نوشتنهای ثبتشده و حذف ابتدا وارد WAL میشوند. پاکسازی از آن نقطه وارسی میگیرد تا WAL فوراً کوچک شود، سپس با vacuum افزایشی صفحات آزاد انتهایی واجد شرایط را از فایل اصلی بازمیگرداند؛ صفحاتی که هنوز قابلبازیابی نیستند در فایل اصلی باقی میمانند و بنابراین در اندازهگیری فیزیکی بعدی همچنان محاسبه میشوند. mode: "warn" مقدار فعلی مازاد فیزیکی را بدون گرفتن نقطه وارسی، نوشتن بایگانی یا حذف ردیفها گزارش میکند.
نگهداری را در صورت نیاز اجرا کنید:
openclaw sessions cleanup --dry-runopenclaw sessions cleanup --enforceنگهداری اشارهگرهای پایدار مکالمه خارجی، مانند نشستهای گروهی و نشستهای گفتوگوی محدود به رشته را حفظ میکند، اما ورودیهای مصنوعی زماناجرا (cron، قلابها، Heartbeat، ACP و عاملهای فرعی) پس از عبور از سن، تعداد یا بودجه دیسک پیکربندیشده همچنان میتوانند حذف شوند. اجراهای cron ایزوله از کنترل جداگانه cron.sessionRetention استفاده میکنند که مستقل از دوره نگهداری کاوش اجرای مدل است.
نوشتنهای عادی Gateway از دسترسیدهنده نشست عبور میکنند که تغییرات SQLite هر عامل را از مسیر نویسنده زماناجرا بهصورت ترتیبی اجرا میکند. کد زماناجرا باید کمککنندههای دسترسیدهنده در src/config/sessions/session-accessor.ts را ترجیح دهد؛ کمککنندههای قدیمی sessions.json ابزارهای مهاجرت و نگهداری آفلاین هستند. هنگامی که Gateway در دسترس است، حالتهای غیر openclaw sessions cleanup و openclaw agents delete تغییرات مخزن را به Gateway واگذار میکنند تا پاکسازی به همان صف نویسنده بپیوندد؛ --store <path> مسیر صریح ترمیم آفلاین برای یک مخزن قدیمی انتخابشده است و همیشه محلی باقی میماند (همانند --dry-run). پاکسازی maxEntries برای مخزنهایی با اندازه تولید بهصورت دستهای انجام میشود؛ بنابراین ممکن است مخزن پیش از آنکه پاکسازی بعدیِ حد بالای مصرف آن را بازنویسی و به زیر سقف برساند، مدتی کوتاه از سقف پیکربندیشده فراتر رود. خواندنها هنگام راهاندازی Gateway هرگز ورودیها را هرس یا محدود نمیکنند؛ فقط نوشتنها یا openclaw sessions cleanup --enforce این کار را انجام میدهند، و مورد دوم همچنین سقف را بلافاصله اعمال میکند و مصنوعات قدیمی بدون ارجاع رونوشت، نقطه وارسی و مسیر حرکت را حتی بدون پیکربندی بودجه دیسک هرس میکند.
OpenClaw دیگر هنگام نوشتنهای Gateway پشتیبانهای چرخشی خودکار sessions.json.bak.* ایجاد نمیکند. طرحواره فعلی کلید قدیمی session.maintenance.rotateBytes را رد میکند و openclaw doctor --fix آن را از پیکربندیهای قدیمیتر حذف میکند.
تغییرات رونوشت از صف نوشتن نشست برای مقصد رونوشت SQLite استفاده میکنند:
قفلهای نوشتن نشست از پیشفرضهای ثابت محیط تولید استفاده میکنند. متغیرهای محیطی
OPENCLAW_SESSION_WRITE_LOCK_* متناظر همچنان برای عیبیابی در سطح فرایند و
بازنویسیهای اضطراری در دسترس هستند.
بازگشت به نسخه قدیمیتر پس از گذار به SQLite
پیش از اجرای نسخه قدیمیتر و فایلمحور OpenClaw، مصنوعات قدیمی بایگانیشده رونوشت را بازگردانید:
openclaw doctor --session-sqlite restore --session-sqlite-all-agentsمهاجرت فایلهای قدیمی sessions.json را برای پشتیبانی و
بازگشت به نسخه قبلی نگه میدارد، اما فایلهای JSONL فعال رونوشت که به SQLite وارد شدهاند
به session-sqlite-import-archive/ تغییر نام مییابند. زماناجراهای قدیمی فایلمحور
مسیرهای sessionFile را در sessions.json دنبال میکنند؛ بنابراین باید این مصنوعات
پیش از راهاندازی بازگردانده شوند. بازیابی از مانیفستهای مهاجرت استفاده میکند، فقط مصنوعات
بایگانیشده ثبتشدهای را که مسیر اصلی آنها وجود ندارد جابهجا میکند و پایگاه داده SQLite را
برای بازیابی رو به جلو در جای خود نگه میدارد.
نشستهایی که پس از گذار به SQLite ایجاد شدهاند فقط در SQLite قرار دارند و در زماناجرای قدیمیتر فایلمحور ظاهر نمیشوند. اگر پس از بازگشت به نسخه قدیمی دوباره ارتقا میدهید، توالی بازرسی و اعتبارسنجی Doctor را دوباره اجرا کنید تا OpenClaw بتواند پیش از واردکردن، مصنوعات قدیمی بازیابیشده را اعتبارسنجی کند.
نشستهای Cron و گزارشهای اجرا
اجراهای cron ایزوله، ورودیها/رونوشتهای نشست خود را با دوره نگهداری اختصاصی ایجاد میکنند:
cron.sessionRetention(پیشفرض"24h") نشستهای قدیمی اجرای cron ایزوله را از مخزن هرس میکند؛falseآن را غیرفعال میکند.- تاریخچه اجرا جدیدترین 2000 ردیف پایانی را برای هر کار cron نگه میدارد. ردیفهای ازدسترفته بازه پاکسازی 24 ساعته خود را حفظ میکنند.
هنگامی که cron یک نشست اجرای ایزوله جدید را بهاجبار ایجاد میکند، پیش از نوشتن ردیف جدید ورودی نشست قبلی cron:<jobId> را پاکسازی میکند: ترجیحات امن (تنظیمات تفکر/سریع/پرمطلب/استدلال، برچسبها و نام نمایشی) و بازنویسیهای مدل/احراز هویت که کاربر صریحاً انتخاب کرده است منتقل میشوند، اما زمینه محیطی مکالمه (مسیریابی کانال/گروه، سیاست ارسال/صف، ارتقای سطح دسترسی، مبدأ و اتصال زماناجرای ACP) حذف میشود تا یک اجرای ایزوله تازه نتواند اختیار قدیمی تحویل یا زماناجرا را از اجرای قدیمیتر به ارث ببرد.
کلیدهای نشست (sessionKey)
یک sessionKey مشخص میکند در کدام محفظه مکالمه قرار دارید (مسیریابی + جداسازی). قواعد معیار: /concepts/session.
| الگو | مثال |
|---|---|
| گفتوگوی اصلی/مستقیم (بهازای هر عامل) | 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 فعلی اشاره میکند (هویت رونوشت SQLite که مکالمه را ادامه میدهد). منطق تصمیمگیری در initSessionState() در src/auto-reply/reply/session.ts قرار دارد.
- بازنشانی (
/new،/reset) یکsessionIdجدید برای آنsessionKeyایجاد میکند. - بدون بازنشانی خودکار حالت پیشفرض است.
sessionIdفعلی ادامه مییابد، درحالیکه Compaction زمینهٔ فعال مدل را محدود نگه میدارد. - بازنشانی روزانه (
session.reset.mode: "daily") با نخستین پیام پس از مرز ساعت محلی پیکربندیشده (session.reset.atHour، پیشفرض4) یکsessionIdجدید ایجاد میکند. - انقضای بیکاری (
session.reset.mode: "idle"همراه باsession.reset.idleMinutes، یاsession.idleMinutesقدیمی) هنگامی که پیامی پس از بازهٔ بیکاری برسد، یکsessionIdجدید ایجاد میکند. اگر هر دو حالت روزانه و بیکاری پیکربندی شده باشند، هرکدام زودتر منقضی شود اولویت دارد. - ازسرگیری پس از اتصال مجدد رابط کنترل، وقتی Gateway مقدار منطبق
sessionIdرا از یک کلاینت رابط کاربری اپراتور دریافت کند، نشست قابلمشاهدهٔ فعلی را برای یک ارسال پس از اتصال مجدد حفظ میکند. این سیگنال یکبارمصرف است؛ ارسالهای عادیِ منقضی همچنان یکsessionIdجدید ایجاد میکنند. - رویدادهای سیستمی (Heartbeat، بیدارباشهای Cron، اعلانهای exec، ثبتهای داخلی Gateway) ممکن است ردیف نشست را تغییر دهند، اما هرگز تازگی بازنشانی روزانه/بیکاری را تمدید نمیکنند. جابهجایی ناشی از بازنشانی، اعلانهای رویداد سیستمیِ در صف برای نشست قبلی را پیش از ساختهشدن پرامپت تازه دور میاندازد.
- سیاست انشعاب والد هنگام ایجاد انشعاب یک رشته یا زیرعامل، از شاخهٔ فعال OpenClaw استفاده میکند. اگر آن شاخه بیشازحد بزرگ باشد (بیش از سقف داخلی ثابتی که اکنون 100K توکن است)، OpenClaw بهجای شکست یا بهارثبردن تاریخچهای غیرقابلاستفاده، فرزند را با زمینهای ایزوله آغاز میکند. اندازهسنجی خودکار است و قابل پیکربندی نیست؛ پیکربندی قدیمی
session.parentForkMaxTokensتوسطopenclaw doctor --fixحذف میشود. - انشعابهای اپراتور:
sessions.create { parentSessionKey, fork: true }نشست جدیدی ایجاد میکند که رونوشت آن از وضعیت فعلی والد منشعب میشود (همان سازوکار انشعابِ ایجاد زیرعامل، شامل سقف اندازهٔ بالا). تا زمانی که والد اجرای فعالی دارد، انشعاب پذیرفته نمیشود؛ انتخاب مدل والد را به ارث میبرد مگر اینکه مدلی صریحاً ارسال شود، و فرزند را باforkedFromParentو شمارندههای توکن تازه علامتگذاری میکند.
شِمای مخزن نشست
مخزن زمان اجرا، مقادیر SessionEntry را در SQLite مختص هر عامل نگه میدارد. نوع مقدار، SessionEntry در src/config/sessions.ts است. فیلدهای کلیدی (فهرست جامع نیست):
sessionId: شناسهٔ رونوشت فعلی که برای آدرسدهی ردیفهای رونوشت SQLite استفاده میشودsessionStartedAt: مُهر زمانی آغازsessionIdفعلی؛ تازگی بازنشانی روزانه از این مقدار استفاده میکند. ردیفهای قدیمی ممکن است آن را از سرآیند نشست JSONL استخراج کنند.lastInteractionAt: مُهر زمانی آخرین تعامل واقعی کاربر/کانال؛ تازگی بازنشانی بیکاری از این مقدار استفاده میکند تا رویدادهای Heartbeat، Cron و exec نشستها را زنده نگه ندارند. ردیفهای قدیمیِ فاقد این فیلد به زمان آغاز بازیابیشدهٔ نشست برمیگردند.updatedAt: مُهر زمانی آخرین تغییر ردیف مخزن که برای فهرستکردن/هرسکردن/ثبتهای داخلی استفاده میشود و مرجع تازگی روزانه/بیکاری نیست.archivedAt: مُهر زمانی اختیاری بایگانی. نشستهای بایگانیشده همراه با رونوشت دستنخوردهٔ خود در مخزن باقی میمانند و از فهرستهای فعال عادی کنار گذاشته میشوند.pinnedAt: مُهر زمانی اختیاری سنجاقکردن. نشستهای فعالِ سنجاقشده پیش از نشستهای سنجاقنشده مرتب میشوند؛ بایگانیکردن نشست، سنجاق آن را پاک میکند.- همکنشپذیری رشتهٔ Codex: هر دو فیلد از ساختار مدیریت رشتهٔ Codex پیروی میکنند؛ مقادیر بولی
archived/pinnedروی سیم همیشه از مُهر زمانی مشتق میشوند و در سمت سرور مُهر میخورند، مطابق با معناشناسیthreads.archived_atدر Codex و سریالسازی camelCase. مُهرهای زمانی OpenClaw برحسب میلیثانیه از مبدأ هستند، درحالیکه Codex از ثانیه از مبدأ استفاده میکند؛ بنابراین پلها تبدیل را در مرز Plugin مربوط بهcodexانجام میدهند. Codex هنوز API سنجاقکردن ندارد (فقطthread/archive/thread/unarchive)؛ وضعیت سنجاقشده تا زمان ایجاد چنین APIای در سمت OpenClaw باقی میماند و پس از آن، ساختار منطبق اجازه میدهد نشستهای مقید وضعیت سنجاق را بهصورت مکانیکی رفتوبرگشت دهند. - نظارت Codex فقط رشتههای بومیِ بایگانینشده را فهرست میکند. یک رشتهٔ
idleمحلی Gateway یا رشتهٔnotLoadedبا فعالیت نامشخص، تنها پس از آن میتواند از طریقthread/archiveبومی بایگانی شود که اپراتور صریحاً تأیید کند هیچ فرایند Codex دیگری مالک آن نیست؛ Plugin ابتدا وضعیت محلی فرایند را دوباره و بهروز میخواند و سپس رشته از کاتالوگ ناپدید میشود. این خواندن نمیتواند ثابت کند فرایند App Server دیگری از رشته استفاده نمیکند. OpenClaw از بایگانیکردن ردیفهای فعال و خطادار خودداری میکند و بایگانی گره جفتشده تا زمانی که پل Node بتواند مالک کل چرخهٔ حیات جریانی رشته باشد، دردسترس نیست. خارجکردن رشته از بایگانی در یک کلاینت بومی Codex، آن را دوباره واجد شرایط نمایش میکند. lastReadAt/markedUnreadAt: مُهرهای زمانی وضعیت خواندن که توسطsessions.patch { unread }در سمت سرور ثبت میشوند؛unread: falseیک خواندن را ثبت میکند (lastReadAtرا تنظیم وmarkedUnreadAtرا پاک میکند)؛unread: trueنشست را تا خواندن بعدی خواندهنشده علامت میزند. ردیفهای نشست یک مقدار بولی مشتقشدهٔunreadارائه میکنند: یا صریحاً خواندهنشده علامت خوردهاند، یا پیش از آخرین فعالیت خوانده شدهاند. نشستهایی که هرگز خواندهشده علامت نخوردهاند،unread: falseباقی میمانند تا نصبهای موجود پس از ارتقا ناگهان برجسته نشوند.lastActivityAt: مُهر زمانی آخرین اجرای تکمیلشدهٔ عامل که فعالیتی شایستهٔ خواندهنشدهشدن محسوب میشود (اجراهای کاربر، کانال و Cron). نوبتهای Heartbeat و رویداد داخلی، همچنین وصلههای فراداده، آن را بهروزرسانی نمیکنند؛updatedAtسیگنال فعالیت نیست.sessionFile: نشانگر قدیمی که برای سازگاری مهاجرت/بایگانی نگه داشته شده است؛ زمان اجرای فعال از هویت SQLite استفاده میکندchatType:direct | group | roomprovider،subject،room،space،displayName: فرادادهٔ برچسبگذاری گروه/کانال- کلیدهای تغییر وضعیت:
thinkingLevel،verboseLevel،reasoningLevel،elevatedLevel،sendPolicy(بازنویسی مختص هر نشست) - انتخاب مدل:
providerOverride،modelOverride،authProfileOverride - شمارندههای توکن (با بیشترین تلاش/وابسته به ارائهدهنده):
inputTokens،outputTokens،totalTokens،contextTokens compactionCount: تعداد دفعات تکمیل Compaction خودکار برای این کلید نشستmemoryFlushAt/memoryFlushCompactionCount: مُهر زمانی و تعداد Compaction آخرین تخلیهٔ حافظهٔ پیش از Compaction
Gateway مرجع نهایی است: ممکن است هنگام اجرای نشستها، ورودیها را بازنویسی یا بازآبرسانی کند. برای نصبهای قدیمیِ مبتنی بر فایل، بهجای
ویرایش sessions.json و انتظار از زمان اجرا برای ادامهٔ خواندن آن فایل، با
openclaw doctor --session-sqlite import --session-sqlite-all-agents مهاجرت کنید.
ساختار رویداد رونوشت
رونوشتها توسط دسترسیدهندهٔ نشست OpenClaw مدیریت میشوند و از طریق یاریگرهای مبتنی بر هویت در اختیار کد زمان اجرا قرار میگیرند. جریان رویداد فقطافزودنی است:
- ورودی نخست: سرآیند نشست؛
type: "session"،id،cwd،timestampوparentSessionاختیاری. - سپس: ورودیهایی با
id+parentId(ساختار درختی).
انواع مهم ورودی:
message: پیامهای کاربر/دستیار/toolResultcustom_message: پیام تزریقشده توسط افزونه که وارد زمینهٔ مدل میشود (وقتیdisplay: trueباشد در TUI رندر میشود و وقتیdisplay: falseباشد کاملاً پنهان است)custom: وضعیت افزونه که وارد زمینهٔ مدل نمیشود (برای پایدارسازی وضعیت افزونه بین بارگذاریهای مجدد)compaction: خلاصهٔ پایدارشدهٔ Compaction باfirstKeptEntryIdوtokensBeforebranch_summary: خلاصهٔ پایدارشده هنگام پیمایش یک شاخهٔ درخت
OpenClaw عمداً رونوشتها را «اصلاح» نمیکند؛ Gateway برای خواندن/نوشتن آنها از SessionManager استفاده میکند.
پنجرههای زمینه در برابر توکنهای ردیابیشده
دو مفهوم متفاوت:
- پنجرهٔ زمینهٔ مدل: سقف قطعی برای هر مدل (توکنهای قابلمشاهده برای مدل). از کاتالوگ مدل میآید و میتوان آن را از طریق پیکربندی بازنویسی کرد.
- شمارندههای مخزن نشست: آمار گردشی که در ردیف نشست نوشته میشوند (برای
/statusو داشبوردها استفاده میشوند).contextTokensیک مقدار تخمینی/گزارشی زمان اجرا است؛ آن را تضمینی قطعی در نظر نگیرید.
اطلاعات بیشتر دربارهٔ محدودیتها: /reference/token-use.
Compaction: چیست
Compaction مکالمهٔ قدیمیتر را در یک ورودی پایدارشدهٔ compaction در رونوشت خلاصه میکند و پیامهای اخیر را دستنخورده نگه میدارد. پس از Compaction، نوبتهای آینده خلاصهٔ Compaction را همراه با پیامهای پس از firstKeptEntryId میبینند. Compaction برخلاف هرس نشست پایدار است؛ به /concepts/session-pruning مراجعه کنید.
Compaction تعبیهشدهٔ OpenClaw بهطور پیشفرض سطح تفکر نشست را به ارث میبرد. برای استفاده از سطحی جداگانه در فراخوانیهای خلاصهسازی، agents.defaults.compaction.thinkingLevel را تنظیم کنید؛ زمان اجرا آن را به محدودهٔ هر مدل مشخص Compaction یا مدل جایگزین محدود میکند. Compaction بومی app-server در Codex مالک درخواست compact خود است و نمیتواند بازنویسی سطح تفکر مختص Compaction را بپذیرد؛ بنابراین OpenClaw هشدار میدهد و آن تنظیم را به Codex واگذار میکند.
تزریق مجدد بخش AGENTS.md پس از Compaction از طریق agents.defaults.compaction.postCompactionSections همچنان اختیاری است. Pluginها میتوانند از طریق before_prompt_build زمینهٔ دیگری به پرامپت اضافه کنند.
مرزهای قطعه و جفتسازی ابزار
هنگام تقسیم یک رونوشت طولانی به قطعههای Compaction، OpenClaw فراخوانیهای ابزار دستیار را با ورودیهای منطبق toolResult جفت نگه میدارد:
- اگر تقسیم بر پایهٔ سهم توکن میان یک فراخوانی ابزار و نتیجهٔ آن قرار بگیرد، OpenClaw بهجای جداکردن جفت، مرز را به پیام فراخوانی ابزار دستیار منتقل میکند.
- اگر بلوک پایانی نتیجهٔ ابزار باعث عبور قطعه از هدف شود، OpenClaw آن بلوک ابزارِ در انتظار را حفظ میکند و دنبالهٔ خلاصهنشده را دستنخورده نگه میدارد.
- بلوکهای فراخوانی ابزار لغوشده/خطادار، تقسیم در انتظار را باز نگه نمیدارند.
زمان وقوع Compaction خودکار
دو محرک در عامل تعبیهشدهٔ OpenClaw:
- بازیابی از سرریز: مدل خطای سرریز زمینه برمیگرداند (
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و گونههای دیگری با ساختار مختص ارائهدهنده)؛ Compaction را انجام میدهد و سپس دوباره تلاش میکند. وقتی ارائهدهنده تعداد توکنهای تلاششده را گزارش کند، OpenClaw آن تعداد مشاهدهشده را به Compaction بازیابی از سرریز میفرستد؛ اگر ارائهدهنده سرریز را تأیید کند اما هیچ تعداد قابلتجزیهای ارائه ندهد، OpenClaw یک تعداد مصنوعیِ حداقلی و اندکی بیش از بودجه را به موتورهای Compaction و ابزارهای تشخیصی میفرستد. اگر بازیابی از سرریز همچنان شکست بخورد، OpenClaw راهنمایی صریح نمایش میدهد و بهجای چرخش بیسروصدا به شناسهٔ نشست تازه، نگاشت نشست فعلی را حفظ میکند؛ پیام را دوباره ارسال کنید،/compactرا اجرا کنید یا/newرا اجرا کنید. - نگهداشت آستانه: پس از یک نوبت موفق، هنگامی که زمینهٔ فعلی از پنجرهٔ مدل منهای فضای ذخیرهٔ داخلی OpenClaw برای پرامپتها و خروجی بعدی مدل فراتر رود.
دو محافظ اضافی خارج از این دو محرک اجرا میشوند:
- Compaction محلی پیش از اجرا: مقدار
agents.defaults.compaction.maxActiveTranscriptBytes(بر حسب بایت یا رشتهای مانند"20mb") را تنظیم کنید تا وقتی رونوشت فعال به آن اندازه رسید، پیش از باز کردن اجرای بعدی Compaction محلی فعال شود. این یک محافظ اندازه برای هزینه بازگشایی محلی است، نه بایگانی خام؛ Compaction معنایی عادی همچنان اجرا میشود و بهtruncateAfterCompactionنیاز دارد تا خلاصه فشردهشده به رونوشت جانشین جدیدی تبدیل شود. - پیشبررسی میاننوبتی: مقدار
agents.defaults.compaction.midTurnPrecheck.enabled: true(پیشفرضfalse) را تنظیم کنید تا محافظی برای حلقه ابزار افزوده شود. پس از افزودهشدن نتیجه ابزار و پیش از فراخوانی بعدی مدل، OpenClaw فشار پرامپت را با همان منطق بودجه پیش از اجرا که در آغاز نوبت استفاده میشود تخمین میزند. اگر زمینه دیگر جا نشود، محافظ Compaction را بهصورت درونخطی انجام نمیدهد؛ بلکه سیگنال ساختاریافته پیشبررسی میاننوبتی را صادر میکند، ارسال پرامپت جاری را متوقف میکند و اجازه میدهد حلقه بیرونی اجرا از مسیر بازیابی موجود استفاده کند (وقتی کافی باشد نتایج بیشازحد بزرگ ابزار را کوتاه کند، یا حالت Compaction پیکربندیشده را فعال کرده و دوباره تلاش کند). با هر دو حالت Compaction یعنیdefaultوsafeguard، از جمله Compaction محافظتی مبتنی بر ارائهدهنده، کار میکند. مستقل ازmaxActiveTranscriptBytesاست: محافظ اندازه بایت پیش از باز شدن نوبت اجرا میشود، اما پیشبررسی میاننوبتی بعدتر و پس از افزودهشدن نتایج جدید ابزار اجرا میشود.
تنظیمات Compaction
{ agents: { defaults: { compaction: { enabled: true, keepRecentTokens: 20000, }, }, },}OpenClaw یک ذخیره داخلی را برای اجراهای تعبیهشده اعمال میکند و آن را بر اساس پنجره زمینه مدل فعال محدود میکند تا نتواند کل بودجه پرامپت را مصرف کند. این کار مانع از آن میشود که مدلهای محلی با زمینه کوچک از نخستین توکن وارد Compaction شوند، در حالی که فضای کافی برای امور نگهداری چندنوبتی مانند تخلیه حافظه باقی میماند.
/compact دستی، مقدار صریح agents.defaults.compaction.keepRecentTokens را رعایت میکند و نقطه برش انتهای اخیر زمان اجرا را نگه میدارد. بدون بودجه نگهداری صریح، Compaction دستی یک نقطه بازرسی قطعی است و زمینه بازسازیشده از خلاصه جدید آغاز میشود.
وقتی truncateAfterCompaction فعال باشد، OpenClaw پس از Compaction رونوشت فعال را به یک جانشین فشردهشده منتقل میکند. کنشهای نقطه بازرسی شاخه/بازیابی از آن جانشین فشردهشده استفاده میکنند؛ فایلهای قدیمی نقطه بازرسی پیش از Compaction تا زمانی که به آنها ارجاع داده شود قابل خواندن باقی میمانند.
ارائهدهندگان قابلاتصال Compaction
Pluginها یک ارائهدهنده Compaction را از طریق registerCompactionProvider() در API Plugin ثبت میکنند. وقتی agents.defaults.compaction.provider روی شناسه یک ارائهدهنده ثبتشده تنظیم شود، افزونه محافظتی بهجای پایپلاین داخلی summarizeInStages، خلاصهسازی را به آن ارائهدهنده واگذار میکند.
provider: شناسه یک Plugin ارائهدهنده Compaction ثبتشده. برای خلاصهسازی پیشفرض LLM تنظیمنشده باقی بگذارید. تنظیم یکprovider، مقدارmode: "safeguard"را اجباری میکند.- ارائهدهندگان همان دستورالعملهای Compaction و سیاست حفظ شناسه مسیر داخلی را دریافت میکنند و محافظ همچنان زمینه پسوند نوبتهای اخیر و نوبت تقسیمشده را پس از خروجی ارائهدهنده حفظ میکند.
- خلاصهسازی محافظتی داخلی، بهجای حفظ کلمهبهکلمه کل خلاصه قبلی، خلاصههای پیشین را همراه پیامهای جدید دوباره تقطیر میکند.
- حالت محافظتی بهطور پیشفرض ممیزی کیفیت خلاصه را فعال میکند؛ برای رد کردن رفتار تلاش مجدد در صورت خروجی بدشکل،
qualityGuard.enabled: falseرا تنظیم کنید. - اگر ارائهدهنده شکست بخورد یا نتیجهای خالی برگرداند، OpenClaw بهطور خودکار به خلاصهسازی داخلی LLM بازمیگردد. سیگنالهای لغو/مهلت زمانی که فراخواننده صراحتاً فعال کرده است، دوباره پرتاب میشوند و نادیده گرفته نمیشوند؛ بنابراین لغو همیشه رعایت میشود.
منبع: src/plugins/compaction-provider.ts، src/agents/agent-hooks/compaction-safeguard.ts.
سطوح قابلمشاهده برای کاربر
/statusدر هر نشست گفتگوopenclaw status(CLI)openclaw sessions/openclaw sessions --json- گزارشهای Gateway (
pnpm gateway:watchیاopenclaw logs --follow): embedded run auto-compaction start+complete - حالت پرجزئیات:
🧹 Auto-compaction completeبههمراه شمار Compaction
امور نگهداری بیصدا (NO_REPLY)
OpenClaw از نوبتهای «بیصدا» برای وظایف پسزمینهای پشتیبانی میکند که در آنها کاربر نباید خروجی میانی را ببیند.
- دستیار خروجی خود را با توکن دقیق سکوت
NO_REPLY/no_replyآغاز میکند که بهمعنای «پاسخی به کاربر تحویل نده» است. OpenClaw این مورد را در لایه تحویل حذف/سرکوب میکند. - سرکوب توکن دقیق سکوت به بزرگی و کوچکی حروف حساس نیست: اگر کل محموله فقط توکن سکوت باشد، هر دو
NO_REPLYوno_replyمعتبرند. - از
2026.1.10، اگر یک قطعه جزئی باNO_REPLYآغاز شود، OpenClaw پخش جریانی پیشنویس/در حال تایپ را نیز سرکوب میکند تا عملیات بیصدا در میانه نوبت خروجی جزئی را نشت ندهند. - این قابلیت فقط برای نوبتهای واقعاً پسزمینه/بدون تحویل است؛ میانبری برای درخواستهای عادی و قابلاقدام کاربر نیست.
تخلیه حافظه پیش از Compaction
پیش از وقوع Compaction خودکار، OpenClaw میتواند یک نوبت عاملیتمحور بیصدا اجرا کند که وضعیت ماندگار را روی دیسک مینویسد (برای نمونه memory/YYYY-MM-DD.md در فضای کاری عامل) تا Compaction نتواند زمینه حیاتی را پاک کند. این قابلیت میزان استفاده از زمینه نشست را پایش میکند و هنگامی که از آستانهای نرم پایینتر از آستانه Compaction عبور کند، با استفاده از توکن دقیق سکوت NO_REPLY / no_reply دستور بیصدای «اکنون حافظه را بنویس» را ارسال میکند تا کاربر چیزی نبیند.
پیکربندی (agents.defaults.compaction.memoryFlush)، مرجع کامل در /gateway/config-agents:
| کلید | پیشفرض | توضیحات |
|---|---|---|
enabled |
true |
|
model |
تنظیمنشده | جایگزینی دقیق ارائهدهنده/مدل فقط برای نوبت تخلیه، برای نمونه ollama/qwen3:8b |
softThresholdTokens |
4000 |
فاصله زیر آستانه Compaction که تخلیه را فعال میکند |
forceFlushTranscriptBytes |
تنظیمنشده (غیرفعال) | هنگامی که فایل رونوشت به این اندازه بایتی (یا رشتهای مانند "2mb") رسید، حتی اگر شمارندههای توکن قدیمی باشند، تخلیه را اجباری میکند؛ 0 غیرفعال میکند |
نکتهها:
- پرامپت داخلی و پرامپت سیستم شامل راهنمای
NO_REPLYبرای سرکوب تحویل هستند. - وقتی
modelتنظیم شده باشد، نوبت تخلیه بدون بهارثبردن زنجیره بازگشت نشست فعال از آن مدل استفاده میکند؛ بنابراین امور نگهداری صرفاً محلی در صورت شکست، بیسروصدا به مدل گفتگوی پولی بازنمیگردد. - تخلیه در هر چرخه Compaction یکبار اجرا میشود (در ردیف نشست ردیابی میشود).
- تخلیه فقط برای نشستهای تعبیهشده OpenClaw اجرا میشود؛ بکاندهای CLI و نوبتهای Heartbeat از آن صرفنظر میکنند.
- وقتی فضای کاری نشست فقطخواندنی باشد (
workspaceAccess: "ro"یا"none") از تخلیه صرفنظر میشود. - برای چیدمان فایلهای فضای کاری و الگوهای نوشتن، حافظه را ببینید.
OpenClaw یک هوک session_before_compact را در API افزونه ارائه میکند، اما منطق تخلیه بالا در سمت Gateway (src/auto-reply/reply/memory-flush.ts، src/auto-reply/reply/agent-runner-memory.ts) قرار دارد، نه در آن هوک.
فهرست بررسی عیبیابی
- کلید نشست اشتباه است؟ از /concepts/session آغاز کنید و
sessionKeyرا در/statusتأیید کنید. - ناهماهنگی مخزن و رونوشت؟ میزبان Gateway و مسیر مخزن را از
openclaw statusتأیید کنید. - Compaction مکرر؟ پنجره زمینه مدل (کوچکبودن بیشازحد باعث Compaction مکرر میشود) و تورم نتایج ابزار را بررسی کنید (هرس نشست را تنظیم کنید).
- به نظر میرسد هر پرامپت در یک مدل محلی کوچک سرریز میشود؟ تأیید کنید که ارائهدهنده پنجره زمینه صحیح مدل را گزارش میکند. OpenClaw تنها زمانی میتواند ذخیره مؤثر را محدود کند که آن پنجره مشخص باشد.
- نوبتهای بیصدا نشت میکنند؟ تأیید کنید پاسخ با توکن دقیق سکوت
NO_REPLY(بدون حساسیت به بزرگی و کوچکی حروف) آغاز میشود و از نسخهای استفاده میکنید که اصلاح سرکوب پخش جریانی (2026.1.10+) را در بر دارد.