import useBaseUrl from ‘@docusaurus/useBaseUrl’;
Сессии
Каждый разговор Hermes Agent автоматически сохраняет как сессию. За счёт этого вы возобновляете беседы с того места, где остановились, ищете по всей истории и управляете полным архивом переписки.
Как устроены сессии
Любой разговор — из CLI, Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Teams или любой другой платформы для сообщений — сохраняется как сессия с полной историей сообщений. Отслеживаются сессии в:
- Базе данных SQLite (
~/.hermes/state.db) — структурированные метаданные сессии с полнотекстовым поиском FTS5 плюс полная история сообщений
База SQLite хранит:
- ID сессии, исходную платформу, ID пользователя
- Заголовок сессии (уникальное, человекочитаемое имя)
- Имя модели и её конфигурацию
- Снимок системного промпта
- Полную историю сообщений (роль, содержимое, вызовы инструментов, результаты инструментов)
- Счётчики токенов (вход/выход)
- Метки времени (started_at, ended_at)
- ID родительской сессии (для разбиения сессии при сжатии)
Что попадает в контекст
Hermes хранит историю сессии, чтобы продолжать беседы, но не пересылает заново каждый байт, который когда-либо обработал. На каждом ходу модель видит выбранный системный промпт, текущее окно разговора и то содержимое, которое Hermes явно подмешивает именно для этого хода.
Медиавложения обрабатываются как входные данные в пределах одного хода:
- Изображения либо прикрепляются нативно к следующему вызову модели, либо заранее разбираются в текстовое описание, если активная модель не поддерживает нативное зрение.
- Аудио расшифровывается в текст, когда настроено распознавание речи.
- Из текстовых документов можно включить извлечённый текст; документы других типов обычно представлены сохранённым локальным путём и короткой пометкой.
- Пути к вложениям и извлечённый или производный текст могут попадать в транскрипт, а вот сырые байты картинки, аудио или бинарного файла повторно в будущие промпты не копируются.
Скажем, пользователь присылает изображение и просит сделать из него мем. Hermes один раз изучит картинку через зрение и запустит скрипт обработки изображения. На следующих ходах исходный JPEG в контекст сам собой не тянется. Остаётся только то, что записалось в разговор: запрос пользователя, короткое описание картинки, путь к локальному кэшу или финальный ответ ассистента.
Чаще всего контекст разрастается вовсе не из-за медиафайла. Виноват многословный текст: вставленные транскрипты, полные логи, объёмный вывод инструментов, длинные диффы, повторяющиеся отчёты о статусе и подробные дампы с доказательствами. Лучше передавать резюме, пути к файлам, точечные выдержки и запросы через инструменты, чем копировать в чат громоздкие артефакты.
Используйте /compress, когда сессия разрослась, /new — для свежей ветки, а hermes sessions prune — только когда действительно хотите удалить старые завершённые сессии из хранилища. Сжатие уменьшает активный контекст, но это не удаление ради приватности. Передайте имя в /new (например, /new payments-refactor), чтобы сразу задать начальный заголовок новой сессии — потом её проще найти через /resume <name> или в выборщике /sessions.
Источники сессий
У каждой сессии проставлена метка исходной платформы:
| Источник | Описание |
|---|---|
cli | Интерактивный CLI (hermes или hermes chat) |
telegram | Мессенджер Telegram |
discord | Сервер/ЛС Discord |
slack | Рабочее пространство Slack |
whatsapp | Мессенджер WhatsApp |
signal | Мессенджер Signal |
matrix | Комнаты и ЛС Matrix |
mattermost | Каналы Mattermost |
email | Электронная почта (IMAP/SMTP) |
sms | SMS через Twilio |
dingtalk | Мессенджер DingTalk |
feishu | Мессенджер Feishu/Lark |
wecom | WeCom (WeChat Work) |
weixin | Weixin (личный WeChat) |
bluebubbles | Apple iMessage через сервер BlueBubbles на macOS |
qqbot | QQ Bot (Tencent QQ) через Official API v2 |
homeassistant | Разговор в Home Assistant |
webhook | Входящие вебхуки |
api-server | Запросы к API-серверу |
acp | Интеграция с редактором по ACP |
cron | Запланированные задания cron |
batch | Пакетная обработка |
Возобновление сессии в CLI
Возобновить прошлые разговоры из CLI можно через --continue или --resume:
Продолжить последнюю сессию
# Возобновить самую недавнюю CLI-сессию
hermes --continue
hermes -c
# Или через подкоманду chat
hermes chat --continue
hermes chat -c
Команда находит самую недавнюю сессию с источником cli в базе SQLite и загружает её полную историю разговора.
Возобновление по имени
Если вы дали сессии заголовок (см. раздел Именование сессий ниже), её можно возобновить по имени:
# Возобновить именованную сессию
hermes -c "my project"
# Если есть варианты-наследники (my project, my project #2, my project #3),
# автоматически возобновится самый недавний
hermes -c "my project" # → возобновляет "my project #3"
Возобновить конкретную сессию
# Возобновить конкретную сессию по ID
hermes --resume 20250305_091523_a1b2c3d4
hermes -r 20250305_091523_a1b2c3d4
# Возобновить по заголовку
hermes --resume "refactoring auth"
# Или через подкоманду chat
hermes chat --resume 20250305_091523_a1b2c3d4
ID сессии показывается, когда вы выходите из CLI-сессии, а найти его можно через hermes sessions list.
Сводка разговора при возобновлении
Когда вы возобновляете сессию, Hermes показывает компактную сводку предыдущего разговора в оформленной панели перед строкой ввода:
<img className=“docs-terminal-figure” src={useBaseUrl(‘/img/docs/session-recap.svg’)} alt=“Stylized preview of the Previous Conversation recap panel shown when resuming a Hermes session.” />
В режиме возобновления показывается компактная панель сводки с недавними ходами пользователя и ассистента, прежде чем вернуть вас к живой строке ввода.
Сводка:
- Показывает сообщения пользователя (золотой
●) и ответы ассистента (зелёный◆) - Урезает длинные сообщения (300 символов для пользователя, 200 символов / 3 строки для ассистента)
- Сворачивает вызовы инструментов до счётчика с именами инструментов (например,
[3 tool calls: terminal, web_search]) - Скрывает системные сообщения, результаты инструментов и внутренние рассуждения
- Ограничивается последними 10 обменами репликами и ставит индикатор «… N earlier messages …»
- Применяет приглушённое оформление, чтобы отличаться от активного разговора
Чтобы отключить сводку и оставить минимальное поведение в одну строку, задайте в ~/.hermes/config.yaml:
display:
resume_display: minimal # по умолчанию: full
ID сессий следуют формату YYYYMMDD_HHMMSS_<hex> — у сессий CLI/TUI шестнадцатеричный суффикс из 6 символов (например, 20250305_091523_a1b2c3), у сессий шлюза — суффикс из 8 символов (например, 20250305_091523_a1b2c3d4). Возобновить можно по ID (полному или уникальному префиксу) или по заголовку — оба варианта работают с -c и -r.
Передача между платформами
Команда /handoff <platform> из CLI-сессии переносит живой разговор в домашний канал платформы для сообщений. Агент подхватывает беседу ровно там, где её оставил CLI: тот же id сессии, полный транскрипт с учётом ролей, вызовы инструментов и всё остальное.
# Внутри CLI-сессии
/handoff telegram
Что при этом происходит:
-
CLI проверяет, что
<platform>включена и для неё задан домашний канал (один раз выполните/sethomeв чате назначения, чтобы его настроить). -
CLI помечает сессию как ожидающую и блокирующе опрашивает шлюз. Если агент в середине хода — команда отказывает, сначала дождитесь окончания текущего ответа.
-
Наблюдатель шлюза забирает передачу и запрашивает у адаптера назначения новую ветку:
- Telegram — открывает новую тему форума (темы в ЛС, если в чате включён режим Topics из Bot API 9.4+, либо тему в супергруппе-форуме).
- Discord — создаёт под домашним текстовым каналом ветку с авто-архивацией на 1440 минут.
- Slack — публикует стартовое сообщение и использует его
tsкак якорь ветки. - WhatsApp / Signal / Matrix / SMS — нативных веток нет, поэтому всё уходит прямо в домашний канал.
-
Шлюз перепривязывает ключ назначения к вашему уже существующему id CLI-сессии, затем формирует синтетический ход пользователя с просьбой подтвердить и подвести итог. Ответ приходит в новую ветку.
-
Когда шлюз подтверждает успех, CLI печатает подсказку с
/resumeи аккуратно завершает работу:↻ Handoff complete. The session is now active on telegram. Resume it on this CLI later with: /resume my-session-title -
С этого момента разговор живёт на платформе. Отвечайте в новой ветке — любой, у кого есть доступ в этот канал, работает с той же сессией, и любое более позднее реальное сообщение пользователя в ветке подключается без сбоев, потому что сессии веток ключуются без
user_id.
Возврат в CLI: когда захотите вернуться за десктоп, просто выполните /resume <title> (или hermes -r "<title>" из оболочки) и продолжите с того места, где остановилась платформа.
Сценарии сбоев:
- Домашний канал не настроен → CLI отказывает и подсказывает про
/sethome. - Платформа не включена / шлюз не запущен → CLI завершается по таймауту в 60 с с понятным сообщением, а ваша CLI-сессия остаётся нетронутой.
- Создать ветку не удалось (права, выключенный режим тем) → всё уходит прямо в домашний канал и передача всё равно завершается; изоляции ветки нет, но сам handoff работает.
adapter.sendупал (лимит запросов, временная ошибка API) → передача помечается неудачной с указанием причины; запись очищается, так что можно повторить.
Ограничение, о котором стоит знать: для платформ без поддержки веток с многопользовательскими групповыми домашними каналами синтетический ход ключуется как сессия в стиле ЛС. Для домашних каналов self-DM (типичная конфигурация) это работает, но для по-настоящему общих групповых чатов вариант не идеален. Ветки покрывают Telegram / Discord / Slack — а это и есть самый частый случай, — поэтому большинство конфигураций сюда вообще не упирается.
Именование сессий
Давайте сессиям человекочитаемые заголовки, чтобы их было легко находить и возобновлять.
Автоматически сгенерированные заголовки
После первого обмена репликами Hermes автоматически генерирует для каждой сессии короткий описательный заголовок (3–7 слов). Делается это в фоновом потоке быстрой вспомогательной моделью, так что задержки не добавляется. Автозаголовки видны при просмотре сессий через hermes sessions list или hermes sessions browse.
Автозаголовок срабатывает только раз на сессию и пропускается, если вы уже задали заголовок вручную.
Установка заголовка вручную
Внутри любой чат-сессии (CLI или шлюз) используйте слеш-команду /title:
/title my research project
Заголовок применяется сразу. Если сессия ещё не создана в базе (например, вы запустили /title до отправки первого сообщения), команда ставится в очередь и применяется, как только сессия стартует.
Переименовать существующие сессии можно и из командной строки:
hermes sessions rename 20250305_091523_a1b2c3d4 "refactoring auth module"
Правила заголовков
- Уникальность — две сессии не могут иметь одинаковый заголовок
- Максимум 100 символов — чтобы вывод списка оставался чистым
- Очистка — управляющие символы, символы нулевой ширины и RTL-переопределения вырезаются автоматически
- Обычный Unicode допустим — эмодзи, иероглифы CJK, символы с диакритикой работают
Авто-наследование при сжатии
Когда контекст сессии сжимается (вручную через /compress или автоматически), Hermes создаёт новую сессию-продолжение. Если у исходной был заголовок, новая сессия автоматически получает нумерованный заголовок:
"my project" → "my project #2" → "my project #3"
При возобновлении по имени (hermes -c "my project") автоматически выбирается самая недавняя сессия в цепочке наследования.
/title в платформах для сообщений
Команда /title работает во всех платформах шлюза (Telegram, Discord, Slack, WhatsApp):
/title My Research— задать заголовок сессии/title— показать текущий заголовок
Команды управления сессиями
У Hermes есть полный набор команд управления сессиями через hermes sessions:
Список сессий
# Список недавних сессий (по умолчанию: последние 20)
hermes sessions list
# Фильтр по платформе
hermes sessions list --source telegram
# Показать больше сессий
hermes sessions list --limit 50
Когда у сессий есть заголовки, вывод показывает заголовки, превью и относительные метки времени:
Title Preview Last Active ID
────────────────────────────────────────────────────────────────────────────────────────────────
refactoring auth Help me refactor the auth module please 2h ago 20250305_091523_a
my project #3 Can you check the test failures? yesterday 20250304_143022_e
— What's the weather in Las Vegas? 3d ago 20250303_101500_f
Когда заголовков ни у одной сессии нет, используется более простой формат:
Preview Last Active Src ID
──────────────────────────────────────────────────────────────────────────────────────
Help me refactor the auth module please 2h ago cli 20250305_091523_a
What's the weather in Las Vegas? 3d ago tele 20250303_101500_f
Экспорт сессий
# Экспортировать все сессии в файл JSONL
hermes sessions export backup.jsonl
# Экспортировать сессии с конкретной платформы
hermes sessions export telegram-history.jsonl --source telegram
# Экспортировать одну сессию
hermes sessions export session.jsonl --session-id 20250305_091523_a1b2c3d4
Экспортированные файлы содержат по одному JSON-объекту на строку с полными метаданными сессии и всеми сообщениями.
Удаление сессии
# Удалить конкретную сессию (с подтверждением)
hermes sessions delete 20250305_091523_a1b2c3d4
# Удалить без подтверждения
hermes sessions delete 20250305_091523_a1b2c3d4 --yes
Переименование сессии
# Задать или изменить заголовок сессии
hermes sessions rename 20250305_091523_a1b2c3d4 "debugging auth flow"
# В CLI заголовки из нескольких слов не требуют кавычек
hermes sessions rename 20250305_091523_a1b2c3d4 debugging auth flow
Если заголовок уже занят другой сессией, выводится ошибка.
Очистка старых сессий
# Удалить завершённые сессии старше 90 дней (по умолчанию)
hermes sessions prune
# Свой порог возраста
hermes sessions prune --older-than 30
# Очистить только сессии с конкретной платформы
hermes sessions prune --source telegram --older-than 60
# Пропустить подтверждение
hermes sessions prune --older-than 30 --yes
Prune удаляет только завершённые сессии (те, что были явно завершены или авто-сброшены). Активные сессии не удаляются никогда.
Статистика сессий
hermes sessions stats
Вывод:
Total sessions: 142
Total messages: 3847
cli: 89 sessions
telegram: 38 sessions
discord: 15 sessions
Database size: 12.4 MB
За более глубокой аналитикой — расход токенов, оценка стоимости, разбивка по инструментам и паттерны активности — обращайтесь к hermes insights.
Инструмент поиска по сессиям
У агента есть встроенный инструмент session_search, который ведёт полнотекстовый поиск по всем прошлым разговорам через движок FTS5 в SQLite — и позволяет агенту пролистывать любую найденную сессию. Без вызовов LLM, без резюмирования, без усечения. Каждый из режимов возвращает реальные сообщения из БД.
Три формы вызова
Инструмент сам определяет, что вам нужно, по тому, какие аргументы вы задали. Параметра mode нет.
1. Поиск по содержимому — передайте query:
session_search(query="auth refactor", limit=3)
Запускает FTS5, схлопывает совпадения по цепочке наследования сессий, возвращает топ N сессий. Каждый результат несёт:
session_id,title,when,sourcesnippet— выдержка совпадения с подсветкой FTS5bookend_start— первые 3 сообщения пользователя и ассистента сессии (цель/старт)messages— ±5 сообщений вокруг совпадения FTS5, с пометкой на якорном сообщении (совпадение в контексте)bookend_end— последние 3 сообщения пользователя и ассистента сессии (итог/решения)match_message_id,messages_before,messages_after
«Скобки» начала и конца вместе с окном восстанавливают цепочку цель → совпадение → итог, не оплачивая весь транскрипт. Типичное время ответа: 15–50 мс на реальной базе сессий.
2. Прокрутка — передайте session_id + around_message_id:
session_search(session_id="20260510_174648_805cc2", around_message_id=590803, window=10)
Возвращает окно из ±window сообщений с центром на якоре. Без FTS5, без «скобок» — только срез. Применяйте после поиска, когда нужно больше контекста, чем даёт окно ±5 по умолчанию.
- Прокрутка вперёд: передайте обратно
messages[-1].idкакaround_message_id - Прокрутка назад: передайте обратно
messages[0].idкакaround_message_id - Граничное сообщение появляется в обоих окнах как ориентир
- Когда
messages_beforeилиmessages_afterменьшеwindow, вы у начала или конца сессии
Типичное время ответа: 1–2 мс на вызов прокрутки.
3. Обзор — без аргументов:
session_search()
Возвращает недавние сессии в хронологическом порядке (заголовки, превью, метки времени). Удобно, когда пользователь спрашивает «над чем я работал», не называя темы.
Синтаксис запросов FTS5
Режим ключевых слов поддерживает стандартный синтаксис запросов FTS5:
- Простые ключевые слова:
docker deployment(FTS5 по умолчанию использует AND) - Фразы:
"exact phrase" - Булевы операторы:
docker OR kubernetes,python NOT java - Префикс:
deploy*
Необязательные параметры
sort—newestилиoldest, поверх ранжирования FTS5. Опустите для сортировки только по релевантности (вариант по умолчанию; подходит для исследовательного поиска). Используйтеnewestдля вопросов «на чём мы остановились с X»,oldest— для «с чего X начался».role_filter— роли через запятую, которые надо включить. По умолчанию поиск используетuser,assistant(вывод инструментов обычно лишний шум). Передайтеuser,assistant,tool, чтобы включить вывод инструментов (отладка поведения инструмента), илиtool, чтобы искать только по их выводу.
Когда он применяется
Агенту в промпте предписано использовать поиск по сессиям автоматически:
«Когда пользователь ссылается на что-то из прошлого разговора или ты подозреваешь, что есть релевантный предыдущий контекст, используй session_search, чтобы вспомнить это, прежде чем просить пользователя повторить.»
Типичные триггеры: «мы это уже делали», «помнишь, когда», «в прошлый раз», «как я упоминал» или любая отсылка к проекту, человеку или понятию, которого нет в текущем окне.
Отслеживание сессий по платформам
Сессии шлюза
На платформах для сообщений сессии ключуются детерминированным ключом сессии, который собирается из источника сообщения:
| Тип чата | Формат ключа по умолчанию | Поведение |
|---|---|---|
| ЛС Telegram | agent:main:telegram:dm:<chat_id> | Одна сессия на каждый чат ЛС |
| ЛС Discord | agent:main:discord:dm:<chat_id> | Одна сессия на каждый чат ЛС |
| ЛС WhatsApp | agent:main:whatsapp:dm:<canonical_identifier> | Одна сессия на пользователя ЛС (псевдонимы LID/телефона схлопываются в одну личность при наличии сопоставления) |
| Групповой чат | agent:main:<platform>:group:<chat_id>:<user_id> | На каждого пользователя внутри группы, когда платформа отдаёт ID пользователя |
| Ветка/тема в группе | agent:main:<platform>:group:<chat_id>:<thread_id> | Общая сессия для всех участников ветки (по умолчанию). На каждого пользователя при thread_sessions_per_user: true. |
| Канал | agent:main:<platform>:channel:<chat_id>:<user_id> | На каждого пользователя внутри канала, когда платформа отдаёт ID пользователя |
Если Hermes не может получить идентификатор участника для общего чата, он откатывается к одной общей сессии на эту комнату.
Общие и изолированные групповые сессии
По умолчанию Hermes использует group_sessions_per_user: true в config.yaml. Это означает:
- Алиса и Боб могут оба общаться с Hermes в одном канале Discord, не деля историю транскрипта
- длинная задача одного пользователя с кучей инструментов не засоряет окно контекста другого
- обработка прерываний тоже остаётся пользовательской, потому что ключ запущенного агента совпадает с ключом изолированной сессии
Если же вам нужен один общий «мозг комнаты», задайте:
group_sessions_per_user: false
Тогда группы/каналы возвращаются к единой общей сессии на комнату: общий контекст разговора сохраняется, но вместе с ним делятся и расход токенов, и состояние прерываний, и рост контекста.
Политики сброса сессий
Сессии шлюза сбрасываются автоматически по настраиваемым политикам:
- idle — сброс после N минут бездействия
- daily — сброс в определённый час каждый день
- both — сброс по тому, что наступит раньше (idle или daily)
- none — без авто-сброса
Перед авто-сбросом сессии агенту даётся ход, чтобы сохранить важные воспоминания или навыки из разговора.
Сессии с активными фоновыми процессами не сбрасываются никогда, какой бы ни была политика.
Где что хранится
| Что | Путь | Описание |
|---|---|---|
| База SQLite | ~/.hermes/state.db | Все метаданные сессий + сообщения с FTS5 |
| Сообщения шлюза | ~/.hermes/state.db | SQLite — каноническое хранилище всех сообщений сессий |
| Индекс маршрутизации шлюза | ~/.hermes/sessions/sessions.json | Сопоставляет ключи сессий с активными ID сессий (метаданные источника, флаги истечения) |
База SQLite работает в режиме WAL — несколько читателей и один писатель, что хорошо ложится на многоплатформенную архитектуру шлюза.
У сессий, созданных до того, как state.db стал каноническим, могут оставаться файлы *.jsonl в ~/.hermes/sessions/. Hermes их больше не пишет и не читает. Их можно безопасно удалить, убедившись, что соответствующая сессия есть в state.db.
Схема базы данных
Ключевые таблицы в state.db:
- sessions — метаданные сессии (id, source, user_id, model, title, метки времени, счётчики токенов). У заголовков уникальный индекс (NULL-заголовки разрешены, уникальными должны быть только не-NULL).
- messages — полная история сообщений (role, content, tool_calls, tool_name, token_count)
- messages_fts — виртуальная таблица FTS5 для полнотекстового поиска по содержимому сообщений
Истечение и очистка сессий
Автоматическая очистка
- Сессии шлюза авто-сбрасываются по настроенной политике сброса
- Перед сбросом агент сохраняет воспоминания и навыки из истекающей сессии
- Авто-очистка по согласию: когда
sessions.auto_pruneравноtrue, завершённые сессии старшеsessions.retention_days(по умолчанию 90) удаляются при старте CLI/шлюза - После prune, который действительно удалил строки, для
state.dbвыполняетсяVACUUM, чтобы освободить место на диске (обычный DELETE файл SQLite не уменьшает) - Prune запускается не чаще раза в
sessions.min_interval_hours(по умолчанию 24); метка времени последнего запуска хранится внутри самогоstate.db, поэтому она общая для всех процессов Hermes в одномHERMES_HOME
По умолчанию опция выключена — история сессий ценна для поиска через session_search, а тихое удаление могло бы застать пользователей врасплох. Включить в ~/.hermes/config.yaml:
sessions:
auto_prune: true # согласие — по умолчанию false
retention_days: 90 # хранить завершённые сессии столько дней
vacuum_after_prune: true # освобождать место на диске после прохода очистки
min_interval_hours: 24 # не перезапускать проход чаще этого интервала
Активные сессии не удаляются автоматически независимо от возраста.
Ручная очистка
# Удалить сессии старше 90 дней
hermes sessions prune
# Удалить конкретную сессию
hermes sessions delete <session_id>
# Экспортировать перед очисткой (резервная копия)
hermes sessions export backup.jsonl
hermes sessions prune --older-than 30 --yes
База растёт медленно (типично: 10–15 МБ на сотни сессий), а история сессий питает поиск session_search по прошлым разговорам, поэтому авто-очистка поставляется отключённой. Включайте её, если у вас тяжёлая нагрузка на шлюз/cron, где state.db ощутимо влияет на производительность (наблюдавшийся сбой: state.db на 384 МБ примерно с 1000 сессий замедлял вставки в FTS5 и листинг /resume). Для разовой очистки без включения автоматического прохода используйте hermes sessions prune.