Управление сессиями
OpenClaw рассматривает одну сессию прямого чата на агента как основную. Прямые чаты сворачиваются в agent:<agentId>:<mainKey> (по умолчанию main), в то время как групповые чаты/каналы получают свои собственные ключи. Значение session.mainKey учитывается. Используйте session.dmScope для управления группировкой личных сообщений:
main(по умолчанию): все ЛС используют основную сессию для непрерывности.per-peer: изолировать по идентификатору отправителя между каналами.per-channel-peer: изолировать по каналу + отправителю (рекомендуется для многопользовательских инбоксов).per-account-channel-peer: изолировать по аккаунту + каналу + отправителю (рекомендуется для мультиаккаунтных инбоксов). Используйтеsession.identityLinksдля сопоставления идентификаторов отправителей с префиксом провайдера с канонической идентичностью, чтобы один и тот же человек использовал одну сессию ЛС между каналами при использованииper-peer,per-channel-peerилиper-account-channel-peer.
Безопасный режим ЛС (рекомендуется для многопользовательских сценариев)
Предупреждение безопасности: Если ваш агент может получать ЛС от нескольких людей, вам настоятельно рекомендуется включить безопасный режим ЛС. Без него все пользователи используют один и тот же контекст разговора, что может привести к утечке приватной информации между пользователями.
Пример проблемы с настройками по умолчанию:
- Алиса (
<SENDER_A>) пишет вашему агенту на приватную тему (например, о медицинской записи) - Боб (
<SENDER_B>) пишет вашему агенту с вопросом «О чём мы говорили?» - Поскольку оба ЛС используют одну сессию, модель может ответить Бобу, используя предыдущий контекст Алисы.
Решение: Установите dmScope для изоляции сессий по пользователям:
// ~/.openclaw/openclaw.json
{
session: {
// Безопасный режим ЛС: изолировать контекст ЛС по каналу + отправителю.
dmScope: "per-channel-peer",
},
}
Когда включать эту настройку:
- У вас есть одобренные подключения более чем от одного отправителя
- Вы используете разрешительный список ЛС с несколькими записями
- Вы устанавливаете
dmPolicy: "open" - Несколько номеров телефонов или аккаунтов могут писать вашему агенту
Примечания:
- По умолчанию
dmScope: "main"для непрерывности (все ЛС используют основную сессию). Это подходит для однопользовательских сценариев. - Локальная настройка через CLI записывает
session.dmScope: "per-channel-peer"по умолчанию, если значение не задано (существующие явные значения сохраняются). - Для мультиаккаунтных инбоксов на одном канале предпочтительнее
per-account-channel-peer. - Если один и тот же человек связывается с вами на нескольких каналах, используйте
session.identityLinks, чтобы объединить его сессии ЛС в одну каноническую идентичность. - Вы можете проверить настройки ЛС с помощью
openclaw security audit(см. безопасность).
Шлюз — источник истины
Все состояние сессии принадлежит шлюзу («главному» OpenClaw). UI-клиенты (приложение для macOS, WebChat и т.д.) должны запрашивать у шлюза списки сессий и количество токенов, а не читать локальные файлы.
- В удалённом режиме хранилище сессий, которое вас интересует, находится на удалённом хосте шлюза, а не на вашем Mac.
- Количество токенов, отображаемое в интерфейсах, берётся из полей хранилища шлюза (
inputTokens,outputTokens,totalTokens,contextTokens). Клиенты не парсят JSONL-транскрипты, чтобы «исправить» итоговые значения.
Где хранится состояние
- На хосте шлюза:
- Файл хранилища:
~/.openclaw/agents/<agentId>/sessions/sessions.json(на агента).
- Файл хранилища:
- Транскрипты:
~/.openclaw/agents/<agentId>/sessions/<SessionId>.jsonl(сессии тем Telegram используют.../<SessionId>-topic-<threadId>.jsonl). - Хранилище представляет собой карту
sessionKey -> { sessionId, updatedAt, ... }. Удаление записей безопасно; они воссоздаются по требованию. - Групповые записи могут включать
displayName,channel,subject,roomиspaceдля маркировки сессий в интерфейсах. - Записи сессий включают метаданные
origin(метка + подсказки маршрутизации), чтобы интерфейсы могли объяснить, откуда взялась сессия. - OpenClaw не читает устаревшие папки сессий Pi/Tau.
Обслуживание
OpenClaw применяет обслуживание хранилища сессий, чтобы ограничить размер sessions.json и артефактов транскриптов со временем.
Значения по умолчанию
session.maintenance.mode:warnsession.maintenance.pruneAfter:30dsession.maintenance.maxEntries:500session.maintenance.rotateBytes:10mbsession.maintenance.resetArchiveRetention: по умолчанию равенpruneAfter(30d)session.maintenance.maxDiskBytes: не задан (отключён)session.maintenance.highWaterBytes: по умолчанию80%отmaxDiskBytes, когда включено бюджетирование
Как это работает
Обслуживание выполняется во время записи в хранилище сессий, и вы можете запустить его вручную с помощью openclaw sessions cleanup.
mode: "warn": сообщает, что было бы удалено, но не изменяет записи/транскрипты.mode: "enforce": применяет очистку в следующем порядке:- удаляет устаревшие записи старше
pruneAfter - ограничивает количество записей до
maxEntries(сначала самые старые) - архивирует файлы транскриптов для удалённых записей, на которые больше нет ссылок
- очищает старые архивы
*.deleted.<timestamp>и*.reset.<timestamp>согласно политике хранения - ротирует
sessions.json, когда он превышаетrotateBytes - если задан
maxDiskBytes, применяет дисковый бюджет доhighWaterBytes(сначала самые старые артефакты, затем самые старые сессии)
- удаляет устаревшие записи старше
Особенности производительности для больших хранилищ
Большие хранилища сессий часто встречаются в высоконагруженных сценариях. Работа по обслуживанию выполняется на пути записи, поэтому очень большие хранилища могут увеличить задержку записи. Что сильнее всего увеличивает затраты:
- очень высокие значения
session.maintenance.maxEntries - длинные окна
pruneAfter, которые сохраняют устаревшие записи - множество артефактов транскриптов/архивов в
~/.openclaw/agents/<agentId>/sessions/ - включение дисковых бюджетов (
maxDiskBytes) без разумных ограничений на удаление/количество
Что делать:
- используйте
mode: "enforce"в продакшене, чтобы рост автоматически ограничивался - устанавливайте и временные, и количественные ограничения (
pruneAfter+maxEntries), а не только одно - задавайте
maxDiskBytes+highWaterBytesдля жёстких верхних границ в крупных развёртываниях - держите
highWaterBytesзначительно нижеmaxDiskBytes(по умолчанию 80%) - запускайте
openclaw sessions cleanup --dry-run --jsonпосле изменения конфигурации, чтобы проверить предполагаемое влияние перед применением - для часто активных сессий передавайте
--active-keyпри ручной очистке
Примеры настройки
Используйте консервативную политику принудительной очистки:
{
session: {
maintenance: {
mode: "enforce",
pruneAfter: "45d",
maxEntries: 800,
rotateBytes: "20mb",
resetArchiveRetention: "14d",
},
},
}
Включите жёсткий дисковый бюджет для директории сессий:
{
session: {
maintenance: {
mode: "enforce",
maxDiskBytes: "1gb",
highWaterBytes: "800mb",
},
},
}
Настройка для крупных инсталляций (пример):
{
session: {
maintenance: {
mode: "enforce",
pruneAfter: "14d",
maxEntries: 2000,
rotateBytes: "25mb",
maxDiskBytes: "2gb",
highWaterBytes: "1.6gb",
},
},
}
Предпросмотр или принудительное обслуживание из CLI:
openclaw sessions cleanup --dry-run
openclaw sessions cleanup --enforce
Очистка сессий
По умолчанию OpenClaw обрезает старые результаты инструментов из контекста в памяти непосредственно перед вызовами LLM. Это не перезаписывает историю JSONL. См. /concepts/session-pruning.
Предварительная очистка памяти перед компрессией
Когда сессия приближается к автоматической компрессии, OpenClaw может выполнить скрытую очистку памяти, которая напоминает модели записать устойчивые заметки на диск. Это выполняется только тогда, когда рабочее пространство доступно для записи. См. Память и Компрессия.
Сопоставление транспортов → ключи сессий
- Прямые чаты следуют
session.dmScope(по умолчаниюmain).main:agent:<agentId>:<mainKey>(непрерывность между устройствами/каналами).- Несколько номеров телефонов и каналов могут быть сопоставлены с одним основным ключом агента; они действуют как транспорты в один разговор.
per-peer:agent:<agentId>:dm:<peerId>.per-channel-peer:agent:<agentId>:<channel>:dm:<peerId>.per-account-channel-peer:agent:<agentId>:<channel>:<accountId>:dm:<peerId>(accountId по умолчаниюdefault).- Если
session.identityLinksсовпадает с идентификатором отправителя с префиксом провайдера (например,telegram:123), канонический ключ заменяет<peerId>, чтобы один и тот же человек использовал одну сессию ЛС между каналами.
- Групповые чаты изолируют состояние:
agent:<agentId>:<channel>:group:<id>(комнаты/каналы используютagent:<agentId>:<channel>:channel:<id>).- Темы форума Telegram добавляют
:topic:<threadId>к идентификатору группы для изоляции. - Устаревшие ключи
group:<id>всё ещё распознаются для миграции.
- Темы форума Telegram добавляют
- Входящие контексты могут всё ещё использовать
group:<id>; канал выводится изProviderи нормализуется к канонической формеagent:<agentId>:<channel>:group:<id>. - Другие источники:
- Cron-задачи:
cron:<job.id> - Вебхуки:
hook:<uuid>(если явно не задано вебхуком) - Запуски узлов:
node-<nodeId>
- Cron-задачи:
Жизненный цикл
- Политика сброса: сессии повторно используются до истечения срока, и срок действия оценивается при следующем входящем сообщении.
- Ежедневный сброс: по умолчанию в 4:00 по местному времени на хосте шлюза. Сессия считается устаревшей, если её последнее обновление произошло раньше времени последнего ежедневного сброса.
- Сброс по бездействию (опционально):
idleMinutesдобавляет скользящее окно бездействия. Когда настроены и ежедневный, и сброс по бездействию, тот, который истекает первым, принудительно запускает новую сессию. - Устаревший режим только по бездействию: если вы установите
session.idleMinutesбез какой-либо конфигурацииsession.reset/resetByType, OpenClaw останется в режиме только по бездействию для обратной совместимости. - Переопределения по типу (опционально):
resetByTypeпозволяет переопределить политику для сессийdirect,groupиthread(thread = треды Slack/Discord, темы Telegram, треды Matrix, когда предоставляются коннектором). - Переопределения по каналу (опционально):
resetByChannelпереопределяет политику сброса для канала (применяется ко всем типам сессий для этого канала и имеет приоритет надreset/resetByType). - Триггеры сброса: точные команды
/newили/reset(плюс любые дополнительные вresetTriggers) запускают новый идентификатор сессии и пропускают остаток сообщения./new <model>принимает псевдоним модели,provider/modelили имя провайдера (нечёткое совпадение) для установки модели новой сессии. Если/newили/resetотправлены отдельно, OpenClaw выполняет короткий «приветственный» ход для подтверждения сброса. - Ручной сброс: удалите конкретные ключи из хранилища или удалите JSONL-транскрипт; следующее сообщение воссоздаст их.
- Изолированные cron-задачи всегда создают новый
sessionIdна запуск (без повторного использования по бездействию).
Политика отправки (опционально)
Блокируйте доставку для определённых типов сессий без перечисления отдельных идентификаторов.
{
session: {
sendPolicy: {
rules: [
{ action: "deny", match: { channel: "discord", chatType: "group" } },
{ action: "deny", match: { keyPrefix: "cron:" } },
// Совпадение с сырым ключом сессии (включая префикс `agent:<id>:`).
{ action: "deny", match: { rawKeyPrefix: "agent:main:discord:" } },
],
default: "allow",
},
},
}
Переопределение во время выполнения (только для владельца):
/send on→ разрешить для этой сессии/send off→ запретить для этой сессии/send inherit→ очистить переопределение и использовать правила конфигурации Отправляйте эти команды как отдельные сообщения, чтобы они зарегистрировались.
Конфигурация (пример опционального переименования)
// ~/.openclaw/openclaw.json
{
session: {
scope: "per-sender", // держать групповые ключи отдельно
dmScope: "main", // непрерывность ЛС (установите per-channel-peer/per-account-channel-peer для общих инбоксов)
identityLinks: {
alice: ["telegram:123456789", "discord:987654321012345678"],
},
reset: {
// По умолчанию: mode=daily, atHour=4 (местное время хоста шлюза).
// Если вы также установите idleMinutes, побеждает тот, который истекает первым.
mode: "daily",
atHour: 4,
idleMinutes: 120,
},
resetByType: {
thread: { mode: "daily", atHour: 4 },
direct: { mode: "idle", idleMinutes: 240 },
group: { mode: "idle", idleMinutes: 120 },
},
resetByChannel: {
discord: { mode: "idle", idleMinutes: 10080 },
},
resetTriggers: ["/new", "/reset"],
store: "~/.openclaw/agents/{agentId}/sessions/sessions.json",
mainKey: "main",
},
}
Инспекция
openclaw status— показывает путь к хранилищу и недавние сессии.openclaw sessions --json— выводит все записи (фильтр с--active <minutes>).openclaw gateway call sessions.list --params '{}'— получить сессии из запущенного шлюза (используйте--url/--tokenдля доступа к удалённому шлюзу).- Отправьте
/statusкак отдельное сообщение в чате, чтобы увидеть, доступен ли агент, сколько контекста сессии использовано, текущие переключатели мышления/подробного вывода и когда ваши учётные данные WhatsApp web были последний раз обновлены (помогает обнаружить необходимость перепривязки). - Отправьте
/context listили/context detail, чтобы увидеть, что находится в системном промпте и внедрённых файлах рабочего пространства (и основных вкладчиков в контекст). - Отправьте
/stop(или отдельные фразы прерывания, такие какstop,stop action,stop run,stop openclaw), чтобы прервать текущий запуск, очистить запланированные последующие действия для этой сессии и остановить любые запуски под-агентов, порождённые из неё (в ответе будет указано количество остановленных). - Отправьте
/compact(опциональные инструкции) как отдельное сообщение, чтобы суммировать старый контекст и освободить место в окне. См. /concepts/compaction. - JSONL-транскрипты можно открывать напрямую для просмотра полных ходов.
Советы
- Держите основной ключ предназначенным для трафика 1:1; позвольте группам иметь свои собственные ключи.
- При автоматизации очистки удаляйте отдельные ключи вместо всего хранилища, чтобы сохранить контекст в других местах.
Метаданные происхождения сессии
Каждая запись сессии записывает (по возможности) своё происхождение в origin:
label: человекочитаемая метка (разрешённая из метки разговора + темы группы/канала)provider: нормализованный идентификатор канала (включая расширения)from/to: сырые идентификаторы маршрутизации из входящего конвертаaccountId: идентификатор аккаунта провайдера (при мультиаккаунтности)threadId: идентификатор треда/темы, когда канал поддерживает это Поля происхождения заполняются для личных сообщений, каналов и групп. Если коннектор только обновляет маршрутизацию доставки (например, чтобы поддерживать основную сессию ЛС свежей), он всё равно должен предоставлять входящий контекст, чтобы сессия сохраняла свои объясняющие метаданные. Расширения могут делать это, отправляяConversationLabel,GroupSubject,GroupChannel,GroupSpaceиSenderNameво входящем контексте и вызываяrecordSessionMetaFromInbound(или передавая тот же контекст вupdateLastRoute).