Управление сессиями

OpenClaw рассматривает одну сессию прямого чата на агента как основную. Прямые чаты сворачиваются к agent:<agentId>:<mainKey> (по умолчанию main), в то время как групповые/канальные чаты получают свои собственные ключи. session.mainKey учитывается.

Используйте session.dmScope для контроля того, как группируются прямые сообщения:

  • main (по умолчанию): все личные сообщения разделяют основную сессию для непрерывности.
  • per-peer: изолировать по id отправителя между каналами.
  • per-channel-peer: изолировать по каналу + отправителю (рекомендуется для общих почтовых ящиков).
  • per-account-channel-peer: изолировать по аккаунту + каналу + отправителю (рекомендуется для почтовых ящиков с несколькими аккаунтами). Используйте session.identityLinks для сопоставления id узлов с префиксом провайдера с каноническим идентификатором, чтобы один и тот же человек разделял сессию личных сообщений между каналами при использовании per-peer, per-channel-peer или per-account-channel-peer.

Шлюз — источник истины

Всё состояние сессии принадлежит шлюзу ("мастер" OpenClaw). UI клиенты (приложение macOS, WebChat и т.д.) должны запрашивать у шлюза списки сессий и количество токенов вместо чтения локальных файлов.

  • В удалённом режиме хранилище сессий, которое вас интересует, находится на удалённом хосте шлюза, а не на вашем Mac.
  • Количество токенов, отображаемое в UI, берётся из полей хранилища шлюза (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 для маркировки сессий в UI.
  • Записи сессий включают метаданные origin (метка + подсказки маршрутизации), чтобы UI мог объяснить, откуда пришла сессия.
  • OpenClaw не читает папки сессий legacy Pi/Tau.

Очистка сессии

OpenClaw обрезает старые результаты инструментов из контекста в памяти прямо перед вызовами LLM по умолчанию. Это не переписывает JSONL историю. См. /concepts/session-pruning.

Сброс памяти перед уплотнением

Когда сессия приближается к автоуплотнению, OpenClaw может запустить тихий сброс памяти ход, который напоминает модели записывать долговечные заметки на диск. Это работает только когда рабочее пространство доступно для записи. См. Memory и Compaction.

Сопоставление транспортов → ключи сессий

  • Прямые чаты следуют 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 соответствует id узла с префиксом провайдера (например, telegram:123), канонический ключ заменяет <peerId>, чтобы один и тот же человек разделял сессию между каналами.
  • Групповые чаты изолируют состояние: agent:<agentId>:<channel>:group:<id> (комнаты/каналы используют agent:<agentId>:<channel>:channel:<id>).
    • Топики форума Telegram добавляют :topic:<threadId> к id группы для изоляции.
    • Legacy ключи group:<id> всё ещё распознаются для миграции.
  • Входящие контексты могут всё ещё использовать group:<id>; канал выводится из Provider и нормализуется к каноническ ой форме agent:<agentId>:<channel>:group:<id>.
  • Другие источники:
    • Задания cron: cron:<job.id>
    • Webhooks: hook:<uuid> (если не установлено явно хуком)
    • Запуски узлов: node-<nodeId>

Жизненный цикл

  • Политика сброса: сессии используются повторно до истечения, и истечение оценивается при следующем входящем сообщении.
  • Ежедневный сброс: по умолчанию 4:00 утра по местному времени на хосте шлюза. Сессия устаревшая, как только её последнее обновление раньше самого последнего времени ежедневного сброса.
  • Сброс по бездействию (опционально): idleMinutes добавляет скользящее окно бездействия. Когда настроены и ежедневный, и сброс по бездействию, какой истекает первым, принуждает к новой сессии.
  • Legacy только бездействие: если вы устанавливаете session.idleMinutes без какой-либо конфигурации session.reset/resetByType, OpenClaw остаётся в режиме только бездействия для обратной совместимости.
  • Переопределения для конкретного типа (опционально): resetByType позволяет переопределить политику для сессий dm, group и thread (thread = потоки Slack/Discord, топики Telegram, потоки Matrix когда предоставляются коннектором).
  • Переопределения для конкретного канала (опционально): resetByChannel переопределяет политику сброса для канала (применяется ко всем типам сессий для этого канала и имеет приоритет над reset/resetByType).
  • Триггеры сброса: точные /new или /reset (плюс любые дополнительные в resetTriggers) запускают свежий id сессии и передают остаток сообщения. /new <model> принимает псевдоним модели, provider/model или имя провайдера (нечёткое совпадение) для установки модели новой сессии. Если /new или /reset отправлен один, OpenClaw запускает короткий приветственный ход "hello" для подтверждения сброса.
  • Ручной сброс: удалите конкретные ключи из хранилища или удалите JSONL транскрипт; следующее сообщение воссоздаст их.
  • Изолированные задания cron всегда создают свежий sessionId на запуск (нет повторного использования по бездействию).

Политика отправки (опционально)

Блокировать доставку для конкретных типов сессий без перечисления отдельных id.

{
  session: {
    sendPolicy: {
      rules: [
        { action: "deny", match: { channel: "discord", chatType: "group" } },
        { action: "deny", match: { keyPrefix: "cron:" } }
      ],
      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 },
      dm: { 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 как отдельное сообщение в чате, чтобы увидеть, доступен ли агент, сколько контекста сессии используется, текущие переключатели thinking/verbose и когда ваши учётные данные WhatsApp web последний раз обновлялись (помогает обнаружить необходимость повторной привязки).
  • Отправьте /context list или /context detail, чтобы увидеть, что в системной подсказке и инъецированных файлах рабочего пространства (и крупнейших вкладчиков контекста).
  • Отправьте /stop как отдельное сообщение, чтобы прервать текущий запуск, очистить очередь последующих для этой сессии и остановить любые запуски подагентов, порождённые от неё (ответ включает остановленное количество).
  • Отправьте /compact (опциональные инструкции) как отдельное сообщение, чтобы суммаризировать старый контекст и освободить место в окне. См. /concepts/compaction.
  • JSONL транскрипты могут быть открыты напрямую для просмотра полных ходов.

Советы

  • Держите первичный ключ выделенным для трафика 1:1; позвольте группам иметь свои собственные ключи.
  • При автоматизации очистки удаляйте отдельные ключи вместо всего хранилища, чтобы сохранить контекст в других местах.

Метаданные происхождения сессии

Каждая запись сессии записывает, откуда она пришла (наилучшее усилие) в origin:

  • label: человеческая метка (разрешённая из метки разговора + тема группы/канал)
  • provider: нормализованный id канала (включая расширения)
  • from/to: необработанные id маршрутизации из входящего конверта
  • accountId: id аккаунта провайдера (когда мульти-аккаунт)
  • threadId: id потока/топика когда канал поддерживает это Поля origin заполняются для прямых сообщений, каналов и групп. Если коннектор только обновляет маршрутизацию доставки (например, чтобы сохранить основную сессию личных сообщений свежей), он всё равно должен предоставить входящий контекст, чтобы сессия сохраняла свои метаданные объяснения. Расширения могут сделать это, отправив ConversationLabel, GroupSubject, GroupChannel, GroupSpace и SenderName во входящем контексте и вызвав recordSessionMetaFromInbound (или передав тот же контекст в updateLastRoute).