TL;DR
Memory Echo («эхо памяти») — находка про долговременную память агентов: когда агент достаёт заметку и записывает пересказ обратно, одна старая запись размножается в несколько. Метод борьбы, FPA (Family–Provenance–Authority), добавляет между поиском и ответом три шага. Он оставляет в контексте одного представителя от каждого источника, отключает устаревшие записи после проверенного исправления и заставляет отвечать по подтверждённым фактам.
Боль знакома. Вы сказали агенту: «Ищу низкоуглеводные овощи». Он всё равно советует кето-батончики, которые вы обсуждали месяц назад. Причина в том, что старая рекомендация пересказывалась и сохранялась снова и снова. В итоге в поиске она занимает три-пять мест, а ваше исправление — одно. Для модели это выглядит как «пять независимых подтверждений против одного», хотя источник у всех пяти один. Важно, что простое чтение без записи этого не делает. Эхо растёт именно от цикла «достал → пересказал → записал». Даже после исправления потомки старой записи остаются в выдаче и продолжают давить на ответ.
Метод решает это в три шага. Шаг 1: записи группируются по происхождению (по «родителю», а не по формулировке), и в контекст попадает максимум одна на семью. Шаг 2: если пришло проверенное исправление, вся старая семья остаётся в архиве, но не имеет права участвовать в текущем ответе. Шаг 3: ответ строится по подтверждённым данным, а черновик сверяется с ними.
Схема метода
ШАГ 1 (Family): сгруппировать найденные записи по источнику/родителю
→ в контекст максимум 1 запись на семью
ШАГ 2 (Provenance): сверить записи с проверенным исправлением
→ старая семья остаётся в архиве, но не допускается в ответ
ШАГ 3 (Authority): ответить по проверенным актуальным фактам
→ черновик сверяется с допущенными данными
Хранилище не удаляется: история сохраняется для аудита.
Меняется только то, что попадает в контекст ответа.
В статье FPA работает кодом между поиском по памяти и генерацией ответа. Шаги выполняются не одним промптом.
Пример применения
Задача: Вы руководите небольшой кофейней в Казани. Агент-закупщик ведёт заметки о поставщиках. В заметках цена на зерно у «Фермер-Юг» (420 ₽/кг) записана три раза. Это письмо поставщика, пересказ в заметке встречи и строка в недельной сводке. Все три — потомки одного письма. Потом пришёл счёт, в котором цена уже 510 ₽/кг. Вы просите агента посчитать закупку на месяц.
Промпт:
Ты — агент-закупщик кофейни. Перед ответом выполни три этапа.
M1 | источник: письмо поставщика (12 марта) | родитель: — | статус: активна
«Зерно Арабика-Блэнд, 420 ₽/кг»
M2 | источник: заметка со встречи (14 марта) | родитель: M1 | статус: активна
«Фермер-Юг держит цену 420 ₽/кг»
M3 | источник: недельная сводка (21 марта) | родитель: M2 | статус: активна
«Основной поставщик зерна: Фермер-Юг, ~420 ₽/кг»
M4 | источник: счёт №188 от поставщика (2 апреля) | родитель: — | статус: проверено
«Арабика-Блэнд, 510 ₽/кг, действует с 1 апреля»
M5 | источник: график работы кофейни | родитель: — | статус: активна
«Расход зерна: 60 кг в месяц»
Сгруппируй записи в семьи по родителю и источнику, а не по формулировке.
Из каждой семьи оставь не более одной записи-представителя.
Выведи список семей и выбранных представителей.
Сверь семьи с проверенными записями.
Если проверенная запись заменяет факт, вся старая семья помечается
«в архиве, не для ответа».
Выведи, какие записи допущены в ответ, какие отключены и почему.
Ответь на вопрос только по допущенным записям.
Если проверенного источника нет — прямо скажи об этом.
Сверь черновик с допущенными записями и исправь расхождения.
Вопрос: сколько мы потратим на зерно в апреле?
Результат: Модель покажет три блока. В первом записи M1–M3 объединены в одну семью, представитель выбран один, M4 и M5 стоят отдельно. Во втором старая семья помечена как отключённая из-за счёта M4. В третьем расчёт опирается на цену из счёта и расход из графика, а старая цена в расчёт не попадает. Конкретные цифры считает сама модель.
Почему это работает
Слабость. Модель не знает, что три записи — это одно и то же письмо. Для неё три похожие заметки выглядят как три независимых подтверждения. Чем больше повторов, тем сильнее «вес» старой версии, и одно свежее исправление проигрывает хору. Остановка записи эту инерцию не убирает: потомки уже лежат в хранилище.
Сильная сторона. Если рядом с каждой записью лежат метаданные (откуда она, чей потомок, проверена ли), дедупликация по происхождению и сверка с проверенными фактами — задача простая. Исследователи показали, что нужно группировать по родословной, а не по похожести слов. Два независимых источника могут говорить одно и то же, а два пересказа одного поиска остаются одной семьёй.
Как метод использует это. Он вмешивается между поиском и ответом. Хранилище остаётся нетронутым, поэтому ничего не теряется и всё можно проверить. Меняется то, что допускается в контекст.
Рычаги:
- Лимит на семью (в статье — одна запись) → можно поднять до двух для сложных задач, но эхо вернётся.
- Порядок проверки → сначала семьи, потом исправления, затем ответ: в таком порядке каждый шаг чистит вход следующему.
- Статус записи (активна / проверено / в архиве) → ключ ко всему методу. Без него шаг 2 не работает.
- Правило при отсутствии проверенного источника → заменяйте на своё: «спросить пользователя», «пометить как непроверенное».
Шаблон промпта
В статье нет готовых промптов, FPA там реализован кодом. Ниже перевод логики трёх шагов в текстовую инструкцию, который можно запускать в чате или агенте. Это не промпт авторов.
Ты — агент с долговременной памятью. Перед каждым ответом пройди три этапа.
{id} | источник: {откуда} | родитель: {id или —} | статус: {активна / проверено / в архиве}
{текст записи}
...
Сгруппируй записи в семьи по родителю и источнику, а не по формулировке.
Две записи с разными словами, но общим родителем — одна семья.
Из каждой семьи допусти не более {лимит_на_семью} записи.
Выведи: семьи и выбранных представителей.
Сверь семьи с проверенными записями.
Если проверенная запись заменяет или опровергает факт, вся старая семья
получает статус «в архиве» и не допускается в ответ.
Записи в архиве не удаляй и не изменяй.
Выведи: допущенные записи, отключённые записи, причину.
Ответь на вопрос только по допущенным записям.
Если проверенного источника нет — скажи об этом и {действие_без_источника}.
Сверь черновик с допущенными записями и исправь расхождения.
Не записывай свой пересказ найденной заметки как новый факт.
Если нужно сохранить пересказ — укажи родителя и пометь его как производный.
Вопрос: {вопрос}
Что подставлять:
- {id}, {источник}, {родитель}, {статус} — данные из ваших заметок. Родителя можно восстановить так: «эта запись — пересказ вот этой».
- {лимит_на_семью} — по умолчанию 1.
- {действие_без_источника} — «задать мне уточняющий вопрос» или «пометить ответ как непроверенный».
- {вопрос} — текущая задача.
🚀 Быстрый старт — вставь в чат:
Вот шаблон трёх этапов очистки памяти (семьи → допуск по проверенным исправлениям → ответ по подтверждённым фактам). Адаптируй под мою задачу: [твоя задача].
Задавай вопросы, чтобы заполнить поля.
[вставить шаблон выше]
LLM спросит, откуда берутся записи, что у вас считается проверенным источником и что делать без проверки. Это нужно потому, что метод держится на трёх вещах: происхождении записей, статусе «проверено» и правиле для случая без подтверждения. Модель возьмёт структуру из шаблона и подстроит под вашу систему заметок.
Ограничения
⚠️ Нужны метаданные: метод работает, когда у записей есть источник, родитель и статус. Если заметки лежат плоским текстом без происхождения, шаг 1 не отличит «пять пересказов одного» от «пяти независимых источников».
⚠️ Нужен проверенный источник: шаги 2 и 3 держатся на подтверждённой «истине» (счёт, документ, ваша прямая правка). Что делать, когда её нет, авторы не проверяли. Восстановительная ветка на схеме названа иллюстративной.
⚠️ В статье это код, не промпт: FPA встроен в поиск по памяти четырёх готовых систем. Перенос в чат-промпт — наш перевод логики. Эффект такого перевода авторы не измеряли.
⚠️ Чтение без записи эху не вредит: проблема возникает от цикла «достал → пересказал → записал». Если ваш агент ничего не пишет обратно в память, главная часть риска у вас отсутствует.
⚠️ Эффект неравномерен: в двух системах из четырёх прирост точности скромнее. Там итоговая выдача часто остаётся «забитой» старыми записями, а ответ всё равно улучшается. Одна картинка выдачи не показывает, что происходит с ответом.
⚠️ Тест — искусственный: «старое утверждение» бралось из другого реального ответа того же набора данных. Живые сценарии (покупки, медицина, путешествия) проверялись на раннем пробном протоколе и не входят в главные цифры. Часть приложений в тексте не видна.
Как исследовали
Исследователи сделали бенчмарк MEchoBench. Они взяли по 50 вопросов из четырёх известных наборов для проверки памяти (LoCoMo, LongMemEval, HotpotQA, BEAM). В итоге осталось 190 вопросов, десять отложили на разработку. К каждому вопросу подмешали «старое» утверждение из другого реального ответа, а верный ответ служил проверенным исправлением. Для каждого вопроса создали три истории памяти. В первой старое утверждение лежит один раз, во второй его шесть раз читают без записи, в третьей после каждого чтения пишут пересказ. Затем во всех историях вводили одно и то же исправление и ещё 30 раз читали память, ничего не записывая.
Это показало ясную картину. Чтение без записи почти не меняет картину, а запись пересказов резко увеличивает долю старой семьи во всех четырёх системах памяти (A-MEM, Mem0, CoM, LangMem). Вывод — виновата сама петля «поиск → запись», а не конкретный алгоритм ранжирования. После исправления старые потомки продолжали занимать места: показатель присутствия старой семьи в выдаче держался на уровне около 0,65–0,70 все 30 запросов без записи. Эхо живёт и без новой записи, как унаследованное преимущество.
Чтобы честно сравнить методы, кандидатов и историю заморозили. Четыре способа выдачи прогоняли по одному и тому же набору записей на двух моделях (DeepSeek V4 Flash и Kimi K2.6). Ответы оценивал GPT-5.6. Базовая точность была 0,825 (DeepSeek) и 0,782 (Kimi), а с FPA стала 0,920 и 0,916. «Загрязнение решения» (насколько ответ ближе к старому утверждению, чем к верному) упало с 0,106 до 0,030 и с 0,109 до 0,038. Три обычных альтернативы (штраф за повторы, оценка качества записей, обученное ранжирование) тоже поднимали точность, но почти не убирали устойчивое присутствие старой семьи. FPA сильнее всех уменьшил устойчивое присутствие: индекс упал с 0,427 до 0,057. Уроки для практики такие: полезная запись может помочь ответу, пока старые потомки всё ещё лезут в выдачу, а чистить надо по родословной и по статусу исправления.
Адаптации и экстраполяции
💡 Адаптация для файла инструкций агента (CLAUDE.md, AGENTS.md, память ассистента): принцип переносится в правила ведения заметок. Это наша экстраполяция: авторы такие правила в промптах не проверяли.
## Правила работы с памятью
- Каждая запись в заметках: что, откуда (источник), чей пересказ (родитель),
статус (активна / проверено / заменена).
- Пересказ найденной заметки не записывай как новый факт. Пиши: «производная от {id}».
- Когда я исправил факт или пришёл документ-подтверждение: пометь старую запись
и все её производные «заменена», не удаляй.
- Отвечая, опирайся на записи со статусом «проверено»; из каждой цепочки
пересказов бери не больше одной записи.
- Нет проверенного источника — скажи об этом, не опирайся на старую версию молча.
🔧 Техника: добавить аудит памяти → увидеть эхо до того, как оно повлияло на ответ
Вот мои заметки о {тема}. Найди записи, которые являются пересказами друг друга
(общий источник, разные слова). Сгруппируй их в семьи и покажи, сколько
«голосов» у каждой версии факта на самом деле. Отметь версии, которые противоречат
более свежим проверенным записям.
Так видно, что «пять подтверждений» на деле один источник.
Ресурсы
- Название работы: Memory Echo in Single-Agent Long-Term Memory: Lifecycle Evaluation and Provenance-Guided Mitigation
- Код и бенчмарк: https://github.com/OrcasSam/memory-echo-benchmark
- Авторы: Yufeng Li, Sheng Yao, Peng Zeng, Dezhang Kong, Shi Lin, Changting Lin, Xun Wang, Meng Han
- Организации: East China Normal University, University of Southern California, Zhejiang University, Zhejiang Gongshang University
- Системы памяти из статьи: A-MEM, Mem0, CoM, LangMem
- Наборы данных: LoCoMo, LongMemEval, HotpotQA, BEAM
