Суть
Разница между ошибкой в ответе и ошибкой в памяти — во времени жизни. Плохой ответ виден сразу и стоит одного запуска. Плохая запись невидима, участвует в десятках следующих ответов и к моменту обнаружения уже не восстанавливается по одной трассе.
Типичная механика отказа: пользователь однажды написал «не тратьте время на уточнения, сразу эскалируйте», агент сохранил это как устойчивое предпочтение — и через две недели, когда ситуация требовала как раз уточнения, уверенно эскалировал.
Самый опасный путь — запись в горячем пути
Модель ответила, рантайм тут же вызывает сохранение в память. На короткой дистанции выглядит красиво. Системные проблемы этого пути:
- запись происходит под давлением задержки, поэтому проверять некогда;
- никто не валидирует, что вообще достойно сохранения;
- нет шага нормализации и удаления лишнего;
- нет отдельной политики изоляции арендаторов;
- потом невозможно объяснить, почему факт оказался в памяти.
Скучное правило, которое это закрывает: запись в долговременную память по умолчанию либо явно разрешена политикой, либо вынесена в фоновый конвейер (Context Compaction).
В горячем пути разумно оставить минимальное состояние сессии, короткие рабочие заметки, временные записи с понятным сроком жизни и то обновление, без которого текущий процесс действительно ломается.
Фоновый конвейер не подтверждает запись
Вынос записи из горячего пути — правило выше — покупается ценой, которую стоит назвать прямо: вызов возвращает идентификатор задачи, а не результат. Факта в памяти в момент возврата ещё нет, и когда он там появится, вызывающая сторона не знает.
Следствий три, и каждое своё:
- Чтение сразу после записи не находит только что записанного. Сценарий «сохранил предпочтение и тут же на него сослался» при фоновом разборе не работает, а тест, написанный последовательно, будет проходить через раз.
- Разбор может решить, что фактов в присланном тексте нет, и не записать ничего. Код ответа при этом успешный. Это молчаливый холостой ход на пути, который заметка целиком объявляет чувствительным.
- Ошибка разбора видна только тому, кто отдельно спросит про задачу. К этому моменту ответ пользователю давно отдан.
Лечится тем же, чем лечится молчание вызова инструмента: исходов у записи не два, а три — записано, фактов не извлечено, ошибка разбора, и они обязаны различаться в ответе и в журнале (Agent Failure Modes — три статуса вызова, разведённые по той же причине). Средний исход нужен именно отдельным: «ничего не извлечено» — это нормальная работа разбора и одновременно самый частый способ потерять запись незаметно.
Слой памяти по умолчанию интерпретирует, а не хранит
Внешний слой памяти — не хранилище, куда кладут текст. Он вызывает модель, извлекает из присланного факты и хранит их (Mem0). Значит, прочитанное не обязано совпадать с записанным, и это поведение по умолчанию, а не особый режим.
В интерфейсе это оформляется переключателем: извлечение включено изначально, дословное сохранение просят явно. Выбор определяется тем, что именно записывается. Реплика диалога, из которой нужен вывод, идёт через извлечение. Формулировка, у которой важна точность буквы — условие договора, значение параметра, цитата с чужими словами, — сохраняется дословно: иначе слой перескажет её своими словами и потеряет ровно то, ради чего её сохраняли.
Запись, которую слой не имеет права переписать
Второе следствие интерпретации — автоматическое разрешение противоречий: новый факт, противоречащий старому, вытесняет его без спроса. Для предпочтений пользователя это правильное поведение и отдельное достоинство слоя (Mem0 — вытеснение устаревшего). Для части записей — неправильное, и отличаются они не важностью, а тем, чем запись является:
- проверенный факт с известным происхождением, у которого источником обновления может быть только та же процедура проверки;
- значение с внешним владельцем: лимит, тариф, условие договора, ограничение политики — его меняет владелец, а не вывод модели из реплики;
- запись, на которую уже сослались в принятом решении: переписав её, систему лишают возможности объяснить прошлый ответ.
Практическая форма — признак неизменности у записи, запрещающий системе трогать её самостоятельно; обновление такой записи идёт только явным вызовом. Слой памяти без такого признака годится для профильной памяти и не годится для проверенных фактов — то же разделение слоёв, что в Memory Boundaries, но выведенное со стороны записи.
Только создание: вытеснение выражается новой записью
Запрет переписывать отдельную запись — половина решения; вторая половина в том, чтобы перезаписи не было в интерфейсе вообще. Хранилище, у которого есть только операция создания, выражает устаревание фактa новым документом со ссылкой на замещаемый, а не правкой старого на месте.
Разница видна не в момент записи, а в момент разбора. При перезаписи вопрос «что здесь было до вредной записи» не имеет ответа: прежнего текста нет нигде, и восстановление вытесненного факта невозможно в принципе (Memory Poisoning). При создании-только прежняя запись остаётся на месте, просто перестаёт быть актуальной, и откат сводится к снятию пометки — операции, которая ничего не теряет.
Цена честная и её надо назвать: объём растёт монотонно, а чтение обязано понимать цепочку замещений, иначе выдаст устаревший факт как текущий. Это плата за обратимость, и она ниже, чем кажется: записей, замещающих друг друга, в реальном профиле немного, а именно они и есть самое спорное содержимое хранилища.
Хорошая память пишет меньше, чем хочется
Отбор важнее объёма. В память стоит писать только то, что пригодится в будущих запусках, имеет понятного владельца и арендатора, объяснимо человеку, не тащит лишних чувствительных данных и не превращает подсказку в свалку.
Проверка перед каждой записью формулируется одним вопросом:
Если этот фрагмент всплывёт через три недели в другом контексте, мне будет комфортно объяснить, почему он здесь?
Неуверенный ответ означает, что запись не нужна.
Но «меньше» — не та ось для рабочих артефактов
Правило строгого отбора верно для профильной памяти и проверенных фактов: там лишняя запись переживает запуск и начинает влиять на решения. Для объёмных рабочих данных ось другая — не «сколько писать», а «что именно хранить».
Кейс из Agent Memory: наивный агент-химик израсходовал 20 млн токенов там, где агент с указателями обошёлся 1234 — разница около 16 000×. Экономия достигнута не отказом от записи, а тем, что в контексте остался короткий идентификатор, а содержимое ушло во внешнее хранилище и подтягивается по запросу.
Отсюда уточнение к правилу: перед тем как решать «писать или нет», стоит проверить третий вариант — записать ссылку. Он снимает главное возражение против записи (раздувание подсказки), сохраняя доступность данных, и потому для результатов инструментов, длинных документов и промежуточных артефактов почти всегда предпочтительнее обеих крайностей (Context Compaction).
Минимальная политика
memory:
allowed_kinds:
- profile_preference
- validated_fact
- session_summary
deny_sources:
- raw_user_prompt
- external_html
- unvalidated_tool_output
require_tenant_id: true
reject_if_contains:
- secrets
- access_tokens
- payment_card_data
write_mode:
profile_preference: background_review
validated_fact: immediate_if_trusted
session_summary: background_only
Ценность не в «уме» правил, а в том, что они видимы и поддаются аудиту. Обратите внимание на deny_sources: сырой пользовательский промпт и непроверенный вывод инструмента запрещены как источники — именно они дают большинство плохих записей.
Правила чтения и записи почти никогда не совпадают
Если развести только хранилище, но не пути, система скатывается в странную логику: всё, что однажды записалось, потом читается почти откуда угодно.
Разведение выглядит так:
- запись в долговременную память требует проверки, происхождения и фонового разбора;
- чтение из неё разрешено только через фильтры извлечения (Agent Retrieval Policy);
- запись в профильную память требует явного сигнала или высокой уверенности;
- чтение профильной памяти разрешено слою персонализации, но не движку политик (Agent Control Plane).
Последняя строка — самая важная: если непроверенная память участвует в решении политики, персонализация превращается в канал влияния на права.
Происхождение хранится по умолчанию
Для каждой записи, живущей дольше одного запуска, минимальный набор полей: source_type, source_id, writer_identity, tenant_id, written_at, confidence или validation_state.
Выглядит бюрократией ровно до первого спора о том, откуда взялся «факт», который агент уверенно повторил в другом контексте.
Идентичность пишущего задаёт среда, а не вызов. Поле writer_identity теряет смысл, если его значение приходит аргументом от того, кто пишет: провенанс тогда сообщает не «кто записал», а «кем записавший назвался». Практичная форма — брать идентичность из конфигурации процесса на старте и не принимать её в параметрах операции; тем же значением ограничивается и выдача на чтении.
Импорт сначала staged, потом durable
Чужой каталог памяти, transcript или backup не должен сразу попадать в автоматический context injection. Безопасный путь: импортировать во временную область, показать preview с provenance, проверить tenant/чувствительные данные и только затем явно повысить записи до durable. До promotion они доступны разбору, но не влияют на обычные ответы.
Тот же provenance ограничивает обещание «забыть». Система может надёжно удалить записи и производные, для которых сохранилась lineage; она не может честно гарантировать удаление копий без происхождения, внешних backup и уже экспортированных данных. Поэтому forget возвращает область выполненного удаления и известные остаточные границы, а не безусловное «всё забыто».
Траектория — свидетельство, insight — производная
Experiential memory часто сохраняет два разных объекта, и склеивать их в одну запись нельзя:
- сырая траектория — вход, действия, результат, точное решение человека
accept / reject / edit, его правка и идентификаторы запуска; - извлечённый insight — короткая формулировка, которую модель вывела из одной или нескольких траекторий: правило, область действия, polarity, confidence и ссылки на источники.
Первая запись отвечает «что произошло» и остаётся неизменяемым evidence. Вторая отвечает «чему, возможно, стоит научиться» и является гипотезой. Её можно пересобрать, объединить с дублем или отклонить, не переписывая исходное событие.
Решение ревьюера тоже не равно истине. accept подтверждает полезность комментария в конкретном контексте, reject может означать ошибку агента, локальное исключение или нехватку времени, а edit смешивает техническую поправку со стилем формулировки. Поэтому один feedback-event не должен автоматически превращаться в обязательную инструкцию следующих запусков. Безопасный поток выглядит так:
trajectory + feedback → proposed insight → дедупликация и проверка конфликтов → управляемое правило
До последнего перехода insight извлекается как подсказка с provenance, а не как policy. Для повторяющихся сигналов система агрегирует независимые source_review_id, хранит противоположные примеры и не выдаёт model-generated confidence за частоту подтверждений. Эта граница позволяет использовать идею ExpeL — извлекать опыт без изменения весов — и не превращать ошибочную интерпретацию одного ревью в долговечный стандарт (Reflexion, Skill Change Control).
Практичная реализация держит три слоя, а не два: immutable raw trajectory; per-run analysis с outcome, первым ошибочным шагом и ссылками на evidence; cross-run candidate с областью применимости, поддерживающими и противоречащими случаями. Формальное знание выпускается только из третьего слоя после transfer-проверки. Так случайный успех не превращается в правило лишь потому, что красиво объяснён постфактум (Continual Agent Evolution).
Память — это контекст, а не инструкция
Разделение путей чтения и записи отвечает на вопрос «кто читает». Есть второй вопрос, который задают реже: чем прочитанное становится. Запись памяти, попавшая в контекст, ничем внешне не отличается от правила — тот же текст на том же языке, и модель обращается с ней так же.
Отсюда граница, которую держат явно: запись памяти рождается непроверенной и не может тихо стать правилом, умением или политикой. Формально это выражается полем доверия со значением «не проверено» у каждой новой записи и отсутствием перехода, который меняет это значение автоматически.
Неочевидная часть — что делает человек, когда запись всё же признана верной. Он не повышает доверие записи: принятое знание переносится в управляемый артефакт другого слоя — правило, решение в журнале решений, runbook, документацию репозитория. Хранилище памяти при этом источником истины не становится никогда и остаётся тем, чем было: подсказкой, у которой есть происхождение.
Это дороже, чем поднять флаг, и разница именно в том, ради чего затевалось. Флаг «проверено» на записи оставляет знание в хранилище, куда пишет агент; перенос кладёт его туда, где действует обычный порядок изменения — владелец, ревью, история. Второе — свойство слоя, первое — свойство строки.
Почему повышение не может выполнить агент
Формулировка, которая делает границу проверяемой: агент с доступом к оболочке не может считаться независимой границей человеческого одобрения. Если повышение записи до правила — это операция, доступная агенту, то согласование выполняет тот же, кто предлагает, и одобрение перестаёт что-либо означать.
Следствие практическое и жёсткое: автоматического перехода к повышению не должно существовать в интерфейсе, а не только в правилах пользования. Отсутствующая операция не обходится ни промптом, ни ошибкой конфигурации; запрещённая — обходится и тем, и другим (Approval Path, Human in the Loop).
Та же логика приложима шире записи памяти: она объясняет, почему право применить proposal к умению отделено от права его подготовить (Skill Change Control), и почему фильтр маршрутизации, выбираемый вызывающим, нельзя называть границей прав — он сужает выдачу по просьбе того же, кого ограничивает.
Повышение, которое уничтожает происхождение
Правило «переносить, а не поднимать флаг» подтверждено второй независимой реализацией. Там повышение урока команды — отдельная команда с перечислимыми порогами: уверенность не ниже 0,90, не меньше пяти голосов «за», не меньше двух участников, возраст не меньше двух недель. Результат пишется в клон основной ветки и попадает туда только через обычный запрос на слияние — то есть ровно перенос в управляемый артефакт.
Та же реализация показывает ловушку, и она стоит на самом осторожном шаге. Текст урока при повышении переписывает модель, и промпт переписывания предписывает убрать происхождение и ужесточить утверждение: для умения — «убери ссылки на конкретные даты, людей и разовые случаи», для правила — «убери контекст случая и сформулируй ограничение как абсолютный стандарт».
Последствие механическое: наблюдение из одного случая, с его оговорками, становится абсолютным правилом без даты и без автора, и ревьюер запроса на слияние видит только эту версию. Исходник не теряется — урок получает пометку, куда его повысили, — но в запросе на слияние его нет, то есть нет там, где принимается решение.
Это прямо против раздела «Происхождение хранится по умолчанию» выше, и случается именно на переходе, ради которого весь раздел затевался: перенос в управляемый слой помогает, только если перенесённое можно сверить с наблюдённым. Отсюда два требования к шагу повышения: запрос на слияние несёт исходник рядом с переписанным текстом, и переписанный текст не категоричнее источника — перевод наблюдения в правило остаётся решением ревьюера, а не свойством промпта (Paraphrase Drift, Context Compaction).
Связано с
- Agent Memory — какие вообще бывают виды памяти
- Memory Poisoning — что происходит, когда политика записи отсутствует
- Memory Boundaries — разные слои с разными правилами
- Context Compaction — фоновый конвейер, куда выносится запись
- Agent Retrieval Policy — фильтры на чтении
- Agent Control Plane — почему память не должна влиять на решения политики
- Multi Tenancy AI — изоляция арендаторов в записи
- Mem0 — внешний слой, извлекающий факты из диалога, и его вытеснение устаревших фактов
- Agent Failure Modes — три исхода вызова, по образцу которых разводятся исходы фоновой записи
- Skill Change Control — та же граница на слое умений: подготовить предложение и применить его — разные права
- Approval Path — подтверждение относится к точному артефакту, а не к намерению
- Human in the Loop — где в цепочке стоит человек и что именно он подтверждает
- Reflexion — словесный разбор опыта и риск закрепления ошибки оценщика
- Continual Agent Evolution — offline-консолидация нескольких оценённых траекторий в versioned candidate