Настройка Nix и NixOS

Агент Гермес предлагает хлопья Nix с различными уровнями развития:

Уровень Для кого Что вы чувствуете
nix run / nix Profile install Любой пользователь Nix (macOS, Linux) Предварительно собранный бинарник со всеми зависимостями — затем викоризованный CLI-рабочий стандартный процесс
Модуль NixOS (родной) Серверные развертывания NixOS Декларативная конфигурация, защищенный systemd-сервис, управляемые секреты
Модуль NixOS (контейнер) Агенты, которым необходимо обновление Всё выше, плюс постоянный контейнер Ubuntu, где агент может выполнить apt/pip/npm install
Установщик завиток | bash сам управляет Python, Node и зависимостями. Nix flake заменяет всё это — собственная Python-зависимость является Nix-производной, построенной с помощью uv2nix, инструментов времени выполнения (Node.js, git, ripgrep, ffmpeg), встроенных в бинарник PATH. Нет пакета времени выполнения, нет активации venv, нет npm install.

Для пользователей, отличных от NixOS это меняется только на шаге установки. Всё после (hermes setup, hermesшлюз install, редактирование конфига) работает идентично настроено установка.

Для пользователей модуля NixOS весь жизненный цикл другой: изменение находится в configuration.nix, секреты идут через sops-nix/agenix, сервис — это systemd-юнит, а CLI-команды конфигурации заблокированы. Вы управляете Hermes так же, как и любым другим NixOS-сервисом.

Предварительные требования


Быстрый старт (любой пользователь Nix)

Клонирование не требуется. Никс загружает, собирает и запускает всё:

# Запуск напрямую (собирается при первом использовании, затем кэшируется)
nix run github:NousResearch/hermes-agent -- setup
nix run github:NousResearch/hermes-agent -- chat

# Или установите постоянно
nix profile install github:NousResearch/hermes-agent
hermes setup
hermes chat

После установки профиля nix hermes, hermes-agent и hermes-acp меняются в вашем PATH. Требуется рабочий процесс, идентичный стандартной установкеhermes setup проведет через выбор провайдера, hermes Gateway install настраивает launchd (macOS) или пользователя systemd-service, конфигурация находится в ~/.hermes/.

<подробности>

Сборка из локального клона
git clone https://github.com/NousResearch/hermes-agent.git
cd hermes-agent
nix build./result/bin/hermes setup

</подробнее>


Модуль NixOS

Flake экспортирует nixosModules.default — полноценный сервисный модуль NixOS, который декларативно управляет созданием пользователей, директориями, генерацией конфига, секретами, документами и жизненным циклом сервиса.:::примечание Для этого модуля требуется NixOS. Для систем, не основанных на NixOS (macOS, других дистрибутивах Linux), используйте nix Profile install и стандартный CLI-рабочий процесс выше.

Добавление Flake Input

# /etc/nixos/flake.nix (или ваш системный flake)
{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    hermes-agent.url = "github:NousResearch/hermes-agent";
  };

  outputs = { nixpkgs, hermes-agent,... }: {
    nixosConfigurations.your-host = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        hermes-agent.nixosModules.default./configuration.nix
      ];
    };
  };
}

Минимальная конфигурация

# configuration.nix
{ config,... }: {
  services.hermes-agent = {
    enable = true;
    settings.model.default = "anthropic/claude-sonnet-4";
    environmentFiles = [ config.sops.secrets."hermes-env".path ];
    addToSystemPackages = true;
  };
}

Вот и всё. nixos-rebuild switch создает пользователя hermes, последовательно config.yaml, включает секреты и запускает шлюз — долго работающий сервис, который соединяет агента с платформами обмена сообщениями (Telegram, Discord и т.д.) и прослушивает входящие сообщения.:::предупреждение Секреты обязательны Строка environmentFiles выше предполагает, что у вас настроены sops-nix или agenix. Файл должен сохранять как минимум один ключ LLM-провайдера (например, OPENROUTER_API_KEY=sk-or-...). См. Управление секретами для полной настройки. Если у вас еще нет менеджера секретов, вы можете использовать обычный файл в качестве отправной точки — просто убедитесь, что он не читается всеми:

echo "OPENROUTER_API_KEY=sk-or-your-key" | sudo install -m 0600 -o hermes /dev/stdin /var/lib/hermes/env
services.hermes-agent.environmentFiles = [ "/var/lib/hermes/env" ];
```::::::совет addToSystemPackages
Установка `addToSystemPackages = true` делает две вещи: помещает CLI `hermes` в системный PATH **и** устанавливает `HERMES_HOME` общесистемно, так что интерактивный раздел CLI показывает состояние (сессии, навыки, cron) с сервисным шлюзом. Без этого запуска `hermes` в вашей оболочке создаст отдельный каталог `~/.hermes/`.</div>
### CLI с поддержкой контейнера:::информация
Когда `container.enable = true` и `addToSystemPackages = true`, **каждая** команда `hermes` на хосте автоматически маршрутизируется в управляемый контейнер. Это означает, что ваша интерактивная CLI-сессия работает в том же механизме, что и сервисный шлюз  с доступом ко всем установленным в пакетах контейнера и инструментам.

- Маршрутизация прозрачна: `чат Гермеса`, `список сессий Гермеса`, `версия Гермеса` и т.д. выполняются внутри контейнера под капотом
- Все флаги CLI передаются так, как есть.
- Если контейнер не запущен, CLI повторяется в течение короткого времени (5 с со спиннером для интерактивного использования, 10 с молчания для скриптов), затем завершается с четкой потерей  без молчаливого отката.
- Для разработчиков, работающих над кодом Hermes, установите HERMES_DEV=1, чтобы обойти маршрут сжатия контейнера и запустить локальное копирование напрямую.

Установите `container.hostUsers`, чтобы создать симлинк `~/.hermes` в каталоге состояния сервиса, чтобы хост CLI и контейнер разделяли сессию, конфиг и воспоминания:
```nix
services.hermes-agent = {
  container.enable = true;
  container.hostUsers = [ "your-username" ];
  addToSystemPackages = true;
};

Пользователи, перечисленные в hostUsers, автоматически подключаются к hermes для доступа к нескольким файлам.

Пользователи Podman: Сервис NixOS запускает контейнер от root. Пользователи Docker получают доступ через сокет группы docker, но корневые-контейнеры Podman требуют sudo. Предоставьте sudo без пароля для вашего контейнерного времени выполнения:

security.sudo.extraRules = [{
  users = [ "your-username" ];
  commands = [{
    command = "/run/current-system/sw/bin/podman";
    options = [ "NOPASSWD" ];
  }];
}];

CLI автоматически определяет, когда требуется sudo, и использует его прозрачность. Без этого вам придется запускать sudo Hermes Chat вручную.

Проверка работы

После nixos-rebuild switch проверьте, что сервис запущен:

# Проверка статуса сервиса
systemctl status hermes-agent

# Просмотр логов (Ctrl+C для остановки)
journalctl -u hermes-agent -f

# Если addToSystemPackages = true, протестируйте CLI
hermes version
hermes config       # показывает сгенерированный конфиг

Выбор режима развертывания

Модуль питания двух режимов, управляемых container.enable:

Нативный (по умолчанию) Контейнер
Как работает Защищенный systemd-сервис на хосте Постоянный контейнер Ubuntu с привязкой /nix/store
Безопасность NoNewPrivileges, ProtectSystem=strict, PrivateTmp Изоляция контейнера, работает как непривилегированный пользователь внутри
Агент может сам хранить пакеты Нет — только инструменты из Nix-предоставленного PATH Да — apt, pip, npm установка приоритета между перезапусками
внешняя конфигурация Та же Та же
Когда будут представлены Стандартные развертывания, максимальная безопасность, воспроизводимость Агенту нужна установка пакета во время выполнения, изменяемое окружение, экспериментальные инструменты

Чтобы включить режим контейнера, введите одну строку:

{
  services.hermes-agent = {
    enable = true;
    container.enable = true;
    #... остальная конфигурация идентична
  };
}
```:::информация
Режим контейнера автоматически включает `virtualisation.docker.enable` через `mkDefault`. Если вы используете Podman, установите `container.backend = "podman"` и `virtualisation.docker.enable = false`.</div>
---

## Конфигурация

### Декларативные настройки

Опция `settings` производит произвольный attrset, который преобразуется в `config.yaml`. Она поддерживает более глубокое слияние между несколькими определениями модулей (через `lib.recursiveUpdate`), так что вы можете просмотреть конфигурацию по файлам:
```nix
# base.nix
services.hermes-agent.settings = {
  model.default = "anthropic/claude-sonnet-4";
  toolsets = [ "all" ];
  terminal = { backend = "local"; timeout = 180; };
};

# personality.nix
services.hermes-agent.settings = {
  display = { compact = false; personality = "kawaii"; };
  memory = { memory_enabled = true; user_profile_enabled = true; };
};

Оба глубоко сливаются во время оценки. Ключи, объявленные в Nix, всегда побеждают ключи в существующем config.yaml на диске, но ключи, добавленные пользователем, которых Nix не трогает, очередь. Это означает, что если агент или ручное редактирование добавляет ключи, такие как skills.disabled или streaming.enabled, они переносят nixos-rebuild switch.:::Примечание Именование моделей settings.model.default использует идентификатор модели, который ожидает ваш провайдер. С OpenRouter (по умолчанию) они выглядят как "anthropic/claude-sonnet-4" или "google/gemini-3-flash". Если вы используете провайдера напрямую (Anthropic, OpenAI), установите settings.model.base_url, чтобы указать их API, и подтвердите их собственные идентификаторы моделей (например, `claude-sonnet-4-20250514'). Если base_url не установлен, Hermes по умолчанию использует OpenRouter.:::

💡 Tip

Обнаружение доступных ключей конфигурации Запустите nix build.#configKeys && cat result, чтобы увидеть каждый файл с ключом конфигурации, полученным из Python DEFAULT_CONFIG. Вы можете вставить существующий config.yaml в attrset settings — структура отображается 1:1.
<подробности>

Полный пример: часто настраиваемые параметры
{ config,... }: {
  services.hermes-agent = {
    enable = true;
    container.enable = true;

    # ── Модель ──────────────────────────────────────────────────────────
    settings = {
      model = {
        base_url = "https://openrouter.ai/api/v1";
        default = "anthropic/claude-opus-4.6";
      };
      toolsets = [ "all" ];
      max_turns = 100;
      terminal = { backend = "local"; cwd = "."; timeout = 180; };
      compression = {
        enabled = true;
        threshold = 0.85;
        summary_model = "google/gemini-3-flash-preview";
      };
      memory = { memory_enabled = true; user_profile_enabled = true; };
      display = { compact = false; personality = "kawaii"; };
      agent = { max_turns = 60; verbose = false; };
    };

    # ── Секреты ────────────────────────────────────────────────────────
    environmentFiles = [ config.sops.secrets."hermes-env".path ];

    # ── Документы ──────────────────────────────────────────────────────
    documents = {
      "USER.md" =./documents/USER.md;
    };

    # ── MCP-серверы ────────────────────────────────────────────────────
    mcpServers.filesystem = {
      command = "npx";
      args = [ "-y" "@modelcontextprotocol/server-filesystem" "/data/workspace" ];
    };

    # ── Опции контейнера ──────────────────────────────────────────────
    container = {
      image = "ubuntu:24.04";
      backend = "docker";
      hostUsers = [ "your-username" ];
      extraVolumes = [ "/home/user/projects:/projects:rw" ];
      extraOptions = [ "--gpus" "all" ];
    };

    # ── Настройка сервиса ─────────────────────────────────────────────────
    addToSystemPackages = true;
    extraArgs = [ "--verbose" ];
    restart = "always";
    restartSec = 5;
  };
}

</подробнее>

Запасной вариант: свой конфиг

Если вы предпочитаете управлять config.yaml полностью вне Nix, используйте configFile:

services.hermes-agent.configFile = /etc/hermes/config.yaml;

Это полностью обходит настройки — никаких слияний, никакой генерации. Файл копируется как есть в $HERMES_HOME/config.yaml при каждой активации.

Шпаргалка по настройке

Быстрая смена самых распространенных вещей, которые пользователи Nix хотят настроить:

Я хочу... Опция Пример
Изменить LLM-модель settings.model.default "антропный/Клод-сонет-4"
Использовать другого провайдера конечных точек settings.model.base_url "https://openrouter.ai/api/v1"
Добавить API-ключи environmentFiles [ config.sops.secrets."hermes-env".path ]
Дать агенту личность ${services.hermes-agent.stateDir}/.hermes/SOUL.md управляйте файлом напрямую
Добавить инструменты MCP-серверов mcpServers.<имя> См. MCP-серверы
Смонтировать хост-директории в контейнер container.extraVolumes [ "/data:/data:rw" ]
Передать доступ к графическому процессору в контейнер container.extraOptions [ "--gpus" "все" ]
Используйте Podman вместо Docker container.backend "подман"
Разделять состояние между хостом CLI и контейнером container.hostUsers [ "сидбин" ]
Сделать дополнительные инструменты доступным агенту дополнительные пакеты [ pkgs.pandoc pkgs.imagemagick ]
Используйте пользовательский базовый образ container.image "ubuntu:24.04"
Переопределить пакет Гермес пакет inputs.hermes-agent.packages.${system}.default.override {... }
Изменить директорию состояния stateDir "/opt/hermes"
Установить действующего директора агента рабочий каталог "/home/user/projects"

Управление секретами

🚨 Danger

Никогда не помещайте API-ключи в settings или environment

Значения в Nix-выражениях используются в /nix/store, которые доступны для чтения всем. Всегда используйте environmentFiles с менеджером секретов. environment (несекретные переменные) и environmentFiles (секретные файлы) объединяются в $HERMES_HOME/.env во время активации (nixos-rebuild переключатель). Гермес читает этот файл при каждом запуске, поэтому изменения вступают в силу после systemctl restart hermes-agent — без пересоздания контейнера.

сопс-никс

{
  sops = {
    defaultSopsFile =./secrets/hermes.yaml;
    age.keyFile = "/home/user/.config/sops/age/keys.txt";
    secrets."hermes-env" = { format = "yaml"; };
  };

  services.hermes-agent.environmentFiles = [
    config.sops.secrets."hermes-env".path
  ];
}

Файл секретов содержит пару ключей-значений:

# secrets/hermes.yaml (зашифрован с помощью sops)
hermes-env: |
    OPENROUTER_API_KEY=sk-or-...
    TELEGRAM_BOT_TOKEN=123456:ABC...
    ANTHROPIC_API_KEY=sk-ant-...

агеникс

{
  age.secrets.hermes-env.file =./secrets/hermes-env.age;

  services.hermes-agent.environmentFiles = [
    config.age.secrets.hermes-env.path
  ];
}

Начальное заполнение OAuth / Auth

Для платформ, требующих OAuth (например, Discord), используйте authFile для начального заполнения учетных данных при первом развертывании:

{
  services.hermes-agent = {
    authFile = config.sops.secrets."hermes/auth.json".path;
    # authFileForceOverwrite = true;  # перезаписывать при каждой активации
  };
}

Файл копируется только в том случае, если auth.json еще не существует (если только authFileForceOverwrite = true). Обновления OAuth-токенов во время выполнения параметра в директории состояния и определения между пересборками.


Документы

Опция documents устанавливает файлы в директорию рабочего агента ("workingDirectory", агент читает как свое игровое пространство). Hermes ищет оригинальные имена файлов по соглашению:

Файл идентичности агента отдельного: Hermes загружает свой основной SOUL.md из $HERMES_HOME/SOUL.md, который в модуле NixOS находится в ${services.hermes-agent.stateDir}/.hermes/SOUL.md. Помещение SOUL.md в documents создает только файл рабочего пространства и не заменяет основной файл личности.

{
  services.hermes-agent.documents = {
    "USER.md" =./documents/USER.md;  # ссылка на путь, копируется из Nix store
  };
}

Значения могут быть связаны строками или ссылками на пути. Файлы прилагаются к каждому nixos-rebuild switch.


MCP-серверы

Опция mcpServers декларативно настраивает MCP (Model Context Protocol) серверы. Каждый сервер использует либо stdio (локальную команду), либо HTTP (удаленный URL-адрес).

Стдио-транспорт (локальные серверы)

{
  services.hermes-agent.mcpServers = {
    filesystem = {
      command = "npx";
      args = [ "-y" "@modelcontextprotocol/server-filesystem" "/data/workspace" ];
    };
    github = {
      command = "npx";
      args = [ "-y" "@modelcontextprotocol/server-github" ];
      env.GITHUB_PERSONAL_ACCESS_TOKEN = "\${GITHUB_TOKEN}"; # разрешается из.env
    };
  };
}
```:::совет
Переменные окружения в значениях `env` разрешаются из `$HERMES_HOME/.env` во время выполнения. Используйте `environmentFiles` для создания секретов  никогда не размещайте токены непосредственно в конфигурации Nix.</div>
### HTTP-транспорт (удаленные серверы)
```nix
{
  services.hermes-agent.mcpServers.remote-api = {
    url = "https://mcp.example.com/v1/mcp";
    headers.Authorization = "Bearer \${MCP_REMOTE_API_KEY}";
    timeout = 180;
  };
}

HTTP-транспорт с OAuth

Установите auth = "oauth" для серверов, использующих OAuth 2.1. Hermes реализовал полный PKCE-поток — обнаружение метаданных, динамическую регистрацию клиента, обмен токенами и дешевое обновление.

{
  services.hermes-agent.mcpServers.my-oauth-server = {
    url = "https://mcp.example.com/mcp";
    auth = "oauth";
  };
}

Токены хранятся в $HERMES_HOME/mcp-tokens/<имя-сервера>.json и располагаются между перезапусками и пересборками.

<подробности>

Первоначальная авторизация OAuth на headless-серверах

Первая авторизация OAuth требует согласования через браузер. При безголовом развертывании Hermes выводит URL-адрес авторизации в стандартный вывод/логики вместо открытия браузера.

Вариант A: Интерактивная начальная загрузка — выполнить поток один раз через docker exec (контейнер) или sudo -u hermes (родной):

# Режим контейнера
docker exec -it hermes-agent \
  hermes mcp add my-oauth-server --url https://mcp.example.com/mcp --auth oauth

# Нативный режим
sudo -u hermes HERMES_HOME=/var/lib/hermes/.hermes \
  hermes mcp add my-oauth-server --url https://mcp.example.com/mcp --auth oauth

Контейнер использует --network=host, поэтому прослушиватель OAuth-колбэка на 127.0.0.1 доступен из браузера хоста.

Вариант Б: Предварительное заполнение токенов — завершите поток на рабочей станции, затем скопируйте токены:

hermes mcp add my-oauth-server --url https://mcp.example.com/mcp --auth oauth
scp ~/.hermes/mcp-tokens/my-oauth-server{,.client}.json \
    server:/var/lib/hermes/.hermes/mcp-tokens/
# Убедитесь: chown hermes:hermes, chmod 0600

</подробнее>

Сэмплинг (инициированные сервером LLM-запросы)

Некоторые MCP-серверы могут запросить LLM-завершения у агента:

{
  services.hermes-agent.mcpServers.analysis = {
    command = "npx";
    args = [ "-y" "analysis-server" ];
    sampling = {
      enabled = true;
      model = "google/gemini-3-flash";
      max_tokens_cap = 4096;
      timeout = 30;
      max_rpm = 10;
    };
  };
}

Управляемый режим

Когда Hermes работает через модуль NixOS, следующие CLI-команды заблокируются с описательной ошибкой, указывающей на configuration.nix:

Заблокированная команда Почему
настройка Гермеса Конфигурация декларативная — отредактируйте настройки в вашей Nix-конфигурации
редактирование конфигурации Гермеса Конфигурация последовательно из settings
набор конфигурации Hermes <ключ> <значение> Конфигурация последовательно из settings
установка шлюза Гермес systemd-сервис управляется NixOS
удаление шлюза Гермеса systemd-сервис управляется NixOS

Это свое перемещение между тем, что объявляет Никс, и тем, что находится на диске. Обнаружение использует два сигнала:

  1. Переменная окружения HERMES_MANAGED=true — устанавливается systemd-сервисом, вид на шлюз процесса
  2. Файл-маркер .managed в HERMES_HOME — настроенный скриптом активации, видимый интерактивным включениям (например, docker exec -it hermes-agent hermes config set... также заблокирован)

Чтобы изменить конфигурацию, отредактируйте вашу Nix-конфигурацию и выполните sudo nixos-rebuild switch.


Архитектура контейнера:::информация

Этот раздел актуален только в том случае, если вы используете container.enable = true. Пропустите его для развертывания в собственном режиме. Когда режим контейнера включен, Hermes работает внутри постоянного контейнера Ubuntu с Nix-собранным бинарником, смонтированным только для чтения хоста:

Хост                                    Контейнер
────                                    ─────────
/nix/store/...-hermes-agent-0.1.0  ──►  /nix/store/... (ro)
~/.hermes -> /var/lib/hermes/.hermes       (симлинк-мост, для каждого hostUsers)
/var/lib/hermes/                    ──►  /data/          (rw)
  ├── current-package -> /nix/store/...    (симлинк, обновляется при каждой пересборке)
  ├──.gc-root -> /nix/store/...           (предотвращает nix-collect-garbage)
  ├──.container-identity                  (sha256 хэш, вызывает пересоздание)
  ├──.hermes/                             (HERMES_HOME)
     ├──.env                             (объединено из environment + environmentFiles)
     ├── config.yaml                      (сгенерировано Nix, глубокое слияние при активации)
     ├──.managed                         (файл-маркер)
     ├──.container-mode                  (метаданные маршрутизации: backend, exec_user и т.д.)
     ├── state.db, sessions/, memories/   (состояние выполнения)
     └── mcp-tokens/                      (OAuth-токены для MCP-серверов)
  ├── home/                                ──►  /home/hermes    (rw)
  └── workspace/                           (MESSAGING_CWD)
      ├── SOUL.md                          (из опции documents)
      └── (файлы, созданные агентом)

Записываемый слой контейнера (apt/pip/npm):   /usr, /usr/local, /tmp

Nix-собранный бинарник работает внутри контейнера Ubuntu, потому что /nix/store смонтирован — он порождает свой собственный интерпретатор и все зависит, поэтому не зависит от контейнера системных библиотек. Точка входа в контейнер разрешается через симлинк current-package: /data/current-package/bin/hermesgateway run --replace. При nixos-rebuild switch обновляется только симлинк — контейнер продолжает работать.

Что сохраняется при каких-либо событиях

Событие Контейнер пересоздается? /data (состояние) /домой/гермес Записываемый слой (apt/pip/npm)
systemctl перезапустите агент Гермеса Нет Сохраняется Сохраняется Сохраняется
nixos-rebuild switch (изменение кода) Нет (симлинк обновлен) Сохраняется Сохраняется Сохраняется
Перезагрузка хоста Нет Сохраняется Сохраняется Сохраняется
nix-сбор мусора Нет (корень GC) Сохраняется Сохраняется Сохраняется
Изменение образа (container.image) Да Сохраняется Сохраняется Потерян
Изменение томов/опций Да Сохраняется Сохраняется Потерян
Изменение environment/environmentFiles Нет Сохраняется Сохраняется Сохраняется

Контейнер пересоздается только при хранении его идентификационного хэша. Хэш раскрывает: версию схемы, образ, extraVolumes, extraOptions и скрипт точки входа. Изменения окружения, настроек, документов или самого пакета Hermes не вызывает пересоздание.:::предупреждение Потеря записываемого слоя Когда определяющий хэш меняется (обновление образа, новый том, новые опции контейнера), контейнер уничтожается и пересоздается из свежего образа container.image. Любые пакеты apt install, pip install или npm install в записываемом состоянии требуются. Состояние в /data и /home/hermes сохраняется (это привязка-монтирования).

Если агент подает на установку пакетов, рассмотрите возможность встраивания их в пользовательский образ (container.image = "my-registry/hermes-base:latest") или скриптования их установки в агенте SOUL.md.

Защита GC Root

Скрипт preStart создает корень GC в ${stateDir}/.gc-root, указывающий на текущий пакет hermes. Это собственное удаление работающего бинарника команды nix-collect-garbage. Если корень GC по какой-то причине сломается, перезапустите его в сервисном центре.


Плагины

Модуль NixOS поддерживает декларативную установку плагинов — без необходимости обязательной установки плагинов Hermes.

Директорийные плагины (extraPlugins)

Для плагинов, которые представляют собой просто исходники дерева с plugin.yaml + __init__.py (например, hermes-lcm):

services.hermes-agent.extraPlugins = [
  (pkgs.fetchFromGitHub {
    owner = "stephenschoettler";
    repo = "hermes-lcm";
    rev = "v0.7.0";
    hash = "sha256-...";
  })
];

Плагины симлинкуются в $HERMES_HOME/plugins/ во время активации. Гермес обнаруживает их с помощью обычных директорий сканирования. Удаление плагина из списка и выполнение nixos-rebuild switch удаление симлинка.

Плагины с точкой входа (extraPythonPackages)

Для плагинов pip-пакетов, которые регистрируются через [project.entry-points."hermes_agent.plugins"] (например, rtk-hermes):

services.hermes-agent.extraPythonPackages = [
  (pkgs.python312Packages.buildPythonPackage {
    pname = "rtk-hermes";
    version = "1.0.0";
    src = pkgs.fetchFromGitHub {
      owner = "ogallotti";
      repo = "rtk-hermes";
      rev = "v1.0.0";
      hash = "sha256-...";
    };
    format = "pyproject";
    build-system = [ pkgs.python312Packages.setuptools ];
  })
];

Пакет site-packages добавляется в PYTHONPATH в обертке Hermes. importlib.metadata обнаруживает точку входа при запуске сессии.

Опциональные группы зависимостей (extraDependencyGroups)

Для дополнительных опций, уже объявленных в pyproject.toml, hermes-agent (например, провайдеров памяти, таких как hindsight или honcho), используйте extraDependencyGroups, чтобы включить их в изолированный венв во время сборки:

services.hermes-agent = {
  extraDependencyGroups = [ "hindsight" ];
  settings.memory.provider = "hindsight";
};

Это разрешено uv вместе с возможными зависимостями за один проход — без патчинга PYTHONPATH, без критериев риска. Доступные группы соответствуют ключам [project.optional-dependents] в pyproject.toml (например, "hindsight","honcho", "voice","matrix", "mistral","bedrock"`).

Когда что использовать:

Нужно Опция
Включить дополнительное дополнение из pyproject.toml extraDependencyGroups
Добавить внешний Python-плагин, отсутствующий в pyproject.toml extraPythonPackages
Добавить системный бинарник (pandoc, jq и т.д.) дополнительные пакеты
Добавить дерево исходников каталога дополнительные плагины

Комбинирование верхних этажей

Директорический плагин с сторонней зависимостью от Python требует наличия опций:

services.hermes-agent = {
  extraPlugins = [ my-plugin-src ];          # исходник плагина
  extraPythonPackages = [ pkgs.python312Packages.redis ];  # его Python-зависимость
  extraPackages = [ pkgs.redis ];            # системный бинарник, который ему нужен
};

Использование наложения

Внешние хлопья могут переопределить пакет напрямую:

{
  inputs.hermes-agent.url = "github:NousResearch/hermes-agent";
  outputs = { hermes-agent, nixpkgs,... }: {
    nixpkgs.overlays = [ hermes-agent.overlays.default ];
    # Затем:
    #   pkgs.hermes-agent.override { extraPythonPackages = [...]; }
    #   pkgs.hermes-agent.override { extraDependencyGroups = [ "hindsight" ]; }
  };
}

Конфигурация плагинов

Плагины все еще необходимо включить в config.yaml. Добавьте их через декларативные настройки:

services.hermes-agent.settings.plugins.enabled = [
  "hermes-lcm"
  "rtk-rewrite"
];
```:::примечание
Проверка конфликтов во время сборки зеленого переопределения пакетов плагинов основных зависимостей Гермеса. Если плагин предоставляет пакет, уже находящийся в изолированном венве, `nixos-rebuild` завершится с явной ошибкой.</div>
---

## Разработка

### Оболочка для разработчиков

Flake предоставляет оболочку для разработки с Python 3.12, uv, Node.js и всеми инструментами времени выполнения:
```bash
cd hermes-agent
nix develop

# Оболочка предоставляет:
#   - Python 3.12 + uv (зависимости устанавливаются в.venv при первом входе)
#   - Node.js 22, ripgrep, git, openssh, ffmpeg в PATH
#   - Оптимизация stamp-файла: повторный вход почти мгновенный, если зависимости не изменились

hermes setup
hermes chat

direnv (рекомендуется)

Включенный .envrc автоматически активирует оболочку разработчика:

cd hermes-agent
direnv allow    # однократно
# Последующие входы почти мгновенны (stamp-файл пропускает установку зависимостей)

Проверки Flake

Flake включает проверки времени сборки, которые выполняются в CI и локально:

# Запустить все проверки
nix flake check

# Отдельные проверки
nix build.#checks.x86_64-linux.package-contents   # бинарники существуют + версия
nix build.#checks.x86_64-linux.entry-points-sync  # синхронизация pyproject.toml ↔ Nix-пакет
nix build.#checks.x86_64-linux.cli-commands        # подкоманды gateway/config
nix build.#checks.x86_64-linux.managed-guard       # HERMES_MANAGED блокирует мутации
nix build.#checks.x86_64-linux.bundled-skills      # навыки присутствуют в пакете
nix build.#checks.x86_64-linux.config-roundtrip    # скрипт слияния сохраняет пользовательские ключи
Что проверяет каждая проверка | Проверка | Что тестирует | |---|---| | `package-contents` | Бинарники `hermes` и `hermes-agent` существуют, и `hermes version` выполняется | | `entry-points-sync` | Каждая запись `[project.scripts]` в `pyproject.toml` имеет обернутый бинарник в Nix-пакете | | `cli-commands` | `hermes --help` показывает подкоманды `gateway` и `config` | | `managed-guard` | `HERMES_MANAGED=true hermes config set...` выводит ошибку NixOS | | `bundled-skills` | Директория навыков существует, содержит файлы SKILL.md, `HERMES_BUNDLED_SKILLS` установлен в обертке | | `config-roundtrip` | 7 сценариев слияния: чистая установка, переопределение Nix, сохранение пользовательских ключей, смешанное слияние, аддитивное слияние MCP, вложенное глубокое слияние, идемпотентность |

Справочник опций

Основные

Опция Тип По умолчанию Описание
enable bool false Включить сервис hermes-agent
package package hermes-agent Используемый пакет hermes-agent
user str "hermes" Системный пользователь
group str "hermes" Системная группа
createUser bool true Автоматически создать пользователя/группу
stateDir str "/var/lib/hermes" Директория состояния (родительская для HERMES_HOME)
workingDirectory str "${stateDir}/workspace" Рабочая директория агента (MESSAGING_CWD)
addToSystemPackages bool false Добавить CLI hermes в системный PATH и установить HERMES_HOME общесистемно

Конфигурация

Опция Тип По умолчанию Описание
settings attrs (глубокое слияние) {} Декларативная конфигурация, преобразуемая в config.yaml. Поддерживает произвольную вложенность; несколько определений сливаются через lib.recursiveUpdate
configFile null или path null Путь к существующему config.yaml. Полностью переопределяет settings, если установлен

Секреты и окружение

Опция Тип По умолчанию Описание
environmentFiles listOf str [] Пути к env-файлам с секретами. Объединяются в $HERMES_HOME/.env во время активации
environment attrsOf str {} Несекретные переменные окружения. Видимы в Nix store — не помещайте сюда секреты
authFile null или path null Начальное заполнение OAuth-учетных данных. Копируется только при первом развертывании
authFileForceOverwrite bool false Всегда перезаписывать auth.json из authFile при активации

Документы

Опция Тип По умолчанию Описание
documents attrsOf (either str path) {} Файлы рабочего пространства. Ключи — имена файлов, значения — встроенные строки или пути. Устанавливаются в workingDirectory при активации

MCP-серверы

Опция Тип По умолчанию Описание
mcpServers attrsOf submodule {} Определения MCP-серверов, объединяются в settings.mcp_servers
mcpServers.<name>.command null или str null Команда сервера (stdio-транспорт)
mcpServers.<name>.args listOf str [] Аргументы команды
mcpServers.<name>.env attrsOf str {} Переменные окружения для процесса сервера
mcpServers.<name>.url null или str null URL endpoint сервера (HTTP/StreamableHTTP-транспорт)
mcpServers.<name>.headers attrsOf str {} HTTP-заголовки, например Authorization
mcpServers.<name>.auth null или "oauth" null Метод аутентификации. "oauth" включает OAuth 2.1 PKCE
mcpServers.<name>.enabled bool true Включить или отключить этот сервер
mcpServers.<name>.timeout null или int null Таймаут вызова инструмента в секундах (по умолчанию: 120)
mcpServers.<name>.connect_timeout null или int null Таймаут подключения в секундах (по умолчанию: 60)
mcpServers.<name>.tools null или submodule null Фильтрация инструментов (списки include/exclude)
mcpServers.<name>.sampling null или submodule null Конфигурация сэмплинга для инициированных сервером LLM-запросов

Поведение сервиса

Опция Тип По умолчанию Описание
extraArgs listOf str [] Дополнительные аргументы для hermes gateway
extraPackages listOf package [] Дополнительные пакеты, доступные агенту. Добавляются в профиль пользователя hermes, так что терминальные команды, навыки и cron-задания видят их
extraPlugins listOf package [] Пакеты директорийных плагинов для симлинкования в $HERMES_HOME/plugins/. Каждый должен содержать plugin.yaml
extraPythonPackages listOf package [] Python-пакеты, добавляемые в PYTHONPATH для обнаружения плагинов с точкой входа. Собирайте с помощью python312Packages
extraDependencyGroups listOf str [] Опциональные экстра из pyproject.toml для включения в изолированный venv (например, ["hindsight"]). Разрешаются uv — без конфликтов
restart str "always" Политика systemd Restart=
restartSec int 5 Значение systemd RestartSec=

Контейнер

Опция Тип По умолчанию Описание
container.enable bool false Включить режим OCI-контейнера
container.backend enum ["docker" "podman"] "docker" Контейнерный runtime
container.image str "ubuntu:24.04" Базовый образ (загружается во время выполнения)
container.extraVolumes listOf str [] Дополнительные монтирования томов (host:container:mode)
container.extraOptions listOf str [] Дополнительные аргументы, передаваемые в docker create
container.hostUsers listOf str [] Интерактивные пользователи, которые получают симлинк ~/.hermes на stateDir сервиса и автоматически добавляются в группу hermes

Структура директорий

Нативный режим

/var/lib/hermes/                     # stateDir (принадлежит hermes:hermes, 0750)
├──.hermes/                         # HERMES_HOME
   ├── config.yaml                  # Сгенерировано Nix (глубокое слияние при каждой пересборке)
   ├──.managed                     # Маркер: мутация CLI-конфига заблокирована
   ├──.env                         # Объединено из environment + environmentFiles
   ├── auth.json                    # OAuth-учетные данные (начальное заполнение, затем самоуправление)
   ├── gateway.pid
   ├── state.db
   ├── mcp-tokens/                  # OAuth-токены для MCP-серверов
   ├── sessions/
   ├── memories/
   ├── skills/
   ├── cron/
   └── logs/
├── home/                            # HOME агента
└── workspace/                       # MESSAGING_CWD
    ├── SOUL.md                      # Из опции documents
    └── (файлы, созданные агентом)

Режим контейнера

Та же конструкция, смонтирована в контейнере:

Положить в контейнер Путь на хосте Режим Примечания
/nix/store /nix/store ро Бинарник Hermes + все Nix-зависимости
/данные /var/lib/hermes рв Всё состояние, конфиг, рабочее пространство
/домой/гермес ${stateDir}/home рв Постоянный HOME агент — pip install --user, кэши инструменты
/usr, /usr/local, /tmp (записываемый слой) рв Установки apt/pip/npm — приоритет между перезапусками, требуется при пересоздании

Обновление

# Обновить flake input (запускать из директории, содержащей flake.nix)
cd /etc/nixos && nix flake update hermes-agent

# Пересобрать
sudo nixos-rebuild switch

В режиме контейнера симлинк current-package обновляется, и агент подхватывает новый бинарник при перезапуске. Без пересоздания контейнера, без потери стандартной упаковки.


Устранение неполадок:::совет Пользователи Подман

Все команды «докера» ниже работают так же с «подманом». Замените соответствующим образом, если вы установили container.backend = "podman".

Логи сервис

# Оба режима используют один и тот же systemd-юнит
journalctl -u hermes-agent -f

# Режим контейнера: также доступно напрямую
docker logs -f hermes-agent

Инспекция контейнера

systemctl status hermes-agent
docker ps -a --filter name=hermes-agent
docker inspect hermes-agent --format='{{.State.Status}}'
docker exec -it hermes-agent bash
docker exec hermes-agent readlink /data/current-package
docker exec hermes-agent cat /data/.container-identity

Принудительное пересоздание контейнера

Если вам нужно удалить записываемый слой (свежая Ubuntu):

sudo systemctl stop hermes-agent
docker rm -f hermes-agent
sudo rm /var/lib/hermes/.container-identity
sudo systemctl start hermes-agent

Проверка секретов

Если агент запускается, но не может аутентифицироваться с LLM-провайдером, проверьте, что файл .env был объединен правильно:

# Нативный режим
sudo -u hermes cat /var/lib/hermes/.hermes/.env

# Режим контейнера
docker exec hermes-agent cat /data/.hermes/.env

Проверка корня GC

nix-store --query --roots $(docker exec hermes-agent readlink /data/current-package)

Частные проблемы

Симптом Причина Исправление
Невозможно сохранить конфигурацию: управляется NixOS Активны CLI-защиты Отредактируйте configuration.nix и выполните nixos-rebuild switch
Контейнер пересоздан неожиданно Изменились extraVolumes, extraOptions или image Ожидаемо — сбрасывается записываемый слой. Переустановите пакеты или воспользуйтесь пользовательским образом
версия Гермеса показывает старую версию Контейнер не перезапущен systemctl перезапустите агент Гермеса
Отказано в доступе к /var/lib/hermes Директория состояния имеет права 0750 Гермес:Гермес Используйте docker exec или sudo -u hermes
nix-collect-garbage удалил Гермес Отсутствует корень GC Перезапустите сервис (preStart в регионе GC root)
нет контейнера с именем или идентификатором "гермес-агент" (Подман) Rootful-контейнер Podman не виден обычному пользователю Добавьте sudo без пароля для podman (см. раздел Режим контейнера)
невозможно найти пользователя Hermes Контейнер еще запускается (точка входа еще не создана пользователем) Подождите несколько секунд и повторите — CLI повторяет автоматически
Инструмент, добавленный через extraPackages, не найден в терминале Требуется nixos-rebuild switch для обновления профиля пользователя Пересоберите и перезапустите: nixos-rebuild switch && systemctl restart hermes-agent