WikiTrace из KAIST учит ИИ-агента сверять уроки памяти с исходными логами
Каждый урок агента хранится со ссылкой на прогон, из которого он выведен. Разбираем формат файлов, промпт с условиями проверки, цену и команды запуска из репозитория.
10 ноября на arXiv вышел препринт «Don’t Just Trust Your Memory»: исследователи из KAIST и DeepAuto.ai описали систему памяти WikiTrace, в которой каждый урок агента хранится со ссылкой на прогон, из которого он выведен, и агент может открыть этот прогон до того, как последует уроку. По замерам авторов, средний результат на восьми наборах задач вырос с 79,5 без памяти до 90,2, а среди задач, которые решались и без памяти, агент провалил 4,5% против 6,5% с теми же уроками без источников. Код WikiTrace открыт под лицензией Apache 2.0.
Тем, кто пишет память кодинг- или терминальному агенту, работа подсказывает три решения: хранить сырые логи после того, как из них выжат урок; держать у каждого урока ссылку на лог и пометку, удачным ли был прогон; прописать в системном промпте, когда урок нужно перепроверить. Всё это сделано обычными файлами и инструментами read и bash. Препринт подан в ACL Rolling Review и находится на рецензии, независимого воспроизведения нет: все числа ниже — замеры авторов.
Ключевые выводы
- Память WikiTrace состоит из трёх слоёв файлов: урок (insight), разбор прогона (compilation) и сырой лог (raw). Урок ссылается на оба нижних слоя.
- Средний результат по восьми наборам задач на deepseek-v4-flash: 90,2 у WikiTrace, 87,0 у тех же уроков без источников (Insights Only), 79,5 без памяти.
- Regression, доля провалов среди задач, которые без памяти решались: 4,5% у WikiTrace, 6,5% у Insights Only, 9,7% у повторного запуска без памяти.
- Решение задачи с WikiTrace в среднем в 1,17 раза дороже, чем с Insights Only. При построении памяти уроки не проверяются дополнительными прогонами.
Почему уроки из прошлых задач ломают агента?
Потому что урок выводится из траектории, у которой есть только пометка «успех» или «провал», и модель угадывает, какое действие привело к исходу. Авторы разобрали задачи, которые агент решал во всех трёх прогонах без памяти и провалил с памятью. В 52% случаев LLM-судья (gpt-5.6-sol) связал провал с записью памяти, которой агент последовал, и чаще всего, в 20% случаев, сама запись была неверной.
Пример из статьи: правило метода ExpeL в ALFWorld гласит, что задача с лампой завершается, когда предмет оказался рядом с включённой лампой. Исходный прогон этому противоречит: эпизод закончился только после того, как агент взял карандаш. С этим правилом агент включил лампу рядом с вазой и объявил задачу решённой.
Lessons are inferred from trajectories labeled only with task success or failure, yet are typically provided without the trajectories they came from, leaving the agent no way to check them.
«Уроки выводятся из траекторий, помеченных только успехом или провалом задачи, но обычно выдаются без траекторий, из которых они получены, и у агента нет способа их проверить» (перевод Proglib).
Что лежит в каждом из трёх слоёв памяти?
Память собрана как каталог, смонтированный в песочницу агента только для чтения по пути /work/corpus. Слои перечислены в описании памяти в репозитории:
| Слой | Файлы | Что хранит | Когда агент его читает |
| Урок (insight) | insight/insight-NNNN.md, по файлу на урок | Что делать, когда урок применим, id и исход исходного прогона, пути к разбору и логу | Всегда: все уроки вставлены в первое сообщение |
| Разбор (compilation) | compilation/step-NNNN.md, по файлу на прогон | Задача, Key Decisions (успех) или Failure Causes (провал) с полями Decision и Support, ссылки на уроки | При спуске: уроку не хватает деталей, он взят из неудачного прогона или спорит с другим уроком |
| Сырой прогон (raw) | raw/step-NNNN/metadata.md и solver.full.jsonl | Задача, исход и число шагов; по строке JSON на ход с рассуждением модели, действием и наблюдением | При спуске и после неудачного действия, за конкретным фактом вроде формата команды |
Документ урока выглядит так:
--- type: insight id: insight-NNNN title: <title> source_step: step-NNNN --- ## Insight <guideline> ## Applicability <when it applies> ## Source episode step-NNNN (success | failure) - Task: <the source run's instruction> - Compilation: /work/corpus/compilation/step-NNNN.md - Raw trajectory: /work/corpus/raw/step-NNNN/
Как компилятор выводит уроки из траектории?
Одним вызовом модели на прогон. Компилятор получает задачу, траекторию и бинарный исход и не видит эталонного решения. Для успешных и неудачных прогонов промпты компилятора разные: в первом случае модель описывает ключевые решения, во втором вероятные причины провала. В обоих промптах стоит ограничение «You can extract *at most 3* candidate insights from the trajectory». Урок возвращается в формате из трёх полей: title, guideline (что делать, одно-два предложения) и applicability (когда применимо и когда нет).
Память строится за один проход и замораживается. Уроки не сливаются и не фильтруются, поэтому в пуле бывают повторы и противоречия, и разбираться с ними авторы оставляют агенту.
Когда агент должен спуститься к источнику?
В трёх случаях до первого действия и ещё раз после каждой неудачи. Вот фрагмент системного промпта для ALFWorld из приложения F HTML-версии статьи (тот же текст лежит в шаблоне descend.j2):
Go down to an insight’s source run and compilation when it tells you what to do but not exactly how, when it came from a failed run, or when two insights disagree. Check this before your first `act` for the insights you will rely on, and again whenever an action fails. Look for the one fact that settles it, such as a command format, in the run.
«Спускайся к исходному прогону урока и его разбору, когда урок говорит, что делать, но не говорит, как именно, когда он взят из неудачного прогона или когда два урока противоречат друг другу. Проверь это до первого вызова act для уроков, на которые собираешься опереться, и снова после каждого неудачного действия. Ищи в прогоне один факт, который решает вопрос, например формат команды».
О разборе неудачного прогона промпт говорит, что модель гадала о причине провала, и добавляет: «Only the raw turns are certain» («Достоверны только сырые ходы»). Следом идут три правила работы с памятью:
- «Never replay a past run»: прошлый прогон начинался из другого состояния, повторять его по шагам нельзя.
- «Take from a run only a fact you can check against this task»: из прогона берётся только факт, который можно сверить с текущей задачей.
- «From a failed run, take only the action to avoid, never the plan»: из неудачного прогона берётся только действие, которого надо избегать.
Для навигации промпт предлагает grep по каталогам памяти и две утилиты: /work/tools/actions step-NNNN печатает действия прогона по строке на ход, /work/tools/turn step-NNNN FROM [TO] выводит ходы целиком. По данным авторов, в трёх текстовых бенчмарках агент спускался к источникам в 22% запусков на лёгких задачах и в 44% на трудных.
Сколько это стоит и на чём проверено?
На этапе решения задача с WikiTrace в среднем по наборам стоит в 1,17 раза больше, чем с Insights Only, то есть с теми же уроками без смонтированных источников и без инструкции спускаться; средний результат выше на 3,2 пункта. Сумм в долларах в статье нет. Построение памяти требует одного вызова компилятора на тренировочную траекторию. Чтобы проверить, не объясняется ли отрыв бюджетом, авторы прогнали построители памяти конкурентов по тем же траекториям повторно: AWM девять раз, ExpeL и ReasoningBank по три. Их средние поднялись до 83,8, 83,3 и 82,8 и остались ниже 87,0 у Insights Only.
Все методы запускались на одном агенте: это Pi, терминальный агент, о котором мы рассказывали в разборе рабочего набора ИИ-агентов. По описанию харнесса, Pi работает в Docker-песочнице, запущенной с --network none. И агент, и компилятор используют deepseek-v4-flash (релиз от 23 апреля 2026 года) с высоким уровнем рассуждений; в базовом конфиге модель вызывается через OpenRouter. Бенчмарков пять (ALFWorld, ScienceWorld, PlanCraft, tau3-bench Retail, AppWorld), наборов задач восемь. Метрики у бенчмарков разные, поэтому 90,2 — это среднее разнородных показателей, а не процент решённых задач.
С GLM-5.3 в версии flash на среднем уровне рассуждений авторы прогнали три набора задач из PlanCraft и ScienceWorld: 92,7 у WikiTrace, 90,9 у Insights Only и 71,2 без памяти.
Regression считается так: для каждой задачи берётся исход большинства из трёх прогонов без памяти, затем доля провалов с памятью среди задач, где этот исход успешный. Сама метрика не доказывает, что провал вызвала память: повторный запуск без памяти даёт 9,7%.
Как запустить WikiTrace и перенести приём в своего агента?
По README, нужны Python 3.11+, uv, Node 20, Docker и ключ OpenRouter. Установка:
uv sync --extra dev cp .env.example .env # set OPENROUTER_API_KEY set -a; . ./.env; set +a scripts/setup/pi.sh # the Pi terminal agent at a pinned commit, with its patches scripts/setup/sandbox_image.sh # the --network none sandbox the agent runs in
Бенчмарки ставятся отдельными скриптами из scripts/setup/. Дальше build прогоняет агента без памяти на тренировочных задачах и компилирует память, run тестирует метод, analyze считает Gain и Regression.
uv run wikitrace build \
--config configs/alfworld.yaml \
--benchmark alfworld \
--suite valid-seen \
--trial 0
uv run wikitrace run \
--config configs/alfworld.yaml \
--benchmark alfworld \
--suite valid-seen \
--trial 0 \
--method wikitrace
uv sync --extra analysis
uv run wikitrace analyze all \
--runs outputs/ \
--out analysis/
Чтобы analyze посчитал метрики, нужны ещё тестовые запуски run с --method no-memory и --trial 0, 1 и 2: по ним определяется базовый исход каждой задачи. Шаги build и run вызывают модель через OpenRouter за деньги; цена полного прогона в README не названа.
Это код экспериментов, а не готовая библиотека. Перенести можно сам приём:
- Сохраняйте каждый прогон без правок: задачу, исход и лог ходов с рассуждением, действием и наблюдением.
- После прогона делайте один вызов компилятора с задачей, логом и исходом. На выходе разбор и не больше трёх уроков.
- Кладите каждый урок в отдельный файл с id исходного прогона, пометкой success или failure и путями к разбору и логу.
- Смонтируйте память только для чтения, дайте агенту чтение файлов и оболочку, добавьте индекс на каждый слой.
- В первое сообщение вставляйте уроки с id и исходом исходного прогона.
- В системный промпт перенесите условия спуска и три правила памяти.
- Измеряйте Gain и Regression раздельно. Формат CSV для своего метода описан в README модуля анализа.
Что авторы оставили открытым?
Первая оговорка: ссылка на источник не делает урок верным.
A source link lets the agent check an insight against its run but does not verify the insight.
«Ссылка на источник позволяет агенту сверить урок с его прогоном, но не верифицирует сам урок».
Вторая: все уроки кладутся в первое сообщение, поэтому промпт растёт вместе с памятью. Как искать уроки в памяти, которая не помещается в контекст, авторы называют задачей, которую работа оставляет открытой. Третья: причины деградации и мотивы спусков размечал LLM-судья по рассуждениям агента, а не по реальным причинам исхода.
Условия эксперимента тоже ограничивают выводы: память строилась один раз и не обновлялась во время тестов, а задач на правку кода в репозитории среди бенчмарков нет. Дальше стоит следить за рецензией ACL Rolling Review (цикл октября 2026 года) и независимыми воспроизведениями.
Изображение на обложке: фрагмент схемы из препринта Lee et al., arXiv:2611.14320, CC BY 4.0.
Источники
- https://arxiv.org/abs/2611.14320
- https://arxiv.org/html/2611.14320v1
- https://github.com/yukyeongleee/wikitrace
- https://github.com/yukyeongleee/wikitrace/blob/main/src/wikitrace/memory/README.md
- https://github.com/yukyeongleee/wikitrace/blob/main/src/wikitrace/harness/README.md
- https://github.com/yukyeongleee/wikitrace/blob/main/src/wikitrace/analysis/README.md
- https://github.com/yukyeongleee/wikitrace/blob/main/src/wikitrace/memory/prompts/descend.j2
- https://github.com/yukyeongleee/wikitrace/blob/main/configs/base.yaml
- https://github.com/yukyeongleee/wikitrace/blob/main/tests/analysis/fixtures/stats_suite_average.csv