Sessions and memory
Осведомлённость о состоянии сеанса
Когда несколько сессий работают над одной задачей — менеджер делегирует её дочерним сессиям, человек напрямую подключается к рабочей сессии, два агента координируются через sessions_send — каждая сессия формирует предположения о других. Эти предположения устаревают, как только вмешивается другой участник. Механизм осведомлённости о состоянии сессий обнаруживает вмешательство, однократно уведомляет затронутую сессию и предоставляет ей экономичный способ получить актуальные данные перед выполнением действий.
Совместно работают три компонента:
- Долговечный журнал сигналов регистрирует выбранные изменения состояния для каждой сессии.
- Наблюдатели хранят курсоры для каждой целевой сессии и получают одно объединённое уведомление об устаревшем состоянии.
- Сверка получает точную дельту через
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 для её наблюдателей и удаляют ссылку на вышестоящий источник. При следующем продолжении сессии из каталога создаётся новая ссылка.
Уведомления: одно, а не множество
Когда регистрируется событие, допускающее уведомление, а курсор наблюдателя отстаёт, наблюдатель получает одно системное уведомление при следующем ходе:
Сессия "agent:main:subagent:child" изменилась (другой участник). Выполните сверку перед действием: session_status sessionKey "agent:main:subagent:child" changesSince 12.Наблюдатели в основных сессиях также немедленно пробуждаются через Heartbeat; вложенные наблюдатели — дочерние агенты получают уведомление при следующем ходе.
Протокол намеренно предотвращает спам:
- Одно ожидающее уведомление для каждой пары наблюдатель/цель. Пока уведомление ожидает доставки, его текст остаётся побайтово неизменным, а очередь системных событий устраняет его дубликаты, поэтому даже двадцать быстрых изменений одной цели по-прежнему создают только одну строку в запросе наблюдателя.
- Зафиксированная отметка. Когда уведомление ставится в очередь, курсор фиксирует позицию, о которой было сообщено. Последующие существенные события продвигают только отметку существенных изменений и не создают повторных уведомлений.
- Подтверждение при извлечении, повторное открытие только при чередующихся изменениях. Когда ход наблюдателя получает уведомление, курсор продвигается. Если между постановкой в очередь и извлечением появились дополнительные существенные события, для оставшихся событий создаётся ровно одно новое уведомление.
- Подавление собственных событий. Наблюдатель никогда не получает уведомления о событиях, которые вызвал сам.
- Восстановление после перезапуска. Ожидающие уведомления находятся в очереди в памяти; после перезапуска Gateway проверка при запуске повторно создаёт их на основе долговечных курсоров.
Сверка
В уведомлении точно указано, что должен сделать наблюдатель. session_status с changesSince: <version> возвращает типизированные события после указанной версии (до 200), не продвигая курсоры:
{ "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 не отслеживается.
Связанные материалы
- Инструменты сессий —
sessions_send,session_status,sessions_list - Дочерние агенты — связи порождения и объявления о завершении
- Heartbeat — как уведомления из очереди пробуждают основные сессии
- Управление сессиями — ключи, области действия и жизненный цикл сессий