Механическое против семантического: что происходит, когда память ИИ-агента ошибается

Соло-разработчик, который копит долгоживущий контекст агента через MCP, рискует не в галлюцинации модели, а в «чистой» механике: инструмент отработал, код выхода нулевой — а факт в памяти ложный. Разработчик @mansio на собственном MCP codebase-intelligence server провёл серию экспериментов и показал, что без ретракции и проверки при чтении «ленивый» агент принимает все ложные записи; для нас это прямой чеклист надёжности агентной памяти, а не абстрактная дискуссия про timestamps.
Где «успешный» вызов инструмента расходится с правдой
В статье разведены два слоя, которые в продакшене часто сливаются в один сигнал «всё ок».
Механическое исполнение — агент вызвал инструмент, код скомпилировался, exit code = 0. Семантическая истина — вывод соответствует реальности, а не только формальному успеху вызова.
Из механически успешного слоя нельзя автоматически вывести семантическую корректность — отсюда риск memory contamination, когда ложный факт закрепляется в долгоживущем контексте агента.
Автор противопоставляет свой подход отраслевому консенсусу вокруг timestamps и связок supersedes / contradicts: для downstream-артефактов — устаревшего кода, тестов, документации — этого недостаточно. Предлагаемый lifecycle: явный переход VERIFIED → REFUTED плюс проверка на границе retrieval.
Эксперимент на MCP-сервере с искусственной памятью
Площадка теста — собственный MCP codebase-intelligence server на Python, порядка 50K LOC. Персистентный слой — IntelligenceStore: агенты логируют инциденты и собирают Architectural Decision Records (ADRs).
Для измерений использован детерминированный proxy-agent на эвристиках без подключённого live LLM. Автор прямо оговаривает: результаты отражают структурную способность системы, а не поведение Claude или GPT в бою — сравнение с живыми моделями в эксперименте не измерялось.
В изолированное хранилище внесено 50 фактов:
- 25 TRUE — реальные детали архитектуры;
- 25 FALSE, из них 22 CONTRADICT (ложь, которую код явно опровергает; пример: «We use Redis» при фактическом DuckDB) и 3 SILENT (правдоподобная ложь про внешние системы, где репозиторий молчит; пример: «We use Celery for background tasks» без очереди задач).
Исходное API памяти — add-only: поиск по delete / refute в API дал 0 результатов.
Три режима агента и цифры загрязнения
Три конфигурации на одном наборе фактов (N=50), проверка по 6 осям (truth-table audit и независимый LLM-аудит «свежими глазами») — идентичные результаты.
| Режим | Correct | Принятые ложные факты | Способность к коррекции |
|---|---|---|---|
| B (No Memory) — только retrieval по коду | 0.94 | 0.0% | 0.0 |
| A_code_first (Honest Agent) — код первичен, память вторична | 0.94 | 12% | 1.0 |
| A_memory_first (Lazy Agent) — память первична, при ответе стоп | 0.50 | 100% | 0.0 |
Lazy Agent принял 100% ложных фактов — паттерн, который автор связывает с «token-optimizing production agents». 12% у Honest Agent — только на SILENT facts: память превращает UNKNOWN в уверенную галлюцинацию.
Явная ретракция вместо add-only памяти
Второй слой — механизм RetractionReceipt и MCP-tool intel_retract_memory_node для явной инвалидации узлов. Статусы узлов: ACTIVE, VERIFIED, REFUTED; pipeline load_memory пропускает только ACTIVE и VERIFIED.
Honest Agent в первой сессии может ретрактить; во второй — свежий memory_first читает память уже после ретракции.
| Метрика | Add-only | С ретракцией |
|---|---|---|
| Adoption (Lazy Agent, сессия 2) | 1.0 (100%) | 0.12 (12%) |
| Ложные факты в памяти | 25 | 3 (−88%) |
| Размер token-контекста | Baseline | −45% |
| Системная коррекция | 0.0 | 1.0 (22/22 опровергнуто) |
Оставшиеся 12% — те же SILENT facts: без сигнала в коде ретракция не срабатывает.
Verify-on-read: проверка при чтении
Пост автор обновил follow-up Experiment 1-V (ADR-0003): при load_memory() из текста узла извлекаются лёгкие anchors — имена файлов, импорты, env vars — и сверяются с live fingerprint кодовой базы на текущем git HEAD.
Правила статусов:
- anchor найден →
VERIFIED; - явное противоречие или ожидаемое отсутствие →
REFUTED; - иначе →
ACTIVE(какINCONCLUSIVE).
Бюджет: ≤50 ms на retrieval; TTL-кэш 30 s на git HEAD; в steady-state при cache hit — ~0.6 ms.
| Метрика | С ретракцией (1-R) | С verify-on-read (1-V) |
|---|---|---|
| Adoption (Honest Agent, A_code_first) | 0.12 (12%) | 0.0 (0%) |
| Adoption (Lazy Agent, A_memory_first) | 0.12 (12%) | 0.16 (16%) |
| SILENT-загрязнение (Honest) | 3 факта | 0 фактов |
Для соло-workflow с MCP-памятью вывод практичный: одной ретракции мало, если агент читает память раньше кода.
Остаточные дыры и что брать в свой агентный стек
Два ограничения verify-on-read зафиксированы в материале явно.
Present-trap: ложная запись «We use sqlite3» плюс реальный импорт sqlite3 в другом контексте → слой помечает VERIFIED; lazy adoption остаётся 0.16.
Anchor typing: prose «We use fastmcp» против фактического from mcp.server.fastmcp import ... даёт ложные REFUTED на верных фактах. Фикс — typed anchors на write-path, а не парсинг prose на read-path.
Cursor, IDE-rules и skills в материале не фигурируют — это агностичный паттерн поверх MCP и агентной памяти. Для разработчика в одиночку переносимый минимум: не оставлять память add-only; дать агенту инструмент ретракции; на чтении сверять anchors с живым репозиторием. Поведение live LLM в такой схеме в эксперименте не измерялось — это следующий слой, не опровержение структурных выводов.
Источники
- @mansio — The Mechanical vs. The Semantic: What Happens When AI Memory is Wrong? (Dev.to, тег
ai, опубликовано 11 августа 2026; доступ 12.08.2026)