# Hermes Agent — вынос хардкода промптов в файлы (prompt_overrides) **Дата:** 2026-09-15 **Статус:** реализовано, закоммичено и запушено **Репо:** `~/.hermes/hermes-agent` (сабмодуль, форк `mallexxx/hermes-agent`) ## Проблема Стабильный слой system prompt был **захардкожен** в `agent/prompt_builder.py`. Чтобы поменять формулировку любого блока (например, ужесточить инструкции про язык ответа или про завершение задачи) — надо было править Python-код сабмодуля. Это значит: правка живёт в форке, конфликтует при подтяжке апстрима, и её надо переносить при каждом обновлении. ## Решение: prompt_overrides Каждый хардкод-блок stable-слоя читается из `.md` файла. Маппинг — в конфиге. Файла нет → fallback на хардкод, ничего не ломается. ### Реализация (3 файла) **1. `agent/system_prompt.py`** — новая функция: ```python 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 ``` 7 констант заменены на её вызовы: | Блок | Константа (fallback) | |------|---------------------| | `hermes_help` | `HERMES_AGENT_HELP_GUIDANCE` | | `task_completion` | `TASK_COMPLETION_GUIDANCE` | | `memory_guidance` | `MEMORY_GUIDANCE` | | `session_search_guidance` | `SESSION_SEARCH_GUIDANCE` | | `skills_guidance` | `SKILLS_GUIDANCE` | | `tool_use_enforcement` | `TOOL_USE_ENFORCEMENT_GUIDANCE` | | `execution_discipline` | `OPENAI_MODEL_EXECUTION_GUIDANCE` | **2. `agent/agent_init.py`** — чтение конфига в `agent._prompt_overrides` (+11 строк, в секции рядом с tool-loop guardrail config). **3. `~/.hermes/hermes-whale/config.yaml`** — секция маппинга: ```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 ``` **4. `~/.hermes/hermes-whale/review/`** — 7 новых `.md` файлов с содержимым блоков. Раньше в этой папке лежали только `memory_prompt.md` и `skill_prompt.md`. ## Pitfall: prompt_overrides — это про Python-код, а не про config Файлы `review/*.md` **обязаны быть закоммичены**. Если закоммитить `config.yaml` с путями, но не сами файлы — подмены промпта молча исчезнут (fallback на хардкод), потому что `_load_prompt_block` ловит отсутствие файла в `except` и отдаёт default. Ошибки нет, поведение просто возвращается к хардкоду. Это ровно то, что чуть не произошло: 7 файлов `review/*.md` были untracked. ## Pitfall: порядок коммита сабмодуля Правки Python живут в сабмодуле. Порядок: ```bash cd ~/.hermes/hermes-agent && git add agent/*.py && git commit -m "..." cd ~/.hermes && git add hermes-agent && git commit -m "..." # обновить пин ``` Если пин не обновить — в родительском репо видно `hermes-agent (new commits, modified content)`, и `-dirty` в diff сабмодуля. ## Коммиты и push (2026-09-15) | Репо | Коммит | Что | |------|--------|-----| | `hermes-agent` | `207a1de16` | feat: load stable system-prompt blocks from config prompt_overrides | | `~/.hermes` | `7fd200c` | feat: wire prompt_overrides + whale-thread-guard multi-bot routing | | `~/.hermes` | `7893c35` | chore: sync skills — curator consolidation | | `~/.hermes` | `bdf84da` | chore(lsp): add vue/dockerfile/pyright/yaml language servers | | `~/.hermes` | `176ce9c` | chore: thread-scoped memory store + claude token refresh script | | `~/.hermes` | `9b111fc` | chore: untrack lsp/node_modules (1957 files, 43M) | **Запушено:** - `hermes-agent` → `github.com:mallexxx/hermes-agent` (20 коммитов) - `~/.hermes` → `git.mallexxx.duckdns.org/git_admin/eagle-hermes` (9 коммитов) ## Осталось в коде (не вынесено) - `DEFAULT_AGENT_IDENTITY` — fallback, остаётся хардкодом - `GOOGLE_MODEL_OPERATIONAL_GUIDANCE` — неактуально для Whale - `COMPUTER_USE_GUIDANCE`, `KANBAN_GUIDANCE` — неактуально - `PLATFORM_HINTS` — webhook там нет - `build_skills_system_prompt()` — автогенерируется, файлом не заменить ## Зачем это было нужно Два практических повода: 1. **Правки промпта без правки Python** — теперь формулировки живут в `.md`, редактируются в vault-стиле, не конфликтуют при подтяжке апстрима. 2. **Фикс языкового дрейфа DeepSeek** — нужна жёсткая языковая инструкция в промпте; теперь её можно добавить файлом, а не патчем кода. См. [[deepseek-language-drift]]. ## Связанное - [[hermes-whale-system-prompt]] — полный состав system prompt (3 слоя) - [[hermes-git-repo]] — структура репо, .gitignore, что коммитить - [[deepseek-language-drift]] — баг с китайским выводом, повод для правок промпта - [[hermes-fork-vs-upstream]] — расхождение с апстримом (24k коммитов)