Проблема памяти
Каждый раз, когда вы начинаете новую сессию с AI-агентом, происходит одно и то же: агент не помнит ничего. Ни ваших конвенций, ни решений, принятых час назад, ни ошибок, которые уже были исправлены. Каждая сессия -- tabula rasa.
Сессия 1: "Используй UUID v7 для первичных ключей"
→ Агент: "Понял, использую UUID v7" ✓
Сессия 2: "Создай новую сущность Product"
→ Агент: "Создаю с auto-increment ID" ✗
→ Человек: "Нет! UUID v7! Я же говорил!"
→ Агент: "Извините, исправляю" ✓
Сессия 3: "Создай сущность Category"
→ Агент: "Создаю с auto-increment ID" ✗
→ Человек: ... (╯°□°)╯︵ ┻━┻
Это не баг -- это фундаментальное свойство LLM. У них нет долговременной памяти. Контекстное окно -- это оперативная память, которая очищается при каждом перезапуске.
Memory Engineering -- это инженерная дисциплина создания систем внешней памяти, которые компенсируют отсутствие нативной долговременной памяти у AI-агентов.
Типы памяти агента
1. Context Memory (Контекстная память)
Это то, что агент "видит" прямо сейчас -- содержимое текущего контекстного окна.
| Характеристика | Значение |
|---|---|
| Объём | 100K-200K токенов (в зависимости от модели) |
| Срок жизни | Одна сессия |
| Скорость доступа | Мгновенная |
| Надёжность | Высокая (пока в окне) |
| Управление | Автоматическое (модель) |
Контекстное окно:
┌─────────────────────────────────────────────┐
│ System prompt │
│ AGENT.md (загружен) │
│ Текущий файл (открыт) │
│ История диалога │
│ Результаты предыдущих команд │
│ ─────────────────────────────────────────── │
│ [Здесь заканчивается то, что агент "знает"]│
└─────────────────────────────────────────────┘
Ограничение: при заполнении контекстного окна старая информация "выталкивается". Агент буквально забывает то, о чём говорили в начале длинной сессии.
2. Project Memory (Проектная память)
Персистентные файлы, которые загружаются при каждом запуске агента.
| Характеристика | Значение |
|---|---|
| Объём | Не ограничен (но ограничен контекстным окном) |
| Срок жизни | Постоянный (файлы на диске) |
| Скорость доступа | Требует чтения файла |
| Надёжность | Высокая (файловая система) |
| Управление | Ручное (человек) + автоматическое (агент) |
project/
├── CLAUDE.md # Instructions for AI agent
├── AGENTS.md # Build/test commands
└── .claude/
└── memory/
└── MEMORY.md # Persistent cross-session knowledge
Это самый важный тип памяти для практической работы. CLAUDE.md и MEMORY.md -- это "мозг" вашего агента между сессиями.
3. Learning Memory (Обучающаяся память)
Накопленный опыт, который делает агента эффективнее с каждой итерацией.
| Характеристика | Значение |
|---|---|
| Объём | Растёт со временем |
| Срок жизни | Постоянный с возможностью ротации |
| Скорость доступа | Требует поиска |
| Надёжность | Зависит от качества записей |
| Управление | Автоматическое (агент) + ручная модерация |
# Learning Memory — пример записи
## Solution: PostgreSQL JSONB query performance
**Problem**: JSONB queries slow on large tables (>500K rows)
**Solution**: GIN index on JSONB column + containment operator @>
**Context**: users table, 500K rows, metadata JSONB column
**Date**: 2026-02-15
**Confidence**: High (verified in production)
**Tags**: postgresql, performance, jsonb, indexing
4. Shared Memory (Командная память)
Знания, доступные нескольким агентам или членам команды.
| Характеристика | Значение |
|---|---|
| Объём | Большой (общая база знаний) |
| Срок жизни | Постоянный |
| Скорость доступа | Зависит от хранилища |
| Надёжность | Зависит от инфраструктуры |
| Управление | Командное |
Shared Memory примеры:
├── Team wiki / Confluence
├── ADR (Architecture Decision Records)
├── Shared CLAUDE.md conventions
├── Common troubleshooting guide
└── Reusable code snippets library
Реализация проектной памяти
Структура файлов памяти
project/
├── CLAUDE.md # Primary AI instructions
├── AGENTS.md # Build commands for AI agents
├── .claude/
│ └── memory/
│ └── MEMORY.md # Auto-updated cross-session memory
├── docs/
│ ├── architecture.md # System architecture
│ ├── decisions/ # Architecture Decision Records
│ │ ├── 001-use-uuid-v7.md
│ │ ├── 002-cursor-pagination.md
│ │ └── 003-event-driven-side-effects.md
│ └── troubleshooting.md # Known issues and solutions
CLAUDE.md: основная инструкция
CLAUDE.md -- это файл, который Claude Code автоматически загружает при каждом запуске. Это основной механизм проектной памяти.
# Project: E-Commerce API
## Critical Rules
- UUID v7 for all primary keys (NEVER auto-increment)
- declare(strict_types=1) in every PHP file
- final classes by default
- Repository pattern for data access
- No business logic in controllers
## Build Commands
- Test: `php bin/phpunit`
- Lint: `vendor/bin/phpstan analyse -l 9`
- Format: `vendor/bin/php-cs-fixer fix`
## Known Gotchas
- EasyAdmin CodeEditorField: no 'json' language — use 'javascript'
- Content import requires: `php -d memory_limit=2G bin/console app:content:import`
- security.yaml: specific ROLE_USER rules BEFORE general PUBLIC_ACCESS
MEMORY.md: автоматическая межсессионная память
MEMORY.md обновляется агентом в конце каждой сессии. Он содержит то, что агент "узнал":
# Project Memory
## Architecture
- Backend: Symfony 7.4 + PHP 8.4
- Frontend: Nuxt 3 SPA
- DB: PostgreSQL 18
- Cache: Redis 7
- Queue: RabbitMQ (Symfony Messenger)
## Recent Changes
- 2026-03-07: Added product reviews API (Review entity, ReviewService, ReviewController)
- 2026-03-06: Migrated from Paddle to free model
- 2026-03-05: Implemented Telegram notifications
## Discovered Patterns
- All repositories extend AbstractRepository with common CRUD methods
- All DTOs use Symfony Validator attributes for validation
- All controllers inherit from AbstractApiController with json() helper
- Error responses follow RFC 7807 format
## Known Issues
- Memory limit needed for content import (2G minimum)
- Google Calendar webhook requires real domain (not localhost)
- RabbitMQ occasionally loses connection — messenger:consume auto-restarts
## Troubleshooting
- "Class not found" after adding entity → run `composer dump-autoload`
- "Table not found" → run `php bin/console doctrine:migrations:migrate`
- Nuxt "#internal/nuxt/paths" error → `rm -rf .nuxt` + restart
Architecture Decision Records (ADR)
ADR фиксируют почему было принято конкретное решение. Это критически важно для AI-агентов, которые иначе могут "переизобрести" то, что уже было решено.
# ADR-001: Use UUID v7 for Primary Keys
## Status
Accepted
## Context
We need a primary key strategy for all entities.
Options considered:
1. Auto-increment SERIAL
2. UUID v4 (random)
3. UUID v7 (time-ordered)
## Decision
Use UUID v7 for all primary keys.
## Rationale
- UUID v7 is time-ordered → good B-tree index performance (unlike UUID v4)
- No coordination needed → works with distributed systems
- No information leakage → user can't guess IDs (unlike SERIAL)
- Sortable by creation time → implicit ordering without additional column
## Consequences
- Slightly larger storage (16 bytes vs 4 bytes for INT)
- Need UUID v7 generation library (symfony/uid)
- All foreign keys are UUID type
- Index size slightly larger
## Date
2026-01-15
Правило: Если вы приняли архитектурное решение -- запишите ADR. Через 3 месяца ни вы, ни AI-агент не вспомните, почему выбрали UUID v7 вместо auto-increment.
Реализация обучающейся памяти
Концепция Compound Learning
Compound Learning (составное обучение) -- это процесс, при котором каждая итерация Ralph Loop добавляет знания, используемые в последующих итерациях.
Итерация 1: Агент создаёт User entity
→ Записывает: "Entity pattern: UUID v7 PK, timestamptz for dates"
Итерация 5: Агент создаёт Order entity
→ Читает: "Entity pattern: UUID v7 PK, timestamptz for dates"
→ Результат: корректный с первой попытки
Итерация 10: Агент создаёт Review entity
→ Читает: "Entity pattern: UUID v7 PK, timestamptz for dates"
→ Дополнительно записывает: "Entities with user ownership need userId field + ownership check in service"
Итерация 20: Агент создаёт Comment entity
→ Знает всё: UUID v7, timestamps, userId, ownership check
→ Качество кода максимальное
Качество кода vs. Количество итераций:
Итерация 1: ████████ 70%
Итерация 5: ██████████████ 85%
Итерация 10: ████████████████ 90%
Итерация 20: ██████████████████ 95%
Итерация 50: ███████████████████ 97%
Стандартная библиотека (stdlib)
Концепция "stdlib" для AI-агентов -- это набор проверенных, многоразовых компонентов, которые контролируют качество генерации кода.
stdlib/
├── templates/
│ ├── entity.php.tpl # Reference entity template
│ ├── repository.php.tpl # Reference repository template
│ ├── service.php.tpl # Reference service template
│ ├── controller.php.tpl # Reference controller template
│ ├── dto-request.php.tpl # Reference request DTO template
│ ├── dto-response.php.tpl # Reference response DTO template
│ └── unit-test.php.tpl # Reference test template
├── patterns/
│ ├── pagination.md # How to implement cursor pagination
│ ├── error-handling.md # Error handling patterns
│ ├── validation.md # Validation patterns
│ └── authentication.md # Auth patterns
└── examples/
├── ProductController.php # Complete working example
├── ProductService.php # Complete working example
└── ProductServiceTest.php # Complete working example
Когда агент создаёт новый контроллер, он смотрит на шаблон и примеры, а не выдумывает с нуля. Это радикально повышает консистентность.
# In AGENT.md:
## Reference Templates
When creating new files, ALWAYS look at these references first:
- New entity → see stdlib/templates/entity.php.tpl
- New repository → see stdlib/templates/repository.php.tpl
- New service → see stdlib/templates/service.php.tpl
- New controller → see stdlib/templates/controller.php.tpl
- New test → see stdlib/templates/unit-test.php.tpl
## Working Examples
For complete implementation reference:
- src/Controller/ProductController.php (exemplary controller)
- src/Service/ProductService.php (exemplary service)
- tests/Unit/Service/ProductServiceTest.php (exemplary test)
Категории обучающейся памяти
Записи в обучающейся памяти делятся на категории:
1. Решения (Solutions):
## Solution: Circular dependency in Symfony services
**Problem**: ServiceA depends on ServiceB, ServiceB depends on ServiceA
**Solution**: Extract shared logic into ServiceC, both depend on ServiceC
**Alternative considered**: Use lazy injection — rejected (hides design problem)
**Date**: 2026-03-01
**Tags**: symfony, di, architecture
2. Ошибки (Mistakes):
## Mistake: Raw SQL in service layer
**What happened**: Agent wrote raw SQL query in OrderService
**Why it's wrong**: Violates repository pattern, untestable, SQL injection risk
**Correct approach**: Add method to OrderRepository, call from service
**Prevention**: Added explicit rule to AGENT.md
**Date**: 2026-02-28
**Tags**: architecture, anti-pattern
3. Паттерны (Patterns):
## Pattern: Cursor-based pagination in this project
**Implementation**:
1. Repository method accepts `?string $cursor` and `int $limit`
2. If cursor provided, add `WHERE id > :cursor` to query
3. Return items + `next_cursor` (last item's ID) or null
4. Controller passes cursor from query parameter
**Reference**: src/Repository/ArticleRepository.php::findPaginated()
**Tags**: pagination, api, repository
4. Конвенции (Conventions):
## Convention: Naming patterns in this project
**Entities**: Singular PascalCase (Order, not Orders)
**Repositories**: {Entity}Repository (OrderRepository)
**Services**: {Domain}Service (OrderService, not OrderManager or OrderHandler)
**DTOs**: {Action}{Entity}Request/Response (CreateOrderRequest, OrderResponse)
**Controllers**: {Entity}Controller (OrderController)
**Tests**: {Class}Test (OrderServiceTest)
**Tags**: naming, conventions
Стратегии поиска по памяти
Полнотекстовый поиск
Простейший подход -- grep по файлам памяти:
# Search memory files for relevant information
grep -r "pagination" docs/ MEMORY.md CLAUDE.md
# Search for solutions to a specific problem
grep -r "JSONB" docs/troubleshooting.md docs/decisions/
AI-агент может использовать эту стратегию при каждой итерации:
# In PROMPT.md:
## Before implementing any task:
1. Search MEMORY.md for related solutions: grep -i "{keywords}" MEMORY.md
2. Search troubleshooting.md for known issues: grep -i "{keywords}" docs/troubleshooting.md
3. Search ADRs for relevant decisions: grep -rl "{keywords}" docs/decisions/
Семантический поиск (Embeddings)
Для больших баз знаний -- поиск по смыслу, а не по точному совпадению:
Запрос: "как сделать пагинацию в API"
Результат: документ о cursor-based pagination (даже если слово "пагинация" не упоминается)
Инструменты: MCP Memory (встроен в Claude Code), Pinecone, Weaviate, ChromaDB.
Тегирование
Каждая запись в памяти содержит теги для быстрой фильтрации:
## Solution: Fix N+1 query problem
**Tags**: performance, database, doctrine, orm
## Convention: API error format
**Tags**: api, errors, rfc7807, conventions
# Find all memory entries tagged with "performance"
grep -B5 "Tags:.*performance" MEMORY.md docs/**/*.md
Ранжирование по свежести
Недавние записи имеют больший приоритет, чем старые:
# Memory entries ordered by date (newest first):
## 2026-03-07: Review entity uses embedded value objects for ratings
## 2026-03-05: Telegram notifications via Messenger async
## 2026-02-28: Cursor pagination pattern established
## 2026-02-15: JSONB GIN index solution discovered
## 2026-01-20: UUID v7 decision made (see ADR-001)
Правило: При конфликте между старой и новой записью -- доверяйте новой. Проект эволюционирует, и старые решения могут устареть.
Антипаттерны памяти
1. Слишком много памяти
Проблема: MEMORY.md на 5000 строк.
Последствие: Занимает 80% контекстного окна, не оставляя места для кода.
Решение: Разделить на файлы по категориям, загружать только релевантные.
Правильная структура:
├── MEMORY.md # 50-100 строк — ключевые факты
├── docs/
│ ├── solutions.md # Загружать при troubleshooting
│ ├── conventions.md # Загружать при создании кода
│ ├── decisions/ # Загружать при архитектурных вопросах
│ └── troubleshooting.md # Загружать при ошибках
2. Слишком мало памяти
Проблема: Только CLAUDE.md с 10 строками.
Последствие: Агент повторяет одни и те же ошибки каждую сессию.
Решение: Добавить MEMORY.md, troubleshooting.md, ADR-ы.
3. Устаревшая память
Проблема: MEMORY.md говорит "используем Paddle для платежей",
но Paddle был удалён 2 недели назад.
Последствие: Агент пытается интегрироваться с несуществующей системой.
Решение: Обновлять память при каждом значимом изменении.
4. Противоречивая память
Проблема: CLAUDE.md: "Используй UUID v4"
MEMORY.md: "Используй UUID v7"
ADR-001: "Решение: UUID v7"
Последствие: Агент "угадывает", какому источнику верить.
Решение: Единственный источник истины. CLAUDE.md — главный.
При обновлении — обновлять ВСЕ файлы.
Обслуживание памяти
Регулярная очистка
# Monthly memory maintenance checklist
## MEMORY.md
- [ ] Remove resolved issues from "Known Issues"
- [ ] Update "Recent Changes" — remove entries older than 30 days
- [ ] Verify "Architecture" section matches actual stack
- [ ] Check "Discovered Patterns" — still accurate?
## Troubleshooting
- [ ] Remove solved issues that won't recur
- [ ] Update solutions for issues that changed
- [ ] Add new issues discovered this month
## ADRs
- [ ] Mark superseded decisions as "Superseded by ADR-XXX"
- [ ] Add new decisions made this month
- [ ] Verify existing decisions still apply
Консолидация
Когда несколько записей описывают одно и то же -- объединяйте:
# Before consolidation:
## Solution: Redis connection timeout (2026-01-15)
## Fix: Redis reconnection issue (2026-02-01)
## Workaround: Redis drops connection (2026-02-20)
# After consolidation:
## Solution: Redis connection stability
**Problem**: Redis connections drop under load or after idle period
**Root cause**: Default timeout too low (60s), no keepalive
**Solution**: Set timeout=300, tcp-keepalive=60 in redis.conf
**History**: First seen 2026-01-15, root cause found 2026-02-20
Валидация против реального состояния
#!/bin/bash
# validate-memory.sh — Check if MEMORY.md matches reality
echo "=== Memory Validation ==="
# Check if mentioned files exist
grep -oP 'src/[^\s]+\.php' MEMORY.md | while read -r file; do
if [ ! -f "$file" ]; then
echo "WARNING: $file mentioned in MEMORY.md but does not exist"
fi
done
# Check if mentioned commands work
grep -oP '`[^`]+`' MEMORY.md | grep -E '^`(php|npm|go)' | tr -d '`' | while read -r cmd; do
echo "Testing: $cmd"
eval "$cmd" >/dev/null 2>&1 && echo " OK" || echo " FAILED"
done
echo "=== Validation complete ==="
Практические инструменты
Claude Code MCP Memory
Claude Code имеет встроенную систему памяти через MCP (Model Context Protocol):
Доступные операции:
├── memory_save — Сохранить факт/решение/урок
├── memory_recall — Найти по ключевым словам
├── memory_search — Семантический поиск
└── memory_list — Показать все записи
Преимущество MCP Memory: семантический поиск (по смыслу, а не по ключевым словам).
Obsidian для человеческой памяти
Obsidian vault/
├── sessions/
│ ├── 2026-03-07.md # What was done today
│ ├── 2026-03-06.md
│ └── ...
├── Memory.md # Current project state
├── Tasks.md # Active tasks
├── Decisions.md # Architecture decisions
└── Troubleshooting.md # Known issues
Двойная система хранения
Оптимальный подход -- хранить знания в двух системах одновременно:
Obsidian (для человека):
+ Читаемые отчёты
+ Богатое форматирование
+ Связи между заметками
+ Визуализация графа знаний
MCP Memory (для агентов):
+ Семантический поиск
+ Быстрый доступ из кода
+ Автоматическая индексация
+ Кросс-сессионная доступность
Правило: Сохраняйте в ОБЕ системы. Obsidian -- подробно для человека. MCP Memory -- кратко для машинного поиска.
Выводы
-
Память -- это инженерная система, а не случайные заметки. Она требует проектирования, поддержки и валидации.
-
Четыре типа памяти: контекстная (в сессии), проектная (CLAUDE.md), обучающаяся (compound learning), командная (shared knowledge).
-
CLAUDE.md + MEMORY.md -- минимум. Без этих файлов каждая сессия начинается с нуля. С ними -- агент "помнит" проект.
-
Stdlib повышает консистентность. Шаблоны и эталонные примеры -- лучший способ контролировать качество генерации.
-
Память нужно обслуживать. Устаревшая или противоречивая память хуже, чем отсутствие памяти.
-
Compound Learning -- конкурентное преимущество. Агент, который учится на каждой итерации, через 50 итераций работает на порядок лучше, чем агент без памяти.