Files
knowledge-base/decisions/2026-06-18-german-hermes-agent-deploy.md

7.5 KiB
Raw Blame History

date, tags
date tags
2026-06-18
decision
ai
hermes
telegram
lxc
assistant

German — Hermes Agent как личный супер-ассистент Олега (LXC 141)

Контекст

Олег попросил поставить Hermes Agent (NousResearch, open-source, MIT, Python, model-agnostic — из ресёрча ../notes/claude/2026-06-08-145004-найди-аналог-openclaw-для-меня-нужен-аркестратор-и) на homelab. Сначала — «для тестирования самого Hermes через Telegram», затем расширил: настроить как супер-помощника с полным доступом к базе знаний. Имя — Герман (German).

Что развёрнуто

  • LXC 141 german (10.0.0.141, Debian 12, 2 vCPU / 3 GB / 12 GB на local-lvm, nesting, unprivileged, onboot=1). Создан из debian-12-standard 12.12.
  • Hermes Agent v0.16.0 — установлен официальным install.sh --non-interactive --skip-setup. Код /usr/local/lib/hermes-agent, данные /root/.hermes (uv + managed Node).
  • Telegram-бот «Герман Непомнящий» @german_dttb_bot (id 8885932329). Gateway = systemd hermes-german.service (hermes gateway run --replace, Restart=always, drain 210s, crash-guard, NoNewPrivileges/PrivateTmp).

Модель

  • Провайдер OmniRoute (OpenAI-совместимый шлюз на LXC 132): base_url http://10.0.0.179:20128/v1, модель cc/claude-opus-4-8 (Opus 4.8 через Max-подписку Олега).
  • Ключ — OPENAI_API_KEY + OPENAI_BASE_URL в /root/.hermes/.env (chmod 600).
  • auxiliary (vision/web_extract/compression/session_search) → provider: main — иначе лезли бы в OpenRouter (ключа нет) и падали.
  • ⚠️ Грабля для будущего: оба воркфлоу-ревьюера по коду утверждали, что на приватный IP-эндпоинт OPENAI_API_KEY из env «гейтится по хосту» и нужен model.api_key: ${OPENAI_API_KEY} в config.yaml, иначе 401. Эмпирически опровергнуто — CLI- и gateway-вызовы к 10.0.0.179 проходят с env-ключом без model.api_key. Если когда-нибудь начнёт давать 401 на первом вызове модели — добавить api_key: ${OPENAI_API_KEY} в секцию model: и systemctl restart hermes-german.

База знаний (KB)

  • Зеркало vault клонировано в /root/german/knowledge-base (workspace = /root/german, systemd WorkingDirectory).
  • Обновление: /root/kb-pull.sh (cron */15) делает git fetch + git reset --hard origin/main — это read-only зеркало (правки агента там затираются; для своих заметок у него /root/german/notes + native memory).
  • Безопасность кред: из .git/config workspace убран токен Gitea (был https://oleg:TOKEN@...); remote сделан tokenless, креды вынесены в /root/.git-credentials (chmod 600, вне workspace).
  • Доступ Германа к KB: тулсеты file (read_file/grep) + terminal. Семантического индекса нет — навигация через knowledge-base/CLAUDE.md → grep. Это прописано в SOUL.md.

Конфиг (ключевое, /root/.hermes/config.yaml, 600)

  • platform_toolsets.telegramявный список [web, terminal, file, memory, todo, skills, session_search, tts] (+ kanban по дефолту).
  • Почему не пресет hermes-telegram: security-ревью (читало toolsets.py:440) показало, что пресет тянет полный core-набор (browser, execute_code, computer_use), а disabled_toolsets их НЕ убирает (категории — web/browser/terminal/code_execution/image_gen). Для бота с доступом к секретам это лишние каналы исхода. Проверено hermes tools --summary: на Telegram 9/26 тулов, browser/code-exec/computer-use отсутствуют.
  • web-поиск без ключей: web.backend: ddgs (DuckDuckGo, бесплатно). Browser недоступен (требует BROWSERBASE_API_KEY) — веб через ddgs + curl в terminal.
  • SOUL.md (личность «Герман», навигация по KB, правила безопасности) — 600.
  • Прочее: display.language: ru, session_reset: idle 2880m, memory_enabled, security.redact_secrets: true + tirith_enabled: true, stt (faster-whisper base — голосовые транскрибируются).

Безопасность — модель угроз

  • Доступ только у Олега: TELEGRAM_ALLOWED_USERS=1292155421, guest_mode: false, unauthorized_dm_behavior: ignore. Проверено по коду (telegram.py/authz_mixin.py): пустой allowlist = deny-all, fail-closed. Чужие сообщения молча игнорируются.
  • terminal=local + root = Герман может выполнять любой bash на 141 и читать секреты из KB. Это намеренно (DevOps-ассистент), защита держится на allowlist. Жёсткий systemd-сэндбокс (ProtectSystem/ProtectHome) не ставил — сломал бы функции. Будущее ужесточение: отдельный непривилегированный юзер.
  • redact_secrets: true — секреты вычищаются из tool output/логов/ответов перед доставкой.

Эксплуатация

  • Статус/логи: systemctl status hermes-german; логи в файлах /root/.hermes/logs/{gateway,agent}.log (не в journal).
  • Рестарт после правок config/SOUL: systemctl restart hermes-german (дренаж до ~180с).
  • Бэкапы конфигов: /root/.hermes/config.yaml.bak.*, .env.bak.orig.
  • Эндпоинт-санити: curl -s http://10.0.0.179:20128/v1/models (должен отдавать cc/claude-opus-4-8).

Проверено

  • Установка, конфиг грузится, hermes status → Model cc/claude-opus-4-8 / Custom endpoint.
  • End-to-end CLI: вопрос по KB → grep → верный ответ (IP openclaw 10.0.0.239).
  • Прямой вызов OmniRoute cc/claude-opus-4-8 (стрим).
  • Gateway: ✓ telegram connected (polling), getMe ok, allowlist на Олега.
  • Тулсет Telegram безопасен (без browser/code-exec/computer-use).
  • Финальный gateway-раунд-трип подтверждается первым реальным сообщением Олега боту.

TODO / на будущее

  • Fallback-цепочка (cc/sonnet-4-6, kr/sonnet-4.5, cx/gpt-5.4) — формат fallback_providers с api_key_env (НЕ ${VAR} — путь резолва фолбэков не делает env-подстановку). Пока не ставил (primary надёжен).
  • Настоящий web-search через self-hosted SearXNG (SEARXNG_URL) или ключ Tavily/Firecrawl — если ddgs будет мало.
  • Рассмотреть запуск под non-root юзером для уменьшения blast radius.