# Как мы ставим и держим Hermes Agent

Инструкция для агентов (Claude Code, Codex, Grok и других) и для людей: сотрудников, учеников, друзей.
Здесь только принципы и порядок действий — без адресов, ключей и паролей.
Это живой документ: его дописывают агенты, которые наступили на новые грабли.

**Агенту:** прочитай целиком до того, как что-то трогать. Если у тебя есть SSH-доступ владельца,
у этой инструкции есть приватная часть с конкретными адресами и командами — попроси у владельца
команду, которой она читается.

---

## 1. Что такое Hermes Agent

Open-source агент от Nous Research (MIT): живёт на сервере 24/7, общается через Telegram,
WhatsApp и другие каналы, умеет терминал, браузер, файлы, задания по расписанию (cron),
навыки (skills) и память. Есть Hermes Desktop — приложение, которое подключается к агенту
на сервере. Код: github.com/NousResearch/hermes-agent, документация: hermes-agent.nousresearch.com.

## 2. Главные правила

1. **Версию проверяй снаружи.** Последний релиз смотри на странице Releases на GitHub, а не через
   `pip` внутри виртуального окружения. Наш агент просидел на старой версии четыре месяца, потому что
   pip в окружении на неподходящем Python «видел» старую версию последней.
2. **Ставь официальным способом, не через pip.** Установка через PyPI у авторов официально не
   поддерживается. Правильный путь — git-установка их установщиком, прибитая к релизному тегу.
3. **Ставь релиз, а не ветку `main`.** `hermes update` и установщик с сайта по умолчанию тянут `main` —
   это нерелизный код. Нам нужен конкретный тег.
4. **Агент живёт под отдельным пользователем, не под root.** Без sudo, без доступа к чужим домашним папкам,
   с лимитами CPU и памяти на сервис.
5. **Секреты — только в `.env` агента.** Никогда в файлы проекта, в чат, в логи и в отчёты.
   Смотреть можно только имена переменных. Осторожно с `ls` служебных папок: некоторые программы
   называют папки токенами.
6. **Свои правки движка — только патч-файлами.** Не правь код прямо в установке: при обновлении
   правки молча пропадут. Каждая правка — отдельный `.patch` в проекте + скрипт, который их
   накатывает идемпотентно.
7. **Изменил настройку — запиши, что и зачем.** Через месяц иначе не восстановить, почему стоит именно так.
8. **Не ограничивай агента молча.** Ограничение ставится, только если можешь объяснить, от чего оно
   защищает, и владелец об этом знает.
9. **Сначала посмотри, как решают другие.** Упёрся — поищи в issues, документации, обсуждениях,
   потом импровизируй.

## 3. Как обновлять (порядок, который работает)

1. Узнай последний релиз и его коммит на GitHub.
2. Подними **новую установку рядом со старой**, на **копии** домашней папки агента
   (базы копируй консистентным снимком SQLite backup API, а не `cp` по живому файлу).
3. Установщик бери **из самого тега** (`git show <коммит>:scripts/install.sh`), а не с сайта:
   свежий установщик рассчитан только на `main` и с релизом может упасть.
4. Запускай установщик с прибитым коммитом и **флагом принудительного отката** (`--commit <sha> --force-commit`):
   без него установщик молча переходит на `main`, если checkout «новее».
5. Запускай **без терминала** (`setsid … </dev/null`), не в tmux/screen: увидев терминал, установщик
   предложит «поставить gateway как сервис» с ответом «да» по умолчанию — и поднимет **второго бота
   на том же токене**.
6. На копии: `hermes config migrate`, `hermes doctor`, живой запрос `hermes -z '…'`, список кронов.
   **Gateway на копии не запускай** — два бота на одном токене подерутся.
7. Накати свои патчи. Проверь, какие из них авторы уже починили сами, — такие выбрось.
8. Прочитай, что поменяла миграция. Она может молча сбросить настройки (у нас сбросила характер агента).
9. Переключение: полный бэкап → остановка gateway → холодная копия домашней папки → миграция боевого
   конфига → сервис на новый движок → запуск. Держи готовый скрипт отката.
10. После запуска проверь руками каждый канал (сообщение, файл, скриншот с подписью), каждый крон
    и все скрипты, которые зовут бинарь агента по полному пути.

## 4. Грабли, на которые мы уже наступили

- **Миграция может молча игнорировать старые блоки конфига.** В новых версиях настройки каналов
  живут только в `platforms.<канал>` / `platforms.<канал>.extra`. Старый блок в корне конфига
  не читается и не переносится — у нас так пропало подключение к своему серверу Telegram Bot API.
- **Кроны теперь у каждого профиля свои.** Поле «профиль» у задания игнорируется, скрипт ищется
  только в папке скриптов своего профиля, симлинки наружу запрещены. Задания с чужими профилями
  нужно переносить в их собственный список.
- **Тайм-аут подключения канала по умолчанию 30 секунд.** Медленному WhatsApp из домашней сети
  не хватает — есть настройка `gateway.platform_connect_timeout`.
- **Обвязки, вызывающие бинарь агента по полному пути, ломаются после переезда.** Найди их все
  (grep по скриптам и юнитам) до переключения.
- **Проверяй флаги команд, а не верь коду.** У нас скрипт месяц звал `hermes send` с несуществующими
  флагами, ошибку глушил `except`, предупреждения не доходили ни разу.
- **Сеть до мессенджеров бывает закрыта не у агента, а у провайдера.** Прежде чем чинить агента,
  проверь `curl` до API мессенджера с той же машины. Если старая версия падала так же — дело в сети.
- **Медленный канал до GitHub** — клон репозитория может идти 20+ минут. Это нормально, не перезапускай.

## 5. Hermes Desktop

- Сервер для Desktop (`hermes serve`) слушает **только 127.0.0.1**. Наружу не открывать: он отдаёт ключи.
- С компьютера к нему ходят через **SSH-туннель** (`LocalForward 9119 127.0.0.1:9119`), туннель
  поднимается автоматически и переподключается после обрывов.
- В Desktop: Settings → Gateways → Remote gateway → `http://127.0.0.1:9119`. Локального агента
  на компьютер не ставить.

## 6. Как дописывать эту инструкцию

- Наткнулся на новую граблю или нашёл способ лучше — **допиши в раздел 4** (или в нужный раздел):
  что случилось, как распознать, как лечится. Коротко, без воды.
- **Ничего конкретного сюда:** ни адресов, ни портов, ни имён пользователей, ни путей к ключам,
  ни телефонов, ни токенов. Это уходит в приватную часть. Публикация автоматически останавливается,
  если в тексте найден похожий на секрет фрагмент.
- Нет доступа к исходнику — пришли владельцу текст правки.
