Перейти до основного вмісту

Керування сесіями та ущільнення (глибокий розбір)

У цьому документі пояснюється, як OpenClaw керує сесіями наскрізно:
  • Маршрутизація сесій (як вхідні повідомлення зіставляються з sessionKey)
  • Сховище сесій (sessions.json) і що воно відстежує
  • Збереження транскрипту (*.jsonl) та його структура
  • Гігієна транскрипту (виправлення для конкретних провайдерів перед запусками)
  • Обмеження контексту (вікно контексту проти відстежуваних токенів)
  • Ущільнення (ручне + автоущільнення) і куди підключати роботу перед ущільненням
  • Тихі службові дії (наприклад, запис пам’яті, який не повинен створювати видимий для користувача вивід)
Якщо спочатку потрібен огляд вищого рівня, почніть із:

Джерело істини: Gateway

OpenClaw спроєктовано навколо єдиного процесу Gateway, який володіє станом сесій.
  • Інтерфейси (macOS app, веб-інтерфейс Control UI, TUI) мають запитувати в Gateway списки сесій і кількість токенів.
  • У віддаленому режимі файли сесій розміщені на віддаленому хості; “перевірка локальних файлів на Mac” не покаже те, що використовує Gateway.

Два шари збереження

OpenClaw зберігає сесії у двох шарах:
  1. Сховище сесій (sessions.json)
    • Мапа ключ/значення: sessionKey -> SessionEntry
    • Маленьке, змінюване, безпечно редагувати (або видаляти записи)
    • Відстежує метадані сесії (поточний id сесії, останню активність, перемикачі, лічильники токенів тощо)
  2. Транскрипт (<sessionId>.jsonl)
    • Транскрипт лише з додаванням записів із деревоподібною структурою (записи мають id + parentId)
    • Зберігає фактичну розмову + виклики інструментів + зведення ущільнення
    • Використовується для відновлення контексту моделі для майбутніх ходів

Розташування на диску

Для кожного агента, на хості Gateway:
  • Сховище: ~/.openclaw/agents/<agentId>/sessions/sessions.json
  • Транскрипти: ~/.openclaw/agents/<agentId>/sessions/<sessionId>.jsonl
    • Сесії тем Telegram: .../<sessionId>-topic-<threadId>.jsonl
OpenClaw визначає ці шляхи через src/config/sessions.ts.

Обслуговування сховища та контроль диска

Збереження сесій має автоматичні механізми обслуговування (session.maintenance) для sessions.json і артефактів транскриптів:
  • mode: warn (типово) або enforce
  • pruneAfter: поріг віку застарілих записів для очищення (типово 30d)
  • maxEntries: обмеження кількості записів у sessions.json (типово 500)
  • rotateBytes: ротація sessions.json, коли файл стає завеликим (типово 10mb)
  • resetArchiveRetention: термін зберігання архівів транскриптів *.reset.<timestamp> (типово: такий самий, як pruneAfter; false вимикає очищення)
  • maxDiskBytes: необов’язковий бюджет каталогу sessions на диску
  • highWaterBytes: необов’язкова ціль після очищення (типово 80% від maxDiskBytes)
Порядок примусового очищення для бюджету диска (mode: "enforce"):
  1. Спочатку видалити найстаріші архівовані або осиротілі артефакти транскриптів.
  2. Якщо все ще вище за ціль, витіснити найстаріші записи сесій і їхні файли транскриптів.
  3. Продовжувати, доки використання не стане на рівні або нижче highWaterBytes.
У режимі mode: "warn" OpenClaw повідомляє про можливі витіснення, але не змінює сховище/файли. Запустити обслуговування на вимогу:
openclaw sessions cleanup --dry-run
openclaw sessions cleanup --enforce

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> (якщо не перевизначено)
Канонічні правила задокументовано в /concepts/session.

Ідентифікатори сесій (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: поточний id транскрипту (ім’я файлу виводиться з нього, якщо не задано sessionFile)
  • updatedAt: мітка часу останньої активності
  • sessionFile: необов’язкове явне перевизначення шляху транскрипту
  • chatType: direct | group | room (допомагає інтерфейсам і політиці надсилання)
  • provider, subject, room, space, displayName: метадані для позначення груп/каналів
  • Перемикачі:
    • thinkingLevel, verboseLevel, reasoningLevel, elevatedLevel
    • sendPolicy (перевизначення для конкретної сесії)
  • Вибір моделі:
    • providerOverride, modelOverride, authProfileOverride
  • Лічильники токенів (best-effort / залежать від провайдера):
    • inputTokens, outputTokens, totalTokens, contextTokens
  • compactionCount: скільки разів автоущільнення завершувалося для цього ключа сесії
  • memoryFlushAt: мітка часу останнього скидання пам’яті перед ущільненням
  • memoryFlushCompactionCount: лічильник ущільнень, коли востаннє виконувався flush
Сховище безпечно редагувати, але Gateway є джерелом істини: під час виконання сесій він може переписувати або повторно гідратувати записи.

Структура транскрипту (*.jsonl)

Транскриптами керує SessionManager з @mariozechner/pi-coding-agent. Файл має формат JSONL:
  • Перший рядок: заголовок сесії (type: "session", містить id, cwd, timestamp, необов’язковий parentSession)
  • Далі: записи сесії з id + parentId (дерево)
Помітні типи записів:
  • message: повідомлення user/assistant/toolResult
  • custom_message: повідомлення, інжектовані розширенням, які потрапляють у контекст моделі (можуть бути приховані від UI)
  • custom: стан розширення, який не потрапляє у контекст моделі
  • compaction: збережене зведення ущільнення з firstKeptEntryId і tokensBefore
  • branch_summary: збережене зведення під час навігації гілкою дерева
OpenClaw навмисно не “виправляє” транскрипти; Gateway використовує SessionManager для їх читання/запису.

Вікна контексту проти відстежуваних токенів

Важливі два різні поняття:
  1. Вікно контексту моделі: жорстке обмеження для кожної моделі (токени, видимі моделі)
  2. Лічильники сховища сесій: ковзна статистика, що записується в sessions.json (використовується для /status і панелей)
Якщо ви налаштовуєте обмеження:
  • Вікно контексту береться з каталогу моделей (і може бути перевизначене через конфігурацію).
  • contextTokens у сховищі — це оцінка/значення звітності під час виконання; не сприймайте його як сувору гарантію.
Докладніше див. у /token-use.

Ущільнення: що це таке

Ущільнення підсумовує старішу частину розмови в збережений запис compaction у транскрипті та залишає недоторканими недавні повідомлення. Після ущільнення майбутні ходи бачать:
  • Зведення ущільнення
  • Повідомлення після firstKeptEntryId
Ущільнення є постійним (на відміну від очищення сесії). Див. /concepts/session-pruning.

Межі чанків ущільнення та поєднання інструментів

Коли OpenClaw розбиває довгий транскрипт на чанки для ущільнення, він зберігає виклики інструментів асистента поєднаними з відповідними записами toolResult.
  • Якщо поділ за часткою токенів припадає між викликом інструмента та його результатом, OpenClaw зміщує межу до повідомлення асистента з викликом інструмента, а не розділяє пару.
  • Якщо кінцевий блок результатів інструмента інакше перевищив би цільовий розмір чанка, OpenClaw зберігає цей очікувальний блок інструмента і залишає неузагальнений хвіст недоторканим.
  • Перервані/помилкові блоки викликів інструментів не утримують відкритим очікувальний поділ.

Коли відбувається автоущільнення (середовище Pi)

У вбудованому агенті Pi автоущільнення спрацьовує у двох випадках:
  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 та подібні варіанти, характерні для конкретних провайдерів) → ущільнити → повторити спробу.
  2. Порогове обслуговування: після успішного ходу, коли:
contextTokens > contextWindow - reserveTokens Де:
  • contextWindow — це вікно контексту моделі
  • reserveTokens — це запас токенів, зарезервований для промптів + наступного виводу моделі
Це семантика середовища Pi (OpenClaw споживає події, але коли ущільнювати, вирішує Pi).

Налаштування ущільнення (reserveTokens, keepRecentTokens)

Налаштування ущільнення Pi зберігаються в налаштуваннях Pi:
{
  compaction: {
    enabled: true,
    reserveTokens: 16384,
    keepRecentTokens: 20000,
  },
}
OpenClaw також застосовує мінімальний захисний поріг для вбудованих запусків:
  • Якщо 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
  • Режим verbose: 🧹 Auto-compaction complete + кількість ущільнень

Тихі службові дії (NO_REPLY)

OpenClaw підтримує “тихі” ходи для фонових завдань, де користувач не повинен бачити проміжний вивід. Умова:
  • Асистент починає свій вивід з точного тихого токена NO_REPLY / no_reply, щоб позначити “не доставляти відповідь користувачу”.
  • OpenClaw прибирає/приглушує це на рівні доставки.
  • Приглушення точного тихого токена нечутливе до регістру, тож NO_REPLY і no_reply обидва зараховуються, коли весь payload — це лише тихий токен.
  • Це лише для справді фонових ходів/ходів без доставки; це не скорочений шлях для звичайних практичних запитів користувача.
Починаючи з 2026.1.10, OpenClaw також приглушує чернетковий/набірний стримінг, коли частковий чанк починається з NO_REPLY, щоб тихі операції не видавали частковий вивід посеред ходу.

”Скидання пам’яті” перед ущільненням (реалізовано)

Мета: перед тим як відбудеться автоущільнення, виконати тихий агентний хід, який записує стійкий стан на диск (наприклад, memory/YYYY-MM-DD.md у робочому просторі агента), щоб ущільнення не могло стерти критичний контекст. OpenClaw використовує підхід flush до порога:
  1. Відстежувати використання контексту сесії.
  2. Коли воно перетинає “м’який поріг” (нижчий за поріг ущільнення Pi), виконати тиху директиву “запиши пам’ять зараз” для агента.
  3. Використовувати точний тихий токен NO_REPLY / no_reply, щоб користувач нічого не бачив.
Конфігурація (agents.defaults.compaction.memoryFlush):
  • enabled (типово: true)
  • softThresholdTokens (типово: 4000)
  • prompt (повідомлення user для ходу flush)
  • systemPrompt (додатковий системний промпт, який додається для ходу flush)
Примітки:
  • Типові значення prompt/system prompt містять підказку NO_REPLY для приглушення доставки.
  • Flush виконується один раз за цикл ущільнення (відстежується в sessions.json).
  • Flush виконується лише для вбудованих сесій Pi.
  • Flush пропускається, коли робочий простір сесії доступний лише для читання (workspaceAccess: "ro" або "none").
  • Див. Memory щодо структури файлів робочого простору та шаблонів запису.
Pi також надає хук session_before_compact в API розширень, але логіка flush в OpenClaw сьогодні живе на боці Gateway.

Контрольний список усунення несправностей

  • Неправильний ключ сесії? Почніть із /concepts/session і перевірте sessionKey у /status.
  • Невідповідність між сховищем і транскриптом? Перевірте хост Gateway і шлях до сховища з openclaw status.
  • Спам ущільненням? Перевірте:
    • вікно контексту моделі (замале)
    • налаштування ущільнення (reserveTokens завелике для вікна моделі може спричиняти раніше ущільнення)
    • роздуття tool-result: увімкніть/налаштуйте очищення сесії
  • Тихі ходи протікають? Переконайтеся, що відповідь починається з NO_REPLY (нечутливий до регістру точний токен) і що у вас збірка, яка містить виправлення приглушення стримінгу.