Управление сеансами и уплотнение (подробный разбор)
Этот документ объясняет, как OpenClaw управляет сеансами от начала до конца:- Маршрутизация сеансов (как входящие сообщения сопоставляются с
sessionKey) - Хранилище сеансов (
sessions.json) и что в нём отслеживается - Сохранение транскриптов (
*.jsonl) и их структура - Гигиена транскриптов (провайдер-специфичные исправления перед запусками)
- Ограничения контекста (окно контекста vs отслеживаемые токены)
- Уплотнение (ручное + автоуплотнение) и точки подключения предварительных работ
- Тихая служебная обработка (например, записи памяти, которые не должны давать вывод, видимый пользователю)
Источник истины: Gateway (шлюз)
OpenClaw спроектирован вокруг одного процесса Gateway, который владеет состоянием сеансов.- UI (приложение для macOS, веб Control UI, 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.
Ключи сеансов (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, когда сообщение приходит после окна простоя. Если настроены и ежедневный сброс, и бездействие, срабатывает то, что истекает раньше.
initSessionState() в src/auto-reply/reply/session.ts.
Схема хранилища сеансов (sessions.json)
Тип значения хранилища — SessionEntry в src/config/sessions.ts.
Ключевые поля (не исчерпывающий список):
sessionId: текущий идентификатор транскрипта (имя файла выводится из него, если не заданsessionFile)updatedAt: отметка времени последней активностиsessionFile: необязательное явное переопределение пути к транскриптуchatType:direct | group | room(помогает UI и политике отправки)provider,subject,room,space,displayName: метаданные для маркировки групп/каналов- Переключатели:
thinkingLevel,verboseLevel,reasoningLevel,elevatedLevelsendPolicy(переопределение на уровне сеанса)
- Выбор модели:
providerOverride,modelOverride,authProfileOverride
- Счётчики токенов (best-effort / зависят от провайдера):
inputTokens,outputTokens,totalTokens,contextTokens
compactionCount: как часто автоуплотнение завершалось для этого ключа сеансаmemoryFlushAt: отметка времени последнего предуплотнительного сброса памятиmemoryFlushCompactionCount: счётчик уплотнений на момент последнего сброса
Структура транскрипта (*.jsonl)
Транскрипты управляются @mariozechner/pi-coding-agent через SessionManager.
Файл — JSONL:
- Первая строка: заголовок сеанса (
type: "session", включаетid,cwd,timestamp, необязательныйparentSession) - Далее: записи сеанса с
id+parentId(дерево)
message: сообщения пользователя/ассистента/результата инструментаcustom_message: сообщения, внедрённые расширениями, которые входят в контекст модели (могут быть скрыты из UI)custom: состояние расширений, которое не входит в контекст моделиcompaction: сохранённая сводка уплотнения сfirstKeptEntryIdиtokensBeforebranch_summary: сохранённая сводка при навигации по ветви дерева
SessionManager для чтения/записи.
Окна контекста vs отслеживаемые токены
Имеют значение два разных понятия:- Окно контекста модели: жёсткий предел для модели (токены, видимые модели)
- Счётчики хранилища сеансов: скользящая статистика, записываемая в
sessions.json(используется для /status и дашбордов)
- Окно контекста берётся из каталога моделей (и может быть переопределено через конфиг).
contextTokensв хранилище — это оценка/значение для отчётности во время выполнения; не воспринимайте его как строгую гарантию.
Уплотнение: что это такое
Уплотнение суммирует более ранний диалог в сохранённую записьcompaction в транскрипте и сохраняет недавние сообщения без изменений.
После уплотнения будущие ходы видят:
- Сводка компактности
- Сообщения после
firstKeptEntryId
Когда происходит автоуплотнение (рантайм Pi)
Во встроенном агенте Pi автоуплотнение срабатывает в двух случаях:- Восстановление после переполнения: модель возвращает ошибку переполнения контекста → уплотнение → повтор.
- Поддержание порога: после успешного хода, когда:
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, чтобы обозначить «не доставлять ответ пользователю». - OpenClaw удаляет/подавляет это на уровне доставки.
2026.1.10, OpenClaw также подавляет потоковую передачу черновиков/набора текста, когда частичный фрагмент начинается с NO_REPLY, чтобы тихие операции не «утекали» частичным выводом в середине хода.
Предуплотнительный «сброс памяти» (реализовано)
Цель: до срабатывания автоуплотнения выполнить тихий агентный ход, который запишет долговечное состояние на диск (например,memory/YYYY-MM-DD.md в рабочем пространстве агента), чтобы уплотнение не могло стереть критический контекст.
OpenClaw использует подход сброса до порога:
- Мониторинг использования контекста сеанса.
- При пересечении «мягкого порога» (ниже порога уплотнения Pi) — запуск тихой директивы агенту «записать память сейчас».
- Использование
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(точный токен) и что вы используете сборку, включающую исправление подавления потоковой передачи.