Sessions and memory

Осведомлённость о состоянии сеанса

Когда несколько сессий работают над одной задачей — менеджер делегирует её дочерним сессиям, человек напрямую подключается к рабочей сессии, два агента координируются через sessions_send — каждая сессия формирует предположения о других. Эти предположения устаревают, как только вмешивается другой участник. Механизм осведомлённости о состоянии сессий обнаруживает вмешательство, однократно уведомляет затронутую сессию и предоставляет ей экономичный способ получить актуальные данные перед выполнением действий.

Совместно работают три компонента:

  1. Долговечный журнал сигналов регистрирует выбранные изменения состояния для каждой сессии.
  2. Наблюдатели хранят курсоры для каждой целевой сессии и получают одно объединённое уведомление об устаревшем состоянии.
  3. Сверка получает точную дельту через session_status с changesSince.

Журнал сигналов

OpenClaw добавляет типизированное событие в общую базу данных состояния (session_state_events), когда отслеживаемая сессия существенно изменяется. События содержат метаданные и однострочное описание, но никогда не содержат текст сообщений.

Тип Когда регистрируется Уведомляет наблюдателей
human_direct_message Человек отправляет ход непосредственно в отслеживаемую сессию Да
upstream_missing Исчезает вышестоящий источник принятой сессии Да
goal_changed Состояние цели сессии создаётся, обновляется или очищается Да
child_spawned Создаётся сессия дочернего агента или дочерняя сессия ACP Нет (инициализирует курсор)
run_completed Дочерний запуск успешно завершается Нет (только журнал)
run_failed Дочерний запуск завершается с ошибкой, превышает время ожидания или отменяется Нет (только журнал)
compacted История сессии подвергается Compaction Нет (только журнал)
adopted Сессия из каталога принимается в OpenClaw Нет (только журнал)

Каждое событие указывает своего инициатора (human, agent или system). Отменённые дочерние запуски и запуски с превышением времени ожидания регистрируются как ошибки, при этом точный результат (cancelled, timeout или error) сохраняется в полезной нагрузке события.

Версия состояния сессии — это просто наибольший порядковый номер в её журнале, отслеживаемый в долговечной записи заголовка каждой сессии, которая сохраняется после очистки. Строки sessions_list содержат stateVersion, если в журнале сессии зарегистрированы изменения; session_status всегда возвращает это значение.

Типы, записываемые только в журнал, предназначены для истории сверки, а не для уведомлений: обычная доставка сведений о завершении дочернего запуска остаётся ответственностью объявлений дочерних агентов, и журнал сигналов никогда её не дублирует.

Наблюдатели

Наблюдатель — это сессия, которая хранит курсор (session_watch_cursors) целевой сессии. Курсоры создаются двумя способами:

  • Неявно (связи порождения). Когда сессия порождает дочернего агента или дочернюю сессию ACP, курсор родительской сессии автоматически инициализируется версией дочерней сессии на момент её порождения. Родительские сессии никогда не подписываются вручную.
  • Явно (sessions_send watch: true). Любой координатор может отслеживать цель, которую он не породил: передайте watch: true в sessions_send, и после успешной отправки сообщения отправитель будет зарегистрирован как наблюдатель сессии, фактически получившей сообщение. Регистрация начинается с текущей версии состояния целевой сессии — предыдущая история никогда не создаёт уведомлений. Если параметр был задан, результат инструмента содержит watched: true|false.

Идентификатор наблюдателя должен быть ключом сессии с указанием агента. При session.scope="global" общий ключ global неоднозначен для разных агентов, поэтому такие сессии получают долговечный журнал и changesSince, но не получают упреждающих уведомлений.

Отслеживания очищаются автоматически: строки курсоров истекают вместе со сроком хранения журнала сигналов, удаляются при сбросе сессии-наблюдателя и удаляются вместе с любой из двух сессий. В v1 команды прекращения отслеживания нет.

Для отслеживаемых сессий, принятых из каталога сессий, с фиксированной периодичностью проверяется непосредственная активность человека в вышестоящем источнике. Обнаруженная активность поступает в тот же журнал сигналов и проходит через тот же поток наблюдателей, что и другие непосредственные ходы человека.

Если вышестоящий источник принятой сессии удалён извне, три последовательные проверки, не обнаружившие его (примерно три такта монитора), создают один сигнал upstream_missing для её наблюдателей и удаляют ссылку на вышестоящий источник. При следующем продолжении сессии из каталога создаётся новая ссылка.

Уведомления: одно, а не множество

Когда регистрируется событие, допускающее уведомление, а курсор наблюдателя отстаёт, наблюдатель получает одно системное уведомление при следующем ходе:

Code
Сессия "agent:main:subagent:child" изменилась (другой участник). Выполните сверку перед действием: session_status sessionKey "agent:main:subagent:child" changesSince 12.

Наблюдатели в основных сессиях также немедленно пробуждаются через Heartbeat; вложенные наблюдатели — дочерние агенты получают уведомление при следующем ходе.

Протокол намеренно предотвращает спам:

  • Одно ожидающее уведомление для каждой пары наблюдатель/цель. Пока уведомление ожидает доставки, его текст остаётся побайтово неизменным, а очередь системных событий устраняет его дубликаты, поэтому даже двадцать быстрых изменений одной цели по-прежнему создают только одну строку в запросе наблюдателя.
  • Зафиксированная отметка. Когда уведомление ставится в очередь, курсор фиксирует позицию, о которой было сообщено. Последующие существенные события продвигают только отметку существенных изменений и не создают повторных уведомлений.
  • Подтверждение при извлечении, повторное открытие только при чередующихся изменениях. Когда ход наблюдателя получает уведомление, курсор продвигается. Если между постановкой в очередь и извлечением появились дополнительные существенные события, для оставшихся событий создаётся ровно одно новое уведомление.
  • Подавление собственных событий. Наблюдатель никогда не получает уведомления о событиях, которые вызвал сам.
  • Восстановление после перезапуска. Ожидающие уведомления находятся в очереди в памяти; после перезапуска Gateway проверка при запуске повторно создаёт их на основе долговечных курсоров.

Сверка

В уведомлении точно указано, что должен сделать наблюдатель. session_status с changesSince: <version> возвращает типизированные события после указанной версии (до 200), не продвигая курсоры:

json
{  "stateVersion": 19,  "stateChanges": {    "events": [      {        "sequence": 14,        "kind": "human_direct_message",        "actorType": "human",        "summary": "сообщение человека через telegram"      },      { "sequence": 19, "kind": "goal_changed", "actorType": "human", "summary": "цель обновлена" }    ],    "historyGap": false  }}

historyGap: true означает, что запрошенная версия предшествует сохранённой истории — вместо интерпретации ответа как точной дельты обновите всё состояние сессии (sessions_history, session_status). Сигнал о пробеле точен: он формируется на основе отметки очистки для каждой сессии, а не выводится арифметически из порядковых номеров.

Хранение и ограничения

История хранится в общей базе данных состояния и ограничена 30 днями и 50 000 строками; заголовки отдельных сессий сохраняют монотонность после очистки. Запись выполняется по мере возможности — ошибка добавления регистрируется в журнале и никогда не приводит к сбою исходного хода, — поэтому stateVersion является заголовком журнала сигналов, а не транзакционной версией журнала изменений.

Текущие ограничения:

  • Доставка уведомлений предполагает, что общей базой данных состояния управляет один процесс Gateway. Несколько процессов Gateway используют общий долговечный журнал и changesSince, но v1 не передаёт уведомления между процессами.
  • События Compaction охватывают владельцев Compaction встроенной среды выполнения; Compaction, выполняемая только нативной тестовой обвязкой, регистрируется не полностью.
  • Подробности полезной нагрузки результата отмены сейчас создаются дочерними запусками ACP; отмены нативных дочерних агентов отображаются как общие ошибки.
  • Обнаружение собственного эха вышестоящего источника сравнивает нормализованный пользовательский текст. Внешний запрос, совпадающий с одним из 10 последних пользовательских сообщений сессии на стороне OpenClaw, считается собственным эхом.
  • Одна локальная строка Claude JSONL размером более 1 МиБ, превышающая ограничение сканирования за один цикл, блокирует курсор этой сессии в v1; неклассифицированные байты никогда не пропускаются.
  • При проверках Claude на сопряжённых узлах за один цикл классифицируются последние 50 элементов истории. Более крупные всплески могут оказаться за пределами окна сканирования v1.
  • Чтение истории Claude на сопряжённых узлах не предоставляет однозначного результата об отсутствии ветки, поэтому удалённые ветки Claude в v1 не классифицируются как upstream_missing.
  • Сессии каталога, которые не были приняты, в v1 остаются за пределами слоя осведомлённости.
  • Сессии, принятые до появления этой функции, не содержат ссылки на вышестоящий источник; один раз продолжите их из каталога, чтобы начать мониторинг вышестоящего источника.
  • Ссылки на вышестоящие источники предполагают, что каждый ключ принятой сессии соответствует одному агенту-владельцу (при принятии используется агент хранилища по умолчанию). Принятие одной внешней ветки несколькими агентами в v1 не отслеживается.

Связанные материалы

Was this useful?
On this page

On this page