Когда я начал использовать Hermes сразу в нескольких проектах, всё работало через один общий профиль. Один Telegram-бот, одна история, один набор настроек и одна память.

Поначалу это было удобно. Агент знал мои предпочтения, понимал рабочие привычки и мог переходить между задачами без дополнительной настройки. Но постепенно общий контекст превратился из преимущества в источник ошибок.

У проектов были разные репозитории, способы деплоя и ограничения. Где-то можно было свободно менять тестовые данные, а где-то требовалась осторожность. Где-то агенту были нужны инструменты для работы с инфраструктурой, а где-то — только анализ кода.

Чем больше таких правил появлялось, тем труднее было ответить на простой вопрос:

Какой проект агент сейчас считает своим?

Я решил разделить Hermes на отдельные проектные профили. Но довольно быстро выяснилось, что создать несколько Telegram-ботов недостаточно. Нужно было решить более сложную задачу: разделить контекст проектов, не размножив при этом память и рабочие процедуры.

Профиль — это не просто отдельный чат

В Hermes профиль — это самостоятельное домашнее пространство агента. У него могут быть свои:

  • конфигурация;
  • модель и провайдер;
  • API-ключи и токены;
  • SOUL.md;
  • MEMORY.md и USER.md;
  • история сессий;
  • skills;
  • MCP-серверы;
  • cron-задачи;
  • gateway-процесс.

Это хорошо описано в документации Hermes о профилях.

Для каждого проекта я создал отдельный профиль, отдельный Telegram-бот и отдельный gateway. Также задал рабочий каталог, из которого агент начинает выполнять команды.

Получилась понятная схема:

Текстовый блок
Telegram-бот
    ↓
отдельный gateway
    ↓
профиль Hermes
    ↓
рабочий каталог проекта

Но здесь есть важное ограничение: профиль изолирует состояние самого Hermes, а не всю операционную систему.

Рабочий каталог задаёт начальную директорию, но не превращает профиль в файловую песочницу. Если terminal backend работает локально, агент по-прежнему имеет права текущего пользователя. Поэтому ограничения в SOUL.md помогают управлять поведением, но не заменяют Docker, отдельного системного пользователя или другую техническую изоляцию.

Тем не менее для моей задачи профиль решил главное: перестал смешиваться проектный контекст.

Память оказалась не одним механизмом

Следующая проблема появилась почти сразу.

Я спросил нового проектного агента, работает ли у него MemPalace. Он проверил поле memory.provider, увидел, что оно пустое, и сообщил, что MemPalace не подключён.

Формально проверка выглядела логично. Но она была основана на неверном предположении: что любая внешняя память Hermes обязательно должна быть настроена как memory provider.

На самом деле в моей архитектуре MemPalace подключается через MCP.

Это два разных механизма.

Memory provider Hermes

Hermes поддерживает внешние memory provider plugins. Согласно официальной документации, активный provider может автоматически:

  1. добавлять найденный контекст в системный prompt;
  2. искать релевантные воспоминания перед очередным ходом;
  3. синхронизировать диалог после ответа;
  4. извлекать новые факты при завершении сессии;
  5. зеркалировать записи встроенной памяти;
  6. предоставлять собственные инструменты для поиска и записи.

Это удобная архитектура: агент получает память автоматически, без отдельного решения о том, когда её искать.

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

Кэширование prompt может влиять на стоимость обработки повторяющегося префикса, но не отменяет сам объём контекста и его влияние на внимание модели.

MemPalace через MCP

MemPalace появился в моём рабочем процессе раньше, чем отдельные проектные профили. Исторически я подключил его как внешний сервер инструментов через Model Context Protocol.

Когда в Hermes появились полноценные memory providers, я не стал автоматически переносить туда уже работающую память. Сначала это было следствием истории системы, а затем стало осознанным архитектурным решением.

Hermes знает, что инструменты MemPalace существуют, но содержимое дворца памяти не добавляется автоматически в каждый запрос. Агент обращается к нему только тогда, когда задача требует исторического контекста.

Например:

Текстовый блок
Пользователь спрашивает о прошлом решении
    ↓
агент вызывает поиск в MemPalace
    ↓
получает несколько релевантных записей
    ↓
проверяет их по текущему коду или документации
    ↓
формирует ответ

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

Именно это стало основной причиной, по которой я умышленно не стал использовать memory provider Hermes для MemPalace.

Почему память вызывается по требованию

Проектная память со временем становится большой. В ней накапливаются:

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

Всё это полезно, но не всё нужно в каждом запросе.

Автоматическая подстановка памяти хорошо работает, когда агенту почти всегда требуется персональный или исторический контекст. У меня другой сценарий: много проектов и большое количество технических операций, значительная часть которых не требует обращения к прошлому.

Поэтому я выбрал постепенное раскрытие контекста:

Текстовый блок
Загружается постоянно:
├── профильные правила
├── короткая память о пользователе
├── несколько критичных ограничений
└── компактный индекс доступных возможностей

Загружается по необходимости:
├── история решений из MemPalace
├── подробности прошлых ошибок
├── инфраструктурные сведения
├── полные инструкции skills
└── дополнительные проектные документы

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

Это не означает, что MCP работает совершенно бесплатно. У модели остаётся информация о доступных инструментах, а поиск памяти требует дополнительного tool-вызова. При первом обращении появляется небольшая задержка.

Hermes решает часть этой проблемы с помощью Tool Search: полные схемы MCP-инструментов могут загружаться по требованию, а в постоянном контексте остаётся более компактный каталог возможностей.

Получается осознанный обмен:

Автоматический providerMemPalace через MCP
Память подбирается автоматическиАгент должен решить, когда искать
Меньше риск забыть про прошлый контекстМеньше лишнего контекста в обычных вызовах
Дополнительный контекст может появляться перед ходамиВ prompt попадают только результаты выполненного поиска
Меньше tool-вызововПоиск требует отдельного вызова
Удобен для постоянно нужной персональной памятиУдобен для большой проектной базы знаний

Для моей работы второй вариант оказался предсказуемее и экономнее по контексту.

Три уровня памяти

В результате память разделилась на три уровня.

1. Короткая встроенная память

USER.md и MEMORY.md остаются включёнными.

В них хранятся только сведения, которые полезны почти в каждой сессии:

  • язык общения;
  • устойчивые предпочтения;
  • постоянные ограничения;
  • правила безопасности;
  • несколько фактов об окружении;
  • принятый стиль работы.

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

Моё практическое правило:

Во встроенную память попадает только то, что стоит повторять модели почти в каждом диалоге.

2. Большая проектная память

MemPalace хранит знания, которые важны в будущем, но не нужны постоянно:

  • почему было принято определённое решение;
  • какие варианты уже проверяли;
  • в чём заключалась root cause;
  • какие ошибки нельзя повторять;
  • как устроен компонент;
  • что осталось нерешённым.

Память разделена по проектам логически, но доступна через общий MCP. Агент начинает поиск с нужного проектного раздела и расширяет его только для межпроектной инфраструктуры.

3. Актуальные первоисточники

MemPalace хранит историю. История не всегда равна текущему состоянию.

Поэтому найденная запись не становится окончательным доказательством. После поиска агент проверяет факты по источнику, который отражает актуальное состояние:

Текстовый блок
MemPalace
    ↓
проектная документация
    ↓
Git и текущий код
    ↓
live runtime, API или база данных

Если в памяти записано, что сервис работал на определённом адресе несколько месяцев назад, это исторический факт. Чтобы назвать адрес текущим, нужно проверить инфраструктуру.

Такой порядок защищает от одной из самых опасных ошибок долговременной памяти: уверенного использования устаревшей информации.

Цена памяти по требованию

У этой архитектуры есть очевидный риск: агент может не вызвать поиск, даже когда прошлый контекст нужен.

Автоматический provider решает эту задачу сам. В MCP-варианте нужно научить агента распознавать ситуации, в которых память обязательна.

Для этого в профильных правилах появились явные триггеры:

  • вопрос о прошлом решении;
  • работа с инфраструктурой;
  • повторная ошибка;
  • неизвестный способ деплоя;
  • упоминание известной особенности проекта;
  • продолжение работы после долгого перерыва;
  • расхождение между текущей сессией и проектной документацией.

При таких запросах агент должен сначала искать в MemPalace, а уже затем предлагать действия.

Важно было зафиксировать и порядок обработки ошибки:

Текстовый блок
MemPalace
→ troubleshooting-документация
→ текущий код
→ live-состояние
→ исправление

Без этого агент мог сразу начать экспериментировать и повторить проблему, которая уже была расследована раньше.

Skills — это тоже память, но процедурная

После разделения обычной памяти возник аналогичный вопрос со skills.

Skills содержат не факты о проектах, а проверенные способы выполнения задач:

  • как проводить аудит;
  • как отлаживать определённый класс ошибок;
  • как выполнять релиз;
  • как проверять инфраструктуру;
  • как оформлять результат;
  • какие защитные проверки обязательны.

Изначально такие skills копировались в каждый профиль. Это казалось логичным: профиль отдельный, значит и инструкции должны лежать внутри него.

Но копии быстро начали расходиться.

Исправление, сделанное в основной библиотеке, не попадало в старые профили. Хуже того, profile-local skill с тем же именем мог иметь более высокий приоритет и незаметно скрывать обновлённую общую версию.

Получилась классическая проблема дублирования:

Текстовый блок
общий skill v3
├── профиль 1: копия v1
├── профиль 2: копия v2
└── профиль 3: локально изменённая v1

Невозможно было уверенно сказать, по какой процедуре работает конкретный агент.

Общая библиотека вместо копий

Решением стала единая каноническая библиотека skills, подключённая к профилям через skills.external_dirs.

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

Текстовый блок
Профиль 1 ─┐
Профиль 2 ─┼──→ общая Git-библиотека skills
Профиль 3 ─┘

Новые профили создаются без копирования всей библиотеки. Локальный skill допускается только как намеренное исключение. Если процедура подходит нескольким профилям, исправляется каноническая версия.

После изменения skill проходит:

  1. проверку структуры;
  2. валидацию связанных файлов и скриптов;
  3. review diff;
  4. обновление семантического индекса;
  5. проверку загрузки из проектного профиля.

Так я получил общие навыки без общей истории и без смешивания проектных ограничений.

Почему skills тоже не исполняются из MemPalace

В какой-то момент появилась естественная идея: если MemPalace умеет семантический поиск, почему бы не хранить там полные тексты skills и не исполнять найденную инструкцию?

От этого варианта я отказался.

Семантическая база хорошо отвечает на вопрос: «Какой skill подходит к этой задаче?» Но она не должна самостоятельно отвечать на вопрос: «Какой текст сейчас разрешено исполнять?»

Если полная инструкция извлекается из поисковой базы, усложняется контроль:

  • происхождения;
  • версии;
  • изменений;
  • связанного кода;
  • валидности скриптов;
  • отката;
  • намеренных локальных исключений.

Поэтому MemPalace хранит только поисковый индекс:

  • название skill;
  • краткое описание;
  • путь;
  • категорию;
  • версию;
  • хэш;
  • подсказки для поиска.

Найденная запись считается метаданными. После поиска агент загружает канонический SKILL.md штатным инструментом Hermes. Исполняемым источником остаётся файловая библиотека под Git.

Это тот же принцип, что и с проектной памятью:

Поисковая система помогает найти источник, но не заменяет сам источник.

Конфигурация ещё не означает, что всё работает

Во время настройки профилей я столкнулся ещё с одной проблемой: успешная команда не всегда означала успешную цепочку.

Одна из первых команд добавления MemPalace дошла до интерактивного подтверждения, но не сохранила конфигурацию. При этом пустой memory.provider отвлёк диагностику в неправильную сторону.

После этого проверка стала состоять из нескольких уровней:

  1. MCP присутствует в конфигурации профиля;
  2. соединение с сервером устанавливается;
  3. Hermes обнаруживает ожидаемые инструменты;
  4. инструменты доступны в новой или перезагруженной сессии;
  5. реальный запрос из Telegram доходит до нужного gateway;
  6. профиль вызывает MemPalace;
  7. ответ возвращается в тот же чат.

Появилась и отдельная операционная тонкость. После перезапуска gateway тестовое сообщение можно отправить слишком рано: Telegram его уже примет, но новое поколение polling ещё не будет готово его обработать.

Поэтому окончательная проверка выглядит так:

Текстовый блок
Telegram
→ gateway нужного профиля
→ модель
→ MCP
→ MemPalace
→ ответ в Telegram

Только успешная сквозная цепочка считается доказательством работоспособности.

Что в итоге получилось

Сейчас архитектура разделяет не агентов целиком, а разные виды их знаний.

Текстовый блок
Отдельно для каждого профиля:
├── Telegram и gateway
├── конфигурация
├── сессии
├── рабочий каталог
├── SOUL.md
├── USER.md
├── MEMORY.md
└── проектные ограничения

Общее:
├── MemPalace
├── каноническая библиотека skills
└── инфраструктурные знания

По требованию:
├── поиск проектной истории
├── загрузка полного skill
└── дополнительная документация

Главное решение здесь не в количестве ботов. Отдельные боты — только видимая часть системы.

Настоящая архитектура определяется ответами на четыре вопроса:

  1. Что агент должен знать всегда?
  2. Что нужно загружать только для конкретной задачи?
  3. Какие знания принадлежат одному проекту?
  4. Какие процедуры должны быть одинаковыми для всех профилей?

Я оставил во встроенной памяти только короткий обязательный контекст. Большую проектную память подключил через MCP и вызываю по необходимости. Skills вынес в общую версионируемую библиотеку, а MemPalace использую как индекс для их поиска.

Так профили сохраняют собственную проектную идентичность, но не превращаются в изолированные копии, которые постепенно забывают общие правила.


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