Агент-инженер по репозиторию · Модуль 3 · Урок 3.4

Чекпойнт v2: память сессии и компакция истории

Зачем (какую проблему чиним)

Многошаговая задача накапливает длинную историю сообщений: старые tool-результаты (содержимое файлов, выводы тестов) распухают и съедают окно. Нужна память сессии с компакцией: удерживать суть, отбрасывать устаревшие детали — не ломая prompt caching.

Решение и альтернативы

Решение: менеджер истории, который (1) держит стабильный префикс (системный промпт, список инструментов) байт-в-байт неизменным ради кэша; (2) компактит хвост — старые большие tool-результаты заменяет краткими резюме («прочитан main.go, 120 строк; ключевое: …»); (3) хранит краткую «рабочую память» задачи (что уже выяснено, что осталось). Собираем рабочий агент версии v2 и тегируем v2.

Альтернативы: обрезать историю с начала — ломает кэш и теряет системный контекст; не компактить вовсе — упираемся в окно и стоимость. Компакция только хвоста при стабильном префиксе — правильный компромисс.

DIFF

Добавляем менеджер истории с компакцией хвоста и сохранением стабильного префикса; подключаем к циклу.

⚠ Безопасность

Компакция не должна затягивать в долговременную память секреты или вредоносные инструкции из прочитанных файлов (prompt injection). Резюмируем фактическое содержание, помечая внешний контент как данные, а не как инструкции. Это мостик к guardrails версии v4.

Проверка

Длинная сессия (десятки шагов) не упирается в окно: в логах видно, как старые tool-результаты сворачиваются в резюме, а usage.CacheReadInputTokens подтверждает, что префикс читается из кэша. Затем git tag v2 — рабочий read-only агент с retrieval и памятью.

Глубже

Архитектуры памяти (эпизодическая/семантическая/процедурная), консолидация и забывание — курс «Продакшн-разработка», Модуль 2 (гл. 4); компакция и стабильный префикс ради кэша — Модуль 1 (гл. 2).

history.go: компакция хвоста при стабильном префиксе (новый файл, фрагмент)
+package main
+
+import "github.com/anthropics/anthropic-sdk-go"
+
+// History управляет окном: стабильный префикс ради кэша + компакция хвоста.
+type History struct {
+	prefixLen int                       // первые N сообщений не трогаем (кэш)
+	msgs      []anthropic.MessageParam
+}
+
+// compact сворачивает старые крупные tool-результаты в краткие резюме,
+// НЕ затрагивая стабильный префикс (иначе инвалидируется prompt cache).
+func (h *History) compact(maxTokens int) {
+	for i := h.prefixLen; i < len(h.msgs)-keepRecent; i++ {
+		if isBulkyToolResult(h.msgs[i]) {
+			h.msgs[i] = summarize(h.msgs[i]) // "прочитан X, ключевое: ..."
+		}
+	}
+}

Anti-patterns

Грабли памяти и компакции
ГрабляПочему плохоКак правильно
Компактить/переписывать начало истории (системный префикс)Любой изменённый байт префикса инвалидирует prompt cache целиком — стоимость растётПрефикс держать неизменным; компактить только хвост (старые tool-результаты)
Обрезать историю простым отбрасыванием первых сообщенийТеряются системный контекст и инструменты; ломается кэшРезюмировать устаревшие детали, сохраняя суть и стабильный префикс
Затягивать в долгую память внешний контент как инструкцииPrompt injection из файла переживает компакцию и влияет на будущие шагиХранить внешний контент как данные с пометкой источника, не как инструкции

Практическое задание (RA-v2)

  • Добавить менеджер истории: стабильный префикс + компакция хвоста (резюме крупных tool-результатов).
  • Подтвердить чтение кэша по usage.CacheReadInputTokens на длинной сессии.
  • Зафиксировать версию: git commit -m "v2: session memory and compaction" и git tag v2.

Проверка знаний

Чтобы экономить, инженер добавил компакцию, которая суммирует и переписывает начало истории, включая системный промпт и список инструментов. Счёт за токены вырос.

Наиболее вероятная причина?

  • A Компакция всегда дороже, её нельзя применять
  • B Переписывание префикса инвалидирует prompt cache целиком — каждый запрос платит за холодную запись вместо дешёвого чтения
  • C Модель стала отвечать длиннее
  • D Эмбеддинги подорожали