🏠 Главная › developer guide › memory provider plugin
Создание плагина провайдера памяти
Плагины провайдеров памяти предоставляют агенту Hermes постоянное межсессионное хранилище знаний, выходное за рамки встроенных MEMORY.md и USER.md. В этом руководстве описано, как создать такой плагин.:::совет
Провайдеры памяти — один из двух типов провайдерских плагинов. Второй — Плагины контекстного движка, которые заменяют встроенный компрессор контекста. Оба следующих шаблона: одиночный выбор, управление через конфигурацию, администрирование через hermes плагины.
Структура директории
Память каждого провайдера находится в plugins/memory/<имя>/:
Ваш плагин реализует абстрактный базовый класс MemoryProvider из agent/memory_provider.py:
fromagent.memory_providerimportMemoryProviderclassMyMemoryProvider(MemoryProvider):@propertydefname(self)->str:return"my-provider"defis_available(self)->bool:"""Проверяет, может ли этот провайдер активироваться. Без сетевых вызовов."""returnbool(os.environ.get("MY_API_KEY"))definitialize(self,session_id:str,**kwargs)->None:"""Вызывается один раз при запуске агента. kwargs всегда включает: hermes_home (str): Активный путь HERMES_HOME. Используйте для хранения. """self._api_key=os.environ.get("MY_API_KEY","")self._session_id=session_id#... реализация остальных методов
Обязательные методы
Основной жизненный цикл
Метод
Когда возникает
Обязателен?
имя (свойство)
Всегда
Да
is_available()
Инициализация агента, перед активацией
Да — без сетевых вызовов
инициализировать(session_id, **kwargs)
Запуск агента
Да
get_tool_schemas()
После изобретения инструменты для ремонта
Да
handle_tool_call(имя, аргументы)
Когда агент использует ваши инструменты
Да (если есть инструменты)
Конфигурация
Метод
Назначение
Обязателен?
get_config_schema()
Объявляет поля конфигурации для настройки памяти Гермеса
Да
save_config(значения, hermes_home)
Записывает несекретную конфигурацию в данном положении
Да (если не только через переменные окружения)
Опциональные хуки
Метод
Когда возникает
Сценарий использования
system_prompt_block()
Сборка системного промпта
Статическая информация о провайдере
предварительная выборка(запрос)
Перед каждым API-вызовом
Возврат извлечённого контекста
queue_prefetch(запрос)
После каждого шага
Предварительная загрузка для следующего шага
sync_turn(пользователь, помощник)
После каждого завершения шага
Сохранение диалога
on_session_end(сообщения)
Завершение диалога
Финальное извлечение/сброс
on_pre_compress(сообщения)
Перед сжатием контекста
Сохранение инсайтов перед удалением
on_memory_write(действие, цель, содержимое)
Встроенные записи в память
Зеркалирование в вашем бэкенде
выключение()
Процесс завершения
Очистка соединений
Схема схемы
get_config_schema() возвращает список описаний полей, включая hermes Memory setup:
defget_config_schema(self):return[{"key":"api_key","description":"API-ключ My Provider","secret":True,# → записывается в.env"required":True,"env_var":"MY_API_KEY",# явное имя переменной окружения"url":"https://my-provider.com/keys",# где получить},{"key":"region","description":"Регион сервера","default":"us-east","choices":["us-east","eu-west","ap-south"],},{"key":"project","description":"Идентификатор проекта","default":"hermes",},]
Поля с secret: True и env_var в .env. Несекретные поля передаются в save_config().
💡 Tip
Минимальная и Полная схема
Каждое поле из get_config_schema() запрашивается во время настройки памяти Hermes. Провайдерам с большим количеством опций следует делать минимальный протокол — включая только поля, которые пользователь обязан настроить (API-ключ, обязательные учётные данные). Дополнительные настройки документируйте в файле конфигурации (например, $HERMES_HOME/myprovider.json), и не запрашивайте их каждый раз во время установки. Это сохраняет скорость установки мастера, но поддерживает расширенную конфигурацию. Смотрите пример провайдера Supermemory — он запрашивает только API-ключ; все остальные параметры находятся в supermemory.json.
Сохранение конфигурации
defsave_config(self,values:dict,hermes_home:str)->None:"""Записывает несекретную конфигурацию в собственное расположение."""importjsonfrompathlibimportPathconfig_path=Path(hermes_home)/"my-provider.json"config_path.write_text(json.dumps(values,indent=2))
Для провайдеров, использующих только переменные окружения, оставьте сообщение по умолчанию (пустую).
Точка входа плагина
defregister(ctx)->None:"""Вызывается системой обнаружения плагинов памяти."""ctx.register_memory_provider(MyMemoryProvider())
sync_turn() НЕ ДОЛЖЕН блокировать выполнение. Если ваш бэкенд имеет задержку (API-вызовы, обработка LLM), выполните работу в фоновом потоке-демоне:
defsync_turn(self,user_content,assistant_content):def_sync():try:self._api.ingest(user_content,assistant_content)exceptExceptionase:logger.warning("Синхронизация не удалась: %s",e)ifself._sync_threadandself._sync_thread.is_alive():self._sync_thread.join(timeout=5.0)self._sync_thread=threading.Thread(target=_sync,daemon=True)self._sync_thread.start()
Изоляция профилей
Все пути хранения обязаны использовать аргумент hermes_home из initialize(), а не жёстко заданный ~/.hermes:
# ПРАВИЛЬНО — в рамках профиляfromhermes_constantsimportget_hermes_homedata_dir=get_hermes_home()/"my-provider"# НЕПРАВИЛЬНО — общий для всех профилейdata_dir=Path("~/.hermes/my-provider").expanduser()
Тестирование
Смотрите tests/agent/test_memory_plugin_e2e.py для полного шаблона E2E-тестирования с использованием реального SQLite-провайдера.
Плагины провайдеров в памяти могут регистрировать собственное дерево подкомандой CLI (например, «статус моего провайдера Гермеса», «конфигурация моего провайдера Гермеса»). Это использует обнаружение систем на основе соглашений — изменений в основных файлах не требуется.
Как это работает
Добавьте файл cli.py в каталог вашего плагина.
Определите функцию register_cli(subparser), которая строит дерево argparse.
Система плагинов памяти обнаруживает его при запуске через discover_plugin_cli_commands()
Ваша команда строительной под hermes <имя-провайдера> <подкоманда>
Ограничение активным провайдером: Ваши CLI-команды тогда только тогда, когда ваш провайдер является активным memory.provider в конфигурации. Если пользователь не настроил вашего провайдера, ваши команды не будут указаны в hermes --help.
Пример
# plugins/memory/my-provider/cli.pydefmy_command(args):"""Обработчик, вызываемый argparse."""sub=getattr(args,"my_command",None)ifsub=="status":print("Провайдер активен и подключён.")elifsub=="config":print("Показываю конфигурацию...")else:print("Использование: hermes my-provider <status|config>")defregister_cli(subparser)->None:"""Строит дерево argparse для hermes my-provider. Вызывается discover_plugin_cli_commands() во время настройки argparse. """subs=subparser.add_subparsers(dest="my_command")subs.add_parser("status",help="Показать статус провайдера")subs.add_parser("config",help="Показать конфигурацию провайдера")subparser.set_defaults(func=my_command)
Эталонная продажа
Смотрите plugins/memory/honcho/cli.py для всего примера с 13 подкомандами, кросс-профильным управлением (--target-profile) и чтением/записью конфигурации.
Только один внешний провайдер памяти может быть активирован одновременно. Если пользователь попытается зарегистрировать вторую, MemoryManager отклонит его предупреждение. Это собственное раздувание схемных инструментов и конфликтов бэкендов.