/EVSTYGNEYМаркетинг на языке денег
ИИ и инструменты

Файловая память для ИИ-агента: воркспейс из markdown, который переживает сессию

TL;DR Контекст ИИ-агента умирает вместе с сессией: завтра он снова не знает ни ваших проектов, ни принятых решений, ни того, что вы уже пробовали. Четыре месяца я живу с файловым решением: память проектов, карта, правила и база знаний лежат в markdown на диске, агент читает их на входе в работу и обновляет на выходе. В статье — архитектура из трёх контрактов, разбор допущений, паттерн «шим» для навыков и тест инструкции свежим агентом в режиме «трудный пользователь»: 16 находок, 7 правок. Каркас — в репозитории под MIT. Чтение займёт минут десять.

Простыми словами ИИ-агент — это LLM с доступом к файлам и терминалу (Claude Code, Cursor, Codex CLI). Он читает и пишет файлы на вашем диске по инструкциям на естественном языке. Дальше считаю, что вы таким пользовались.

Почему не хватает того, что есть из коробки

Задача: в понедельник агент помог с проектом, в четверг открываю новую сессию — и хочу продолжить с места, где остановились, а не пересказывать проект заново. Штатные способы упираются каждый в свой предел.

Длинная сессия Контекстное окно конечно, при переполнении история сжимается автосаммари. Что именно выживет при сжатии — вы не контролируете: первыми обычно теряются мотивировки решений («почему выбрали B, а не A»), сами решения остаются. И сессия всё равно когда-нибудь закрывается.

Один большой CLAUDE.md Рабочий приём до определённого размера. Дальше файл превращается в свалку: контексты десяти проектов вперемешку, агент тащит в каждую задачу всё подряд, стоимость и шум растут.

Встроенная память агента У Claude Code есть автоматическая память. Она полезна, но непрозрачна ровно настолько, насколько автоматична: вы не выбираете, что в неё попадёт, она не переносится между инструментами и не читается глазами как единый документ.

RAG поверх заметок Векторная база, пайплайн индексации, обновление эмбеддингов — инфраструктура ради задачи «не пересказывать проект». Для личной работы одного человека это пушка по воробьям; к тому же результат поиска по эмбеддингам не отревьюишь так же просто, как файл.

Файловый воркспейс закрывает ту же задачу дешевле: обычные папки и markdown, полная прозрачность (всё читается глазами и лежит в git), переносимость между агентами. Плата — дисциплина структуры. Её и разбираем.

Архитектура: три контракта

За четыре месяца структура устоялась такой (35 проектов, база знаний на 15 тем):

workspace/
├── main.md                  ← карта: все проекты и разделы, по строке на каждый
├── CLAUDE.md                ← контракт поведения: агент читает сам при старте
├── AGENTS.md                ← однострочник «читай CLAUDE.md» для других агентов
├── .claude/skills/          ← автозапуск навыка-хранителя (шим, о нём ниже)
├── _inbox/                  ← приёмник непонятного; разбирается раз в неделю
├── _meta/templates/         ← шаблоны: README проекта, память, wiki-заметка
├── rules/global/            ← правила устройства воркспейса
├── skills/                  ← навыки агента (источники)
├── knowledge-base/
│   ├── AGENTS.md            ← контракт ведения базы знаний
│   └── <домен>/main.md      ← карта домена + страницы
└── projects/<имя>/
    ├── README.md            ← что это и зачем
    ├── memory.md            ← память проекта: агент читает первым
    ├── docs/ prompts/ assets/
    └── app/                 ← код, отдельный git-репозиторий

Несущих элемента три, остальное — обвязка.

Контракт №1: memory.md на проект Файл с фиксированными секциями: что это за проект, ключевые решения с мотивировками, текущий статус, следующий шаг, договорённости с агентом. Правило в CLAUDE.md: при входе в проект читать память первой, после значимого шага — обновлять. Новая сессия стартует не с нуля, а с последнего чекпоинта. По сути это ручной, человекочитаемый снапшот контекста — и в отличие от автосаммари, что в него попадает, решаете вы (точнее, агент по вашим правилам, а вы ревьюите глазами).

Контракт №2: main.md как карта По строке на проект и домен знаний. Агенту не нужно сканировать дерево, чтобы понять, что где лежит: одна загрузка карты — и он знает, куда идти. Это же спасает от дублей: прежде чем создать проект, агент сверяется с картой.

Контракт №3: правила поведения, записанные файлами. Договорённость «клади файлы аккуратно» агент забудет со сменой сессии — контракт должен лежать там, откуда он читается автоматически. У меня это три уровня: CLAUDE.md в корне (краткий контракт, подхватывается при старте), правило в rules/ (полная версия с обоснованиями) и навык-хранитель в skills/ (операционные рецепты: куда положить, как назвать, какой frontmatter). Тройное дублирование намеренное: инструкции для LLM исполняются вероятностно, и вероятность соблюдения растёт с числом мест, откуда правило может попасть в контекст.

Замечание База знаний устроена отдельным паттерном — три слоя с разными правами записи: raw/ (первоисточники, агент только читает), wiki-страницы (агент пишет и перезаписывает), схема-контракт (меняется редко, руками). Плюс правило противоречий: новый факт, конфликтующий со старым, не затирает его молча, а помечается блоком с указанием источников. Это тема отдельной статьи; схема лежит в references репозитория.

Допущения, которые пришлось принять

Каждое решение в структуре — ответ на конкретный отказ. Три показательных.

Архив вместо удаления Агент (и человек) плохо предсказывает, что «точно больше не понадобится». Правило: ничего не удаляется, устаревшее переезжает в archive/ рядом с оригиналом. Перемещение обратимо, удаление — нет, а диск дешевле восстановления удалённого.

Латиница и kebab-case в путях Кириллица и пробелы в путях ломаются на стыках: git на разных ОС, shell-скрипты, часть инструментов. Контент заметок — на любом языке, пути — только latin-kebab-case. Скучное правило, которое экономит часы отладки.

Код отдельно от заметок Код проекта живёт в app/ со своим git-репозиторием; workspace-репозиторий его игнорирует (projects/*/app/ в .gitignore). У кода и заметок разные жизненные циклы: заметки хочется коммитить пачкой раз в день, код — атомарно и с CI.

Паттерн «шим»: один источник для навыка

Инженерная деталь, на которой я застрял. Claude Code автоматически подхватывает навыки из скрытой .claude/skills/, а «витринная» skills/ воркспейса для него — просто папка с файлами. Хочется и автозапуск, и видимый пользователю источник. Держать две копии — гарантированный рассинхрон: правишь одну, вторая молча устаревает.

Решение В .claude/skills/workspace-organizer/SKILL.md кладётся файл-переадресация: тот же YAML-frontmatter с description (по нему движок решает, когда навык триггерить), а вместо тела — три строки: «прочитай и выполни ../../../skills/workspace-organizer/SKILL.md; здесь ничего не редактировать». Автотриггер работает, источник один, дублируется только description. Если источник переименуют или удалят — шим прямым текстом скажет об этом пользователю и предложит восстановить навык повторным запуском мастера.

Инструкция для LLM — это код. Тестируйте соответственно

Каркас воркспейса я упаковал в скилл-мастер: интервью из пяти блоков (путь, кто вы, проекты, темы, настройки) → план → постройка → заполнение памяти ответами. Написал, трижды перечитал, всё выглядело однозначным.

Потом я запустил тест: отдельный экземпляр агента, который скилл никогда не видел, получил инструкцию «выполни этот SKILL.md буквально, не привнося своих представлений о замысле» и сценарий пользователя, который на каждый вопрос отвечает «не знаю». Плюс обязанность: журналировать каждое место, где инструкция неоднозначна, невыполнима или потребовала догадки.

Свежий агент дошёл до конца — воркспейс собрался, все 16 файлов каркаса на месте. И принёс 16 задокументированных неоднозначностей. Примеры, за которые мне до сих пор слегка стыдно:

  • План не совпадал с постройкой. Дерево, которое мастер показывает пользователю для подтверждения («строим вот это, ок?»), было короче того, что реально создаётся на следующем этапе. Пользователь подтверждал один набор, получал другой.
  • Невыполнимая ветка. «Если тем для базы знаний нет — создай домен по профессии из блока 2». А в блоке 2 пользователь сказал «работаю и всё». Профессии нет, ветка виснет. Агент выкрутился сам (создал нейтральный домен work), но это была его догадка, не моя инструкция.
  • Самопротиворечие. «Создай пустую папку _inbox/ (и положи в неё README)». Папка с файлом — не пустая. Мелочь, но свежий исполнитель споткнулся и записал в журнал.
  • Молчание про плейсхолдеры. Шаблоны копируются в воркспейс «как есть», с {{PROJECT_NAME}} внутри — а конвенция «подставляй значения вместо {{...}}» нигде не была записана для будущих сессий.
  • Пустые папки и git. Каркас создаёт пустые docs/, prompts/, assets/ — а git пустых папок не хранит. Первый же клон воркспейса потерял бы половину структуры. В инструкции не было ни слова.

Семь находок стали правками скилла, остальные оказались штатным поведением или осознанным дизайном. Отдельно отмечу: на пункте «заполни память проекта содержательно», не имея ни одного содержательного ответа, тестовый агент не стал выдумывать легенду — записал факт настройки, принятые дефолты и следующий шаг. Повёл себя правильно без инструкции. Полагаться на это нельзя: следующий экземпляр может решить иначе, поэтому поведение закрепили явным правилом.

Чем хорош метод Он дешёвый: один запуск свежего агента с журналом неоднозначностей находит то, чего автор сам не видит, — автор знает замысел и достраивает его поверх текста. Это ровно code review, только ревьюер — та же система, что будет исполнять.

Чем плох Недетерминизм: один прогон — одна траектория. Тот факт, что агент сегодня выкрутился из невыполнимой ветки, не значит, что выкрутится завтра. Тест снижает вероятность отказа, но не даёт гарантий — как и любой тест, впрочем.

Грабли дистрибуции, собранные лбом

Скилл — это текст, но распространяется он как софт, и ломается тоже как софт. Что нашлось на пути от «работает у меня» до «работает у человека, который видит агента впервые»:

Грабля Что происходит Фикс
: (двоеточие с пробелом) внутри YAML-description frontmatter не парсится, скилл не подхватывается переформулировать без двоеточий или закавычить значение
GitHub ZIP распаковывается в <repo>-main скилл лежит не по ожидаемому пути, «не работает» явная инструкция переименования в README
%USERPROFILE% в команде установки в PowerShell не раскрывается — создаётся папка с буквальным именем $env:USERPROFILE
~/.claude скрыта в Finder пользователь без терминала не может найти папку скиллов ⇧⌘G → «Переход к папке» в инструкции
Свежеустановленный скилл не виден в текущей сессии «сказал волшебную фразу — ничего не произошло» установочная фраза велит агенту выполнить SKILL.md сразу, не дожидаясь перезапуска
Агент по голой ссылке строит «по мотивам» вместо эталонного каркаса — импровизация по README требование в тексте скилла: шаблоны брать из файлов, по памяти не восстанавливать

Последняя строка — любимая. Дай агенту ссылку на репозиторий без инструкций — он прочитает README, поймёт идею и уверенно построит нечто похожее, но своё. Для тысячи пользователей это тысяча разных воркспейсов. Лечится одной строкой в скилле, но додуматься до неё надо.

Где подход не работает

  • Команда. Всё выше — про одного человека. Совместная память на файлах упирается в merge-конфликты человеческих решений; для команды нужен другой контур согласования, у меня его нет.
  • Поиск по смыслу. Здесь нет эмбеддингов: агент ходит по картам (main.md) и grep'у. На моих объёмах хватает; если у вас тысячи заметок с перекрёстными смысловыми запросами — RAG вернётся в разговор.
  • Протухание памяти. memory.md обновляет агент, агент подчиняется правилу вероятностно. Без еженедельной ревизии («разбери inbox, обнови статусы») память дрейфует от реальности. Ритуал занимает минут двадцать, но он обязателен — это цена подхода.
  • Другие агенты. Структура переносима (markdown есть markdown), но автозапуск навыков — механика Claude Code. В Cursor тот же контракт приходится скармливать через AGENTS.md, триггер слабее.

Краткие выводы

  1. Память агента между сессиями решается файлами: memory.md на проект + карта + правила, записанные там, откуда агент читает их автоматически. Дорогая инфраструктура для этой задачи не нужна.
  2. Инструкции для LLM исполняются вероятностно. Контракт стоит дублировать по уровням (CLAUDE.md → правило → навык), а критичные конвенции записывать явно, даже если агент «и так догадался».
  3. Инструкция для LLM — это код. Тестируйте её как код: свежий исполнитель без знания замысла + сценарий худшего пользователя + журнал неоднозначностей. 16 находок на «трижды перечитанном» тексте — моя цена этого урока.
  4. Дистрибуция текста ломается как софт: YAML, пути, скрытые папки, порядок активации. Таблица граблей выше сэкономит вам вечер.

Каркас воркспейса, скилл-мастер с интервью, шаблоны и обе справки — в репозитории ai-workspace-starter (MIT). Ставится за 15 минут, работает без программирования.

А ваш агент завтра утром помнит, почему вы вчера выбрали вариант B, а не A? Если нет — посчитайте, сколько минут в день вы тратите на пересказ контекста, и умножьте на цену своего часа.

Интересно, как эту задачу решаете вы: файлы, встроенная память, RAG, что-то своё? И переживает ли ваш вариант смену сессии без пересказа проекта с нуля?