Учебный гайд: Часть 19. Память агента на SQLite

Урок 2 из 5 в модуле «Часть 19. Память агента на SQLite»
Вы просматриваете урок без входа. Войдите, чтобы сохранять прогресс и проходить тесты.

Тема: Часть 19. Память агента на SQLite

Уровень сложности: Средний

Расчётное время изучения: 6-8 часов (теория 2 часа, практика 4-6 часов)

Предварительные требования: Базовые знания SQL и SQLite (создание таблиц, индексы, простые запросы)

Понимание архитектуры Qwen Code и системы хуков (части 1-4 курса)

Опыт работы с командной строкой и Python-скриптами

Знакомство с концепцией SDD (Specification-Driven Development)

Базовое понимание работы LLM и контекстных окон

Цели обучения: Самостоятельно развёртывать полноценную систему памяти агента на SQLite с таблицами events и memories, включая схему, хуки и механизм инъекции контекста

Критически оценивать, какие данные стоит сохранять в память агента, а какие категорически нельзя, и применять правила приватности и безопасности на практике

Реализовывать и настраивать фоновое обобщение памяти (аналог /dream) через скрипты dream_sqlite.py с вызовом LLM-API и контролировать его запуск

Отличать границу между оперативной памятью агента и устойчивыми спецификациями, перенося стабильные правила из memories в specs/, QWEN.md или навыки

Оптимизировать контекст запросов, применяя принцип «меньше — лучше»: фильтровать релевантные записи по тегам, ограничивать количество инжектируемых блоков, предотвращать «деградацию контекста»

Обзор: Эта часть курса посвящена созданию локального, прозрачного и полностью контролируемого слоя памяти для агентной разработки на базе SQLite. Встроенная память Qwen Code (QWEN.md, /remember, /forget, /dream) достаточна для большинства проектов, но при необходимости аудита, переноса между средами или кастомных правил очистки разработчик может построить собственную систему. Ключевая идея: события из сессий агента логируются через хуки в таблицу events, затем фоновым обобщением сжимаются в компактные памятки таблицы memories, которые инжектируются в контекст новых сессий. Важнейшее ограничение — память дополняет, но не заменяет спецификации: устойчивые правила должны мигрировать в specs/ или QWEN.md. Курс охватывает схему базы, два ключевых хука (log_event.py и inject_memory.py), подключение к Qwen Code, автоматизацию обобщения, приватность, а также принципы экономии контекста для предотвращения «деградации контекста».

Ключевые концепции: Двухуровневая архитектура памяти (events + memories): Сырые события хранятся в таблице events — это полный журнал действий агента: запросы, вызовы инструментов, результаты. Устойчивые выводы из этих событий компрессируются в таблицу memories — компактные, структурированные заметки. Разделение критически важно: events дают аудит и исходный материал для обобщения, memories — быстрый релевантный контекст для новых сессий. Без этого разделения контекст быстро раздувается неструктурированными данными.

Хуки qwen code (log event.py, inject memory.py): Хуки — это исполняемые скрипты, вызываемые в ключевых точках жизненного цикла сессии. log_event.py подключается к событиям UserPromptSubmit (отправка запроса), PostToolUse (после использования инструмента) и Stop (завершение сессии) — он записывает метаданные в events. inject_memory.py подключается к SessionStart и UserPromptSubmit — он читает релевантные записи из memories и добавляет их в контекст текущей сессии. Оба скрипта должны быть исполняемыми и корректно настроены в settings.json.

Фоновое обобщение (/dream для sqlite): Периодический процесс консолидации сырых событий в устойчивые памятки. В отличие от встроенного /dream, SQLite-версия работает офлайн: скрипт dream_sqlite.py читает events за период (например, --since 24h), вызывает LLM для суммаризации через API (DashScope/Bailian), и записывает результат в memories. Запуск через cron, вручную или после фаз проекта. Ключевое преимущество: полная прозрачность — человек может просмотреть и сырые события, и сжатые заметки.

Гигиена контекста и «деградация контекста»: Феномен, при котором большой нерелевантный контекст ухудшает качество ответов модели хуже, чем короткий точный. Исследования показывают: 300 релевантных токенов эффективнее 30 000 нерелевантных. Практические выводы: инжектировать не более 3-5 блоков памяти, фильтровать по тегам/категориям, удалять устаревшее, а не «уточнять», переносить часто нужные записи в QWEN.md как правила.

Граница память vs. спецификация: Память агента — оперативный слой для выявляемых паттернов, предпочтений и ошибок. Спецификации (specs/, QWEN.md, навыки) — обязательные для продукта правила. Когда фоновое обобщение находит устойчивое правило (например, «всегда обновлять CHANGELOG.md перед слиянием»), оно должно мигрировать из memories в соответствующую спецификацию. Память помогает обнаруживать, спецификации — закреплять обязательность.

Приватность и безопасность памяти: Память легко превращается в склад чувствительных данных. Обязательные правила: не логировать переменные окружения, обрезать ответы инструментов, не хранить секреты и персональные данные, ограничивать контекст 3-5 блоками, регулярно чистить устаревшее, не коммитить .db-файл (только схему и скрипты). Пример .gitignore предоставлен в курсе.

Full-text search (fts) в sqlite: Таблица memory_fts обеспечивает быстрый поиск по содержимому памяток. Используется функция snippet() для отображения контекста найденных совпадений. Позволяет находить релевантные записи по ключевым словам при инъекции в контекст или при ручном аудите.

Практические упражнения: Название: Развёртывание базовой схемы и первый хук

Проблема: Создайте директорию .qwen/memory, скопируйте schema.sql из учебника, инициализируйте SQLite-базу agent-memory.db. Затем создайте .qwen/hooks, скопируйте log_event.py, сделайте исполняемым. Настройте settings.json для подключения хука к событиям UserPromptSubmit и PostToolUse. Проведите одну тестовую сессию Qwen Code с простым запросом (например, «создай hello.py»). Проверьте, что события записались в базу.

Решение: 1. mkdir -p .qwen/hooks .qwen/memory

  1. cp "$TUTORIAL_DIR/examples/sqlite-memory/schema.sql" .qwen/memory/schema.sql
  2. sqlite3 .qwen/memory/agent-memory.db < .qwen/memory/schema.sql
  3. cp "$TUTORIAL_DIR/examples/sqlite-memory/hooks/log_event.py" .qwen/hooks/
  4. chmod +x .qwen/hooks/log_event.py
  5. Объедините конфигурацию из settings-hooks.example.json с вашим settings.json (не перезаписывайте модель и авторизацию)
  6. Запустите Qwen Code, выполните запрос
  7. Проверьте: sqlite3 .qwen/memory/agent-memory.db "select event_name, tool_name, substr(prompt,1,80), timestamp from events order by id desc limit 5;"

Ожидаемый результат: видны записи с типами UserPromptSubmit и PostToolUse.

Сложность: beginner

Название: Инъекция релевантной памяти в сессию

Проблема: Подключите inject_memory.py к событиям SessionStart и UserPromptSubmit. Создайте вручную 2-3 тестовые записи в таблицу memories с разными категориями (preferences, workflow, project). Запустите новую сессию Qwen Code с запросом, релевантным одной из категорий. Проверьте через логи или модификацию inject_memory.py с выводом в stderr, что правильные записи добавились в контекст.

Решение: 1. cp "$TUTORIAL_DIR/examples/sqlite-memory/hooks/inject_memory.py" .qwen/hooks/

  1. chmod +x .qwen/hooks/inject_memory.py
  2. Добавьте хуки в settings.json
  3. Создайте записи вручную через SQL или скопируйте manual-memory-example.sql
  4. Модифицируйте inject_memory.py временно: добавьте print(f"[DEBUG] Injecting: {path}", file=sys.stderr)
  5. Запустите сессию с запросом, связанным с вашей категорией
  6. Проверьте вывод: вы должны увидеть [DEBUG] Injecting: с правильными путями
  7. Убедитесь, что нерелевантные записи не инжектируются

Сложность: intermediate

Название: Фоновое обобщение с dry-run

Проблема: Установите dream_sqlite_qwen_example.py как dream_sqlite.py. Убедитесь, что у вас настроена переменная BAILIAN_API_KEY. Запустите обобщение за последние 24 часа в режиме dry-run. Проанализируйте вывод: какие события были выбраны, какие памятки предложены. Затем запустите без dry-run и проверьте результат в таблице memories.

Решение: 1. cp "$TUTORIAL_DIR/examples/sqlite-memory/dream_sqlite_qwen_example.py" .qwen/memory/dream_sqlite.py

  1. export BAILIAN_API_KEY=ваш_ключ
  2. python .qwen/memory/dream_sqlite.py --since 24h --dry-run
  3. Изучите stdout: там будет показан план — какие events выбраны, какие summaries сгенерированы
  4. Если результат удовлетворительный: python .qwen/memory/dream_sqlite.py --since 24h
  5. Проверьте: sqlite3 .qwen/memory/agent-memory.db "select path, substr(content,1,100), updated_at from memories order by updated_at desc;"
  6. Ожидаемый результат: новые компактные записи в memories, отражающие паттерны из events

Сложность: intermediate

Название: Миграция правила из памяти в спецификацию

Проблема: После нескольких сессий вы заметили, что агент систематически забывает обновлять CHANGELOG.md. Этот паттерн зафиксирован в memories как workflow/sdd-validation.md с заметкой. Ваша задача: оценить, стало ли это устойчивым правилом, и корректно перенести его в спецификацию проекта, удалив из memories или пометив как перенесённое.

Решение: 1. Найдите запись: sqlite3 .qwen/memory/agent-memory.db "select path, content from memories where path like '%validation%';"

  1. Проанализируйте частоту: сколько раз повторялась ошибка, подтверждало ли пользователь исправление
  2. Если правило устойчивое (≥3 подтверждения, критично для продукта):
  • Создайте или обновите specs/workflow/changelog.md или добавьте раздел в QWEN.md
  • Сформулируйте как обязательное правило: «Перед слиянием ветки фичи в main обновить CHANGELOG.md с секцией Unreleased»
  1. Пометьте в memories: UPDATE memories SET content = content || '\n\n[TRANSFERRED TO specs/workflow/changelog.md 2024-XX-XX]' WHERE path = 'workflow/sdd-validation.md';

Или удалите, если уверены в дублировании

  1. Проверьте в новой сессии: агент должен следовать правилу из спецификации, не требуя памяти

Сложность: advanced

Название: Аудит и очистка чувствительных данных

Проблема: При проверке базы вы обнаружили, что в events случайно попали строки с API-ключом в поле prompt (пользователь вставил его в запрос для теста). Также в memories есть запись с личным email тестировщика. Выполните аудит, найдите все чувствительные записи, очистите их, и внедрите защиту от повторения.

Решение: 1. Аудит events: sqlite3 .qwen/memory/agent-memory.db "select id, substr(prompt,1,200) from events where prompt like '%sk-%' or prompt like '%Bearer%' or prompt like '%@%.%';"

  1. Аудит memories: аналогичный запрос с поиском по content
  2. Удалите найденные записи: DELETE FROM events WHERE id IN (...); DELETE FROM memories WHERE path = '...';
  3. Проверьте FTS: DELETE FROM memory_fts WHERE docid IN (SELECT id FROM memories WHERE ...);
  4. Усильте log_event.py: добавьте фильтрацию — перед записью проверяйте prompt на регулярные выражения секретов, заменяйте на [REDACTED]
  5. Добавьте в .gitignore: .qwen/memory/agent-memory.db и любые .db-journal, .db-wal
  6. Документируйте правило в README проекта: «Никогда не вставляйте секреты в промпты»

Сложность: advanced

Кейсы: Название: AgentClinic: от оперативных заметок к продуктовой спецификации

Сценарий: Стартап разрабатывает сервис AgentClinic — публичную платформу сатирических отзывов об AI-агентах. Команда из 4 разработчиков использует Qwen Code с кастомной SQLite-памятью для координации. За 3 месяца накопилось 15 000 событий и 200 памяток в memories.

Задача: Проблема 1: Контекст новых сессий раздулся до 8000 токенов из-за нефильтрованной инъекции всех memories — модель стала «теряться» и игнорировать ключевые инструкции из QWEN.md. Проблема 2: Продуктовая договорённость о тональности отзывов («публичные и сатирические, не приватные обращения») жила только в memories, и разные разработчики трактовали её по-разному. Проблема 3: Новый разработчик не мог понять, почему определённые решения принимались, — memories не версионировались и не коммитились.

Решение: Команда ввела строгую фильтрацию в inject_memory.py: только записи с тегами, релевантными текущей задаче (определяемой по ключевым словам запроса), максимум 4 блока по 200 токенов каждый. Для продуктовых договорённостей создали процесс «memory triage» — еженедельно senior-разработчик просматривал новые memories и переносил устойчивые правила в specs/. Конкретно договорённость о тональности мигрировала в specs/mission.md с формулировкой «Все записи в AgentClinic публичны по умолчанию; сатирический тон — обязательный, приватные обращения запрещены». Схему и скрипты вынесли в отдельный репозиторий с версионированием, а .db-файл добавили в .gitignore — каждый разработчик хранил локальную копию, синхронизируясь через экспорт/импорт memories в виде SQL-дампов при необходимости.

Результат: Средний контекст сессии сократился с 8000 до 1200 токенов, при этом точность следования инструкциям (измерялась через ручную оценку 50 сессий) выросла с 64% до 91%. Продуктовые договорённости стали единообразными across командой. Новый разработчик смог разобраться в правилах за 2 часа чтения specs/ вместо 2 дней раскопок в памяти. Время на «memory triage» — 30 минут в неделю — окупилось снижением ошибок интерпретации.

Извлечённые уроки: Нефильтрованная инъекция всех memories хуже, чем отсутствие памяти — деградация контекста реальна и измерима

Продуктовые правила должны мигрировать в specs/ максимально быстро; memories — только инкубатор

Версионирование схемы и скриптов критично, но .db-файл не должен коммититься — это персональные данные и оперативный слой

Регулярный ручной аудит памяти (memory triage) необходим, полностью автоматическое обобщение рискует закрепить ошибочные паттерны

Связанные концепции: Гигиена контекста и «деградация контекста»

Граница память vs. спецификация

Приватность и безопасность памяти

Фоновое обобщение (/dream для SQLite)

Название: Финтех-стартап: приватность данных клиентов в памяти агента

Сценарий: Финтех-компания с 12 разработчиками использовала Qwen Code с SQLite-памятью для разработки системы обработки платежей. Память помогала отслеживать сложные бизнес-правила и частые ошибки интеграции с банковскими API.

Задача: Во время аудита безопасности обнаружили, что log_event.py записывал полные ответы API-банка в таблицу events, включая маскированные номера карт, суммы транзакций и внутренние идентификаторы клиентов. Также в memories накопились заметки с email и телефонами тестировщиков, использовавшихся для отладки SMS-уведомлений. База agent-memory.db случайно попала в коммит при спешном фиксе.

Решение: Немедленная реакция: ревокнутый коммит, ротация всех потенциально скомпрометированных ключей, уведомление регулятора по процедуре (данные были маскированными, но факт утечки — риск). Структурные изменения: переписан log_event.py с обязательной фильтрацией — регулярные выражения для PAN (даже маскированных), сумм, email, телефонов; ответы API обрезаются до статус-кода и message без payload. Внедрён pre-commit хук, блокирующий коммит любых .db-файлов. memories очищены через SQL-скрипт с логированием операций для аудита. Добавлена роль «privacy reviewer» в memory triage.

Результат: Инцидент ограничен, штрафов не последовало благодаря быстрому реагированию и маскированию исходных данных. Новая система фильтрации за 6 месяцев заблокировала 340 потенциальных утечек (измерено по срабатываниям регулярных выражений). Время разработчика на настройку фильтров — 4 часа — окупилось за первую неделю. Культура «privacy by design» встроена в процесс памяти агента.

Извлечённые уроки: «Маскированные» данные всё ещё чувствительны — регуляторы и этика требуют их исключения из любых логов

Техническая мера (.gitignore) недостаточна без pre-commit хука — человеческий фактор в спешке неизбежен

Фильтрация должна быть в log_event.py, не полагайтесь на «разработчики будут осторожны»

Аудит памяти должен быть таким же регулярным, как аудит кода — данные накапливаются незаметно

Связанные концепции: Приватность и безопасность памяти

Двухуровневая архитектура памяти (events + memories)

Хуки Qwen Code (log_event.py, inject_memory.py)

Советы по изучению: Начните с ручного прохождения всей цепочки: создайте схему, запустите один хук, проверьте базу вручную через sqlite3 CLI — так вы «почувствуете» поток данных, прежде чем автоматизировать

Ведите «лабораторный журнал» в отдельном файле: фиксируйте, какие SQL-запросы выполняли, что ожидали, что получили — это развивает интуицию отладки SQLite-памяти

Практикуйте принцип «сначала dry-run, потом реальность» с dream_sqlite.py: привычка проверять обобщение перед записью предотвращает загрязнение memories мусором

Создайте собственную «шкалу зрелости» для правил: 1 раз — заметка, 2 раза — проверить, 3 раза — кандидат в спецификацию. Это облегчает решение о миграции

Используйте аналогию с человеческой памятью: events — это «всё, что вы видели сегодня», memories — «записи в ежедневнике», specs/ — «подписанные контракты». Контракты имеют юридическую силу, ежедневник — оперативная помощь

Для визуального стиля: нарисуйте на бумаге диаграмму потока данных от события до инъекции, отмечая, где может произойти утечка или раздувание контекста — это активирует пространственное мышление

Парное обучение: если возможно, один человек настраивает log_event.py, другой — inject_memory.py, затем меняются ролями и ищут баги в чужой реализации — лучший способ найти edge cases

Регулярно выполняйте /clear в Qwen Code во время обучения — это тренирует осознанную работу с контекстом, а не накопление всего подряд

Дополнительные ресурсы: Оригинальные примеры курса (schema.sql, хуки, dream sqlite): Репозиторий sdd-qwen-code-ru/examples/sqlite-memory/ — первоисточник всех скриптов, копируйте отсюда, не переписывайте с нуля

Документация sqlite fts5: https://www.sqlite.org/fts5.html — для глубокого понимания полнотекстового поиска в таблице memory_fts

Статья venturebeat о памяти агентов anthropic: Упомянута в курсе; ищите по ключевым словам 'Anthropic agent memory sessions patterns' — концептуальная основа фонового обобщения

Часть 14 курса (гигиена контекста): part-14-build-your-own-workflow.md — обязательное дополнение для понимания, почему /clear и разделение ролей работают

Часть 4 курса (настройка api dashscope/bailian): Для корректной настройки BAILIAN_API_KEY в dream_sqlite_qwen_example.py

Owasp cheat sheet на логирование безопасности: https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html — расширение правил приватности для агентной памяти

Исследование 'lost in the middle' (stanford, 2023): Ключевая научная основа феномена деградации контекста; ищите по названию для понимания, почему позиция информации в контексте критична

Резюме: Память агента на SQLite — это локальный, прозрачный и полностью контролируемый слень для дополнения встроенной памяти Qwen Code. Ключевые принципы: разделение сырых событий (events) и устойчивых памяток (memories), хуки для логирования и инъекции, офлайн-фоновое обобщение через dream_sqlite.py, строгая граница между оперативной памятью и обязательными спецификациями. Главные риски — деградация контекста от избыточной инъекции и утечка чувствительных данных. Решения: фильтрация по релевантности, ограничение 3-5 блоков, регулярный аудит, фильтрация секретов в хуках, не-коммит .db-файлов. Успешная реализация требует дисциплины: память помогает обнаруживать правила, но спецификации делают их обязательными.

Мои заметки
0 / 10000

Заметки сохраняются в этом браузере. На другом устройстве они не появятся.

Меню курса

Курс

Разработка по спецификациям с Qwen Code CLI
Прогресс 0 / 135