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

302 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 вс).
---
## Вынос хардкода промптов в файлы
**Статус:** Реализовано ✅ (будет активно после перезапуска 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` — функция загрузки
```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
```
#### 3. `agent/agent_init.py` — пробросить конфиг
После загрузки `_agent_cfg` (строка ~1058) добавлено чтение `agent.prompt_overrides`:
```python
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`
Добавлена секция:
```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.yaml** — `config.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.