Секреты

Hermes умеет вытягивать API-ключи из внешних менеджеров секретов прямо на старте процесса — вместо того чтобы держать их в ~/.hermes/.env. В .env остаётся только bootstrap-токен самого менеджера. Все остальные ключи провайдеров (OpenAI, Anthropic, OpenRouter и так далее) живут в менеджере и ротируются централизованно. Для автономного ИИ-агента на своём сервере это удобно: один источник правды для учётных данных, а не россыпь ключей по конфигам.

Что поддерживается:

  • Bitwarden Secrets Manager — CLI bws, ставится по требованию, бесплатного тарифа хватает.
  • 1Password — ссылки op:// через официальный CLI op; авторизация сервис-аккаунтом или десктопной сессией.
  • Команда-хелпер — любое CLI-хранилище (keepassxc-cli, secret-tool, pass, самописный скрипт) через настроенную вами команду-хелпер, которая печатает строки KEY=VALUE.

Несколько источников одновременно

Можно включить сразу несколько источников секретов — например, командный проект в Bitwarden вместе с личным плагином-хранилищем. Источники сочетаются по каждой переменной окружения отдельно, по детерминированной лестнице приоритетов:

  1. По умолчанию побеждает ваш .env / шелл. Источник заменяет уже существующее значение только тогда, когда у него самого выставлен override_existing: true (у Bitwarden это true по умолчанию — чтобы работала централизованная ротация).
  2. Сопоставленные источники бьют массовые. Источник, где вы явно привязываете переменные окружения к ссылкам (карта env:), обходит источник, который неявно вливает целый проект секретов, — независимо от порядка.
  3. Первый заявивший побеждает. Внутри одной формы порядок решает необязательный список secrets.sources (или порядок регистрации). Повторная заявка на уже занятую переменную пропускается — с предупреждением при старте, а не молча.

override_existing никогда не позволяет одному источнику перезаписать переменную, уже занятую другим источником, и ни один источник не может перезаписать чужой bootstrap-токен (например, BWS_ACCESS_TOKEN).

secrets:
  sources: [bitwarden]     # необязательный явный порядок
  bitwarden:
    enabled: true
    project_id: "..."

У каждого значения, которое подставляет источник, отмечено происхождение — в мастерах настройки и в hermes model рядом с найденными ключами стоит пометка (from Bitwarden), так что всегда видно, откуда взялось значение.

Профили и общие хранилища

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

  • secrets.preserve_existing — список имён переменных окружения, чьё текущее значение из .env / шелла побеждает всегда, даже против источника с override_existing: true. Пригодится для секретов конкретного профиля (например, FEISHU_APP_SECRET), которые намеренно различаются между профилями, пока всё остальное ротируется централизованно:

    secrets:
      preserve_existing: [FEISHU_APP_SECRET, TELEGRAM_BOT_TOKEN]
  • Алиасинг профилей (включён по умолчанию, отключается через secrets.profile_alias: false) — когда Hermes запущен под именованным профилем, секрет хранилища с именем FOO_<PROFILE> (только для суффиксов вида учётных данных: *_API_KEY, *_TOKEN, *_SECRET, *_KEY, *_PASSWORD) заодно наполняет и каноническое имя FOO. Положите TELEGRAM_BOT_TOKEN_MILLA в общий проект — и адаптеры профиля milla, которые читают фиксированное имя TELEGRAM_BOT_TOKEN, автоматически получат нужное значение. Переменная, которую хранилище отдаёт напрямую под каноническим именем, всегда побеждает алиас.

Оба флага действуют для любого источника — и встроенного, и плагина, — потому что живут в оркестраторе, а не в бэкендах.

Секреты в дочерних процессах

Терминальные команды, песочницы execute_code и скрипты cron-задач no_agent запускаются с очищенным окружением: учётные данные, которыми управляет Hermes, вырезаются, а пробрасываются только переменные, объявленные в terminal.env_passthrough (или в required_environment_variables загруженного навыка). Объявленная переменная пробрасывается со значением профиля-владельца — из .env этого профиля или его источников секретов, — даже если профиль обслуживается мультипрофильным шлюзом или бэкендом десктопа/дашборда и его секреты никогда не попадали в окружение процесса. Объявленное значение одного профиля никогда не доходит до дочерних процессов другого, а учётные данные из .env профиля запуска выбрасываются из дочерних процессов, которые работают для обслуживаемого профиля. Учётные данные провайдеров объявить нельзя; см. Безопасность → Область действия учётных данных.

Свой бэкенд

Сторонние менеджеры секретов поставляются отдельными плагинами, а не PR в ядро. Бэкенд наследует agent.secret_sources.base.SecretSource (обязателен один метод: fetch(cfg, home_path) -> FetchResult) и регистрируется через ctx.register_secret_source(MySource()) в register(ctx) плагина. Оркестратор берёт на себя приоритеты, разрешение конфликтов, тайм-ауты и происхождение — источник только получает значения. Полный гайд с правилами контракта, хелпером безопасности подпроцессов и набором тестов на соответствие: Плагины источников секретов.

Встроенный набор закрыт намеренно (та же политика, что и у провайдеров памяти): Bitwarden и 1Password идут в комплекте. Всё остальное — Infisical, Proton Pass, HashiCorp Vault, AWS Secrets Manager, системные keystore — оформляется как плагин-репозиторий; делитесь им в Discord Nous Research (#plugins-skills-and-skins).

перевод и редактура:

обновлено

⌕ ESC