Technical reference

بررسی عمیق مدیریت نشست‌ها

یک فرایند Gateway به‌تنهایی مالک سرتاسری وضعیت نشست است. رابط‌های کاربری (برنامه macOS، رابط وب Control UI و TUI) فهرست نشست‌ها و شمارنده‌های توکن را از Gateway دریافت می‌کنند. در حالت راه‌دور، فایل‌های نشست روی میزبان راه‌دور قرار دارند؛ بنابراین بررسی فایل‌های Mac محلی، آنچه Gateway استفاده می‌کند را نشان نمی‌دهد.

ابتدا مستندات کلی را ببینید: مدیریت نشست، Compaction، نمای کلی حافظه، جست‌وجوی حافظه، هرس نشست، بهداشت رونوشت، و مرجع کامل پیکربندی در پیکربندی عامل.

دو لایه ماندگاری

  1. ردیف‌های نشست (SQLite به‌ازای هر عامل) - نگاشت کلید/مقدار sessionKey -> SessionEntry. وضعیت زمان‌اجرای تغییرپذیر که مالک آن Gateway است. فراداده‌هایی مانند شناسه نشست فعلی، آخرین فعالیت، گزینه‌های روشن/خاموش و شمارنده‌های توکن را ردیابی می‌کند.
  2. رویدادهای رونوشت (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" مقدار فعلی مازاد فیزیکی را بدون گرفتن نقطه وارسی، نوشتن بایگانی یا حذف ردیف‌ها گزارش می‌کند.

نگه‌داری را در صورت نیاز اجرا کنید:

bash
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، مصنوعات قدیمی بایگانی‌شده رونوشت را بازگردانید:

bash
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 | room
  • provider، 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: پیام‌های کاربر/دستیار/toolResult
  • custom_message: پیام تزریق‌شده توسط افزونه که وارد زمینهٔ مدل می‌شود (وقتی display: true باشد در TUI رندر می‌شود و وقتی display: false باشد کاملاً پنهان است)
  • custom: وضعیت افزونه که وارد زمینهٔ مدل نمی‌شود (برای پایدارسازی وضعیت افزونه بین بارگذاری‌های مجدد)
  • compaction: خلاصهٔ پایدارشدهٔ Compaction با firstKeptEntryId و tokensBefore
  • branch_summary: خلاصهٔ پایدارشده هنگام پیمایش یک شاخهٔ درخت

OpenClaw عمداً رونوشت‌ها را «اصلاح» نمی‌کند؛ Gateway برای خواندن/نوشتن آن‌ها از SessionManager استفاده می‌کند.

پنجره‌های زمینه در برابر توکن‌های ردیابی‌شده

دو مفهوم متفاوت:

  1. پنجرهٔ زمینهٔ مدل: سقف قطعی برای هر مدل (توکن‌های قابل‌مشاهده برای مدل). از کاتالوگ مدل می‌آید و می‌توان آن را از طریق پیکربندی بازنویسی کرد.
  2. شمارنده‌های مخزن نشست: آمار گردشی که در ردیف نشست نوشته می‌شوند (برای /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:

  1. بازیابی از سرریز: مدل خطای سرریز زمینه برمی‌گرداند (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 را اجرا کنید.
  2. نگهداشت آستانه: پس از یک نوبت موفق، هنگامی که زمینهٔ فعلی از پنجرهٔ مدل منهای فضای ذخیرهٔ داخلی 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

json5
{  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+) را در بر دارد.

مرتبط

Was this useful?
On this page

On this page