Files
obsidian-vault/personal/projects/personal-os/hermes-agent-improvements.md
T

23 KiB
Raw Blame History

Hermes Agent — Улучшения и Паттерны

Ref: personal-os-agent-rules

Agentic Memory Update

Как лучше обновлять доки/память агента из истории бесед.

Основные паттерны

1. Async post-session (доминирующий) — разделить живой чат и консолидацию памяти. После завершения сессии / по расписанию агент читает транскрипт, извлекает инсайты, пишет в canonical store. Никакой задержки в живом чате.

2. Three-memory model:

  • Episodic — история сессий (summary что обсуждали)
  • Semantic — факты, предпочтения, решения
  • Procedural — воркфлоу, скиллы, подходы

Чем запускают

  • Cron (2–4 AM) — самый простой и надёжный
  • Webhook после завершения сессии
  • LangMem ReflectionExecutor — фоновый тред прямо во время чата

Инструменты

Инструмент Плюсы Минусы
LangMem Нативная интеграция с LangGraph p95 latency = 60s в продакшне
Mem0 Граф с conflict detection, лучшая производительность Проприетарный
Custom agents Полный контроль, пишет в git/docs Надо делать самому

Eagle использует custom agents — текущий подход.

Главные правила

  1. Обрабатывать один раз в конце сессии, не после каждого сообщения
  2. Дешёвые модели для memory ops, дорогие — для разговора
  3. Guard: «обновлять только при значимой новой информации»
  4. Temporal decay — чтобы память не росла бесконечно

Пробелы в текущей системе

Vault root не обрабатывается

Файлы попадают в корень vault через мобильный sync (Obsidian iOS) — нет хэндлера.

  • vault-enrichment — не перемещает (запрещено в промпте)
  • inbox-sort — сканирует только staging-папки (family/sort/, personal/inbox/)

Fix: расширить inbox-sort, чтобы сканировал vault root и перемещал файлы по классификатору (food/recipes → family/documents/, etc.)

Нет renaming agent

Никто не переименовывает файлы. Мобильный sync создаёт файлы с произвольными именами, они остаются как есть.

Fix: добавить логику нормализации имён в inbox-sort или отдельный препроцессор.

Нет post-session memory agent

Сессии пишутся в ~/.hermes/sessions/, но memory.md и vault обновляются только вручную или через vault-enrichment (раз в неделю).

Fix: cron 02:00 AM ежедневно — читает свежие сессии, обновляет memory.md и personal/projects/. Вписывается в слот между inbox-sort (01:00) и vault-enrichment (03:00 вс).

Бэклог из обзора рынка ИИ-агентов (2026-09-02)

Полный разбор: ai-agent-landscape-2026. Вывод: смена фреймворка нецелесообразна (Hermes — #1 по объёму работы на OpenRouter в нише self-hosted перс.агента; альтернативы не перекрывают кастомизации). Из трендов, применимых к конфигу, растут следующие потенциальные улучшения (в порядке ценности):

  1. Event-driven проактивность поверх timer-driven cron — триггеры на изменение vault / новые файлы / сигналы, а не только по расписанию. Точка роста: сейчас проактивность только cron/watchdog.
  2. Confidence scoring + temporal decay для semantic-tier памяти — сейчас MEMORY.md overflow есть, но нет явного скоринга/устаревания фактов (паттерн Mem0/Letta/LangMem). Позже, кандидат на апгрейд semantic-tier сторонним движком (Letta/Mem0).
  3. Аудит скиллов до установки — урок из ClawHub supply-chain poisoning (341 вредоносный скилл) и CVE-2026-48710 (Hermes v0.16). Касается Skills Hub / установки сторонних скиллов.
  4. Модельная маршрутизация — самый дешёвый рычаг снижения токен-расхода (спред 100× между open-weight и фронтиром).

Статус каждого: не начато / потенциально — это research-findings, не подтверждённый план. Пересмотреть при планировании следующего спринта улучшений.


Вынос хардкода промптов в файлы

Статус: Реализовано (будет активно после перезапуска webhook)

Мотивация

В Hermes Whale все stable-блоки system prompt (identity, guidance, enforcement) были захардкожены в agent/prompt_builder.py как Python-константы. Невозможно изменить их без редактирования исходного кода Hermes Agent.

Решение

Вынести каждый блок в отдельный .md файл, добавить маппинг в config.yaml: agent.prompt_overrides, модифицировать agent/system_prompt.py, чтобы он читал файлы вместо констант.

Изменяемые файлы

1. agent/system_prompt.py — замена констант на file-load

Добавлена функция _load_prompt_block(agent, block_name, default_text) — строки 51-71 в /Users/admin/.hermes/hermes-agent/agent/system_prompt.py:

  • Читает agent._prompt_overrides (берётся из конфига на старте)
  • Если для block_name указан путь — читает файл, возвращает его содержимое
  • Иначе возвращает default_text

Заменены все 7 прямых ссылок на константы в build_system_prompt_parts() на вызовы _load_prompt_block().

Добавлены импорты: import logging, import os, from pathlib import Path, logger = logging.getLogger(__name__).

Константы, которые заменяются (7 блоков):

Блок Константа Вставляется при условии
hermes_help HERMES_AGENT_HELP_GUIDANCE всегда
task_completion TASK_COMPLETION_GUIDANCE всегда
memory_guidance MEMORY_GUIDANCE когда есть tool "memory"
session_search_guidance SESSION_SEARCH_GUIDANCE когда есть tool "session_search"
skills_guidance SKILLS_GUIDANCE когда есть tool "skill_manage"
tool_use_enforcement TOOL_USE_ENFORCEMENT_GUIDANCE зависит от модели
execution_discipline OPENAI_MODEL_EXECUTION_GUIDANCE зависит от модели

Не заменяется (остаётся в коде):

  • DEFAULT_AGENT_IDENTITY — это fallback когда нет SOUL.md (у нас есть SOUL.md, не нужно)
  • GOOGLE_MODEL_OPERATIONAL_GUIDANCE — Google-specific, неактуально для Whale
  • COMPUTER_USE_GUIDANCE — нет toolset
  • KANBAN_GUIDANCE — нет kanban
  • PLATFORM_HINTS — platform-specific, другая логика

2. agent/system_prompt.py — функция загрузки

def _load_prompt_block(agent, block_name: str, default: str) -> str:
    """Load a prompt block from a file if configured, else return default."""
    overrides = getattr(agent, "_prompt_overrides", None) or {}
    path = overrides.get(block_name)
    if path:
        try:
            resolved = os.path.expanduser(path)
            content = Path(resolved).read_text(encoding="utf-8").strip()
            if content:
                return content
        except Exception:
            logger.debug("Could not load prompt override '%s' from %s", block_name, path)
    return default

3. agent/agent_init.py — пробросить конфиг

После загрузки _agent_cfg (строка ~1058) добавлено чтение agent.prompt_overrides:

agent._prompt_overrides = {}
try:
    _po = _agent_cfg.get("agent", {}).get("prompt_overrides", {})
    if isinstance(_po, dict):
        agent._prompt_overrides = _po
except Exception:
    pass

4. Конфиг Whale — config.yaml

Добавлена секция:

agent:
  prompt_overrides:
    hermes_help: ~/.hermes/hermes-whale/review/hermes_help.md
    task_completion: ~/.hermes/hermes-whale/review/task_completion.md
    memory_guidance: ~/.hermes/hermes-whale/review/memory_guidance.md
    session_search_guidance: ~/.hermes/hermes-whale/review/session_search_guidance.md
    skills_guidance: ~/.hermes/hermes-whale/review/skills_guidance.md
    tool_use_enforcement: ~/.hermes/hermes-whale/review/tool_use_enforcement.md
    execution_discipline: ~/.hermes/hermes-whale/review/execution_discipline.md

5. Файлы блоков

Созданы 7 файлов в ~/.hermes/hermes-whale/review/:

  • hermes_help.md — содержимое константы HERMES_AGENT_HELP_GUIDANCE
  • task_completion.md — содержимое TASK_COMPLETION_GUIDANCE
  • memory_guidance.md — содержимое MEMORY_GUIDANCE
  • session_search_guidance.md — содержимое SESSION_SEARCH_GUIDANCE
  • skills_guidance.md — содержимое SKILLS_GUIDANCE
  • tool_use_enforcement.md — содержимое TOOL_USE_ENFORCEMENT_GUIDANCE
  • execution_discipline.md — содержимое OPENAI_MODEL_EXECUTION_GUIDANCE

Обратная совместимость

Если prompt_overrides не задан или файл не найден — используется хардкод. Никакой код не ломается для других профилей/пользователей.

Порядок выполнения

  1. Создать 7 файлов блоков в ~/.hermes/hermes-whale/review/
  2. Пропатчить agent/system_prompt.py — добавить _load_prompt_block() и заменить 7 констант
  3. Пропатчить agent/agent_init.py — пробросить prompt_overrides из конфига
  4. Обновить config.yaml — добавить agent.prompt_overrides (через копию, т.к. patch блокирован TIRITH)
  5. ⏸️ Перезапустить webhook (ждёт команды)
  6. ⏸️ Обновить Obsidian docs (этот шаг — выполнен)

Проверка

После изменений system prompt должен содержать те же блоки, что и раньше, но загруженные из файлов. При изменении файла и рестарте сессии — новый текст. При удалении файла — fallback на хардкод.

Pitfalls

  • TIRITH блокирует patch/config.yamlconfig.yaml под защитой TIRITH, patch и write_file отказываются писать в него. Решение: cp в /tmp/, отредактировать там, cp обратно (с аппрувом).
  • sed не подходит для YAML конфигов — сложные многострочные замены с вложенными отступами и escape-символами (~, /) ломаются в sed. Лучше patch.
  • Конфиг всё равно просит аппрув — при cp обратно TIRITH запрашивает подтверждение (overwrite project env/config file). Это нормально, нужно подтвердить.
  • SOUL.md уже существует — в Whale он лежит в /Users/admin/.hermes/hermes-whale/SOUL.md. Он НЕ выносится через prompt_overrides, т.к. уже является файлом и загружается отдельно через load_soul_md().
  • webhook не в PLATFORM_HINTS — webhook нет в словаре PLATFORM_HINTS в prompt_builder.py, поэтому блок platform hints пустой. Это не менялось.

Анализ вынесенных prompt-блоков

Все 7 файлов лежат в ~/.hermes/hermes-whale/review/ и подключаются через config.yaml → agent.prompt_overrides.

1. SOUL.md — Identity (не выносился, уже файл)

Путь: ~/.hermes/hermes-whale/SOUL.md 33 строки — определяет личность Кит (Whale), правила работы с Obsidian, инструментами, TIRITH, jq.

Структура:

  • Identity + run location
  • Core Rules (Obsidian first, vault namespaces, no external APIs, no python3 -c "import json", TIRITH, jq)
  • Absolute rules (стоп — zero actions)
  • Hermes self-reference (дока в приоритете над skill_view)

Наблюдения:

  • ⚠️ Дублирование с hermes_help.md — SOUL.md строка 34+ («AGAIN. ALWAYS check Obsidian first...») и hermes_help.md (Hermes Agent docs) пересекаются. Hermes help ссылается на docs.nousresearch.com, а SOUL напоминает про Obsidian MCP. Это complementary, а не конфликт — одно про внешнюю доку, другое про внутреннюю. Но стоит явно разделить: SOUL = who you ARE, hermes_help = что делать с Hermes как продуктом.
  • jq-правило (строка 22-23) удачно помещено именно сюда — это Whale-specific constraint.
  • respond in the language you're addressed in — хорошее мягкое правило, сохраняет билингвальность.
  • Нет guard: после обновления доков — проверить, нет ли сломанных ссылок/дубликатов.

2. execution_discipline.md — 48 строк, самый большой блок

Структура XML-тэги:

  • <tool_persistence> — не останавливаться рано, retry, verify
  • <mandatory_tool_use> — не отвечать по памяти: math, hashes, system state, git, web
  • <act_dont_ask> — очевидные интерпретации — действовать сразу
  • <prerequisite_checks> — проверять зависимости перед действием
  • <verification> — корректность, grounding, формат, safety
  • <missing_context> — не гадать, использовать lookup, только потом спросить

Наблюдения:

  • Отличная структура: секции-запреты с чёткими примерами уменьшают ambiguity.
  • ⚠️ <verification> пункт «Safety: if the next step has side effects... confirm scope before executing» — мягко противоречит <act_dont_ask>, которое велит не спрашивать. В hermes_whale system prompt поверх есть «NEVER REMOVE/KILL WITHOUT CONFIRMATION», так что extra safety здесь не лишняя, но формулировка «confirm scope» может спровоцировать лишний вопрос.
  • <mandatory_tool_use> — самое важное: запрещает LLM-галлюцинации фактов внешнего мира.
  • Нет секции про batch/parallel execution — при multi-file операциях агент может делать последовательно то, что можно параллельно.
  • Нет секции про отношение к ошибкам — если инструмент вернул ошибку, нужно ли retry с другим подходом (записано в <tool_persistence>) или сообщить пользователю.

3. task_completion.md — 3 строки

Суть: не останавливаться на плане/стабе — доводить до работающего артефакта. Не фабриковать результаты при блокере.

Наблюдения:

  • Критически важный guard против premature stopping.
  • ⚠️ Не покрывает ситуацию: «задача сделана, но пользователь не проверил» — должен ли агент спросить «проверить?» или просто отчитаться?
  • Не упоминает сценарий partial failure: часть задачи выполнена, часть провалилась — как подавать результат?

4. hermes_help.md — 1 строка

Суть: docs.nousresearch.com как authoritative reference, skill_view('hermes-agent') для guidance.

Наблюдения:

  • Лаконично.
  • Не упоминает куда писать issue / как апдейтить самому.
  • ⚠️ Несовпадение с реальностью: дока не всегда полная (есть расхождения с реальным API). Skill часто актуальнее.

5. memory_guidance.md — 1 строка, 1441 символ (самая длинная строка)

Суть: compact facts, what to save (preferences, corrections, env), what NOT to save (task progress, PRs, stale artifacts). Imperative phrasing bad. Sessions for recall, skills for procedures.

Наблюдения:

  • Отличный negative list (не сохранять PR numbers, commit SHAs, "Phase N done").
  • Важный паттерн: declarative facts vs instructions — записана разница с примерами.
  • ⚠️ «Write memories as declarative facts, not instructions to yourself» — полезно, но не всегда практично: некоторые memory entries работают лучше как правила (например, «Allways back up before editing» vs «User prefers backups before edits»).
  • Нет про conditional memory — «если X, то запомни Y». Например, при ошибке сети — не запоминать «нет соединения», это transient.

6. session_search_guidance.md — 1 строка

Суть: прежде чем спрашивать пользователя — поищи в истории сессий.

Наблюдения:

  • Одно чёткое правило, минимум слов.
  • Не хватает: когда НЕ надо искать (например, если вопрос про current OS state — не искать, а сразу uname).

7. skills_guidance.md — 1 строка

Суть: после сложной задачи — сохранить как skill; outdated skill — patch сразу.

Наблюдения:

  • Лаконично.
  • Не хватает: критерии «сложности» (5+ tool calls — триггер). И что делать с zombie skills (которые больше не нужны).

8. tool_use_enforcement.md — 2 строки

Суть: MUST use tools, не описывать планы без экзекьюшена. Каждый response = tool calls или final result.

Наблюдения:

  • Самый жёсткий enforcement блок. Правильно.
  • Не хватает: что делать когда tools не доступны (tool_use_enforcement не может быть выполнен).

Cross-cutting observations

  1. Размеры файлов несбалансированы: execution_discipline (48 строк) vs session_search_guidance (1 строка). Это ОК — разные блоки разной сложности.
  2. XML vs Markdown: execution_discipline использует XML-тэги как semantic sections — интересно, работает ли это для модели как структурный сигнал? В hermes_whale system prompt есть ещё # Headers как разделители. Два стиля в одном system prompt — возможно, снижают эффективность.
  3. Нет ordering гарантий: блоки вставляются в разном порядке в build_system_prompt_parts() — сначала task_completion, потом hermes_help, потом execution_discipline. Но модель читает слева направо. Если execution_discipline должен быть последним (как enforcement override) — его позиция в сборке не гарантирует этого.
  4. Нет cross-reference между файлами: например, execution_discipline не ссылается на task_completion или наоборот. Агент может воспринимать их как независимые, несмотря на overlap.
  5. Нет версионирования блоков: если поменять execution_discipline.md, нет способа отследить «было / стало» без диффа гита.
  6. Potential prompt compression issue: при длинных system prompts модель может терять середину (lost-in-the-middle). execution_discipline (2.7KB) — самый тяжёлый блок. Возможно, стоит сократить примеры в <mandatory_tool_use> (все 11 пунктов проверять не надо — достаточно 4-5).

Рекомендации

  1. Добавить ordering guard — execution_discipline и tool_use_enforcement должны быть последними в system prompt (как override rules).
  2. Консолидировать XML-стиль — либо все блоки в XML-тэгах, либо все в Markdown headers.
  3. Добавить conditional session_search — правило: для state-вопросов (time, OS, memory) — не session_search, сразу tool.
  4. Добавить partial failure protocol в task_completion.
  5. Ввести дайджест prompt-блоков — при изменении любого .md файла в review/ логировать diff.