Перейти к содержимому

Память и знания

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

В ней три уровня, и они отвечают на разные вопросы:

  1. Факты — то, что верно (соглашение, результат, решение).
  2. Политики — что агенты должны с этим делать (нормативное правило).
  3. Рабочая память — то, чем занимался конкретный агент.

Различие важно, потому что до агента они доходят разными путями. Факты ищутся. Политики передаются принудительно. Рабочая память приватна.

MemoryFact — единица знания, привязанная к рабочему пространству и домену.

Атрибут Что это
domain Домен знаний (“conventions”, “decisions”, “codebase”)
topic Короткая метка темы
content Текст знания
confidence 0.0–1.0; задаётся по происхождению и повышается при повторном упоминании
memoryType Вид факта — определяет кривую его временного затухания
veracity Как знание было получено — задаёт уверенность и размер каждого прироста за повторное упоминание
sourceObservationIds Какие наблюдения привели к нему
supersededBy Более новый факт, который его заменил, если он есть
validUntil, recallCount, mentionCount Сигналы истечения срока и использования, учитываемые при извлечении

Последние две строки обычно упускают, а именно они решают, какой факт всплывёт. memoryType несёт параметры затухания по Вейбуллу для своего типа, поэтому обязательство с ограниченным сроком быстро угасает, а устойчивый факт профиля — нет. veracity фиксирует происхождение — сообщено человеком (вес 1.0), выведено агентом (0.7), получено инструментом (0.5), импортировано (0.6) — и этот вес задаёт начальную уверенность факта.

Когда факту противоречат, его никогда не правят на месте. Запись факта запускает обнаружение конфликтов с фактами того же домена и темы и заменяет проигравшего, создавая строку конфликта. Смысл именно в журнале аудита: всегда видно, что считалось верным раньше и что это заменило.

MemoryPolicy — нормативное правило, выведенное из фактов, привязанное к рабочему пространству и домену, с флагом активности и необязательным requiredRole.

Каждая активная политика рабочего пространства подставляется в каждый запуск без фильтрации — без отбора по домену, роли, задаче или пространству. Это стоит знать, прежде чем писать двадцатую политику: политики конкурируют за то же контекстное окно, что и задача. Поэтому же requiredRole у политики носит рекомендательный характер: он описывает, на кого нацелено правило, но не мешает правилу дойти до всех остальных.

MemoryDomain группирует факты и политики внутри рабочего пространства. Домены придают знаниям организационную структуру, и именно к ним привязываются разрешения доступа, — но прежде чем считать домен границей конфиденциальности, прочитайте предостережение ниже.

Домен либо охватывает всё рабочее пространство (architecture), либо привязан к одному репозиторию (repo:<slug>/architecture). Одно и то же имя в обеих областях — это два независимых хранилища: факт, верный для одной кодовой базы, не перезаписывает факт уровня рабочего пространства. search_memory и преамбула запуска ставят память, привязанную к репозиторию, на первое место, когда агент работает в этом репозитории; остальную они не отсеивают. Передайте repo в propose_fact / propose_policy / search_memory, чтобы писать в эту область или усиливать её.

Контроль доступа разрешает чтение при сбое

Заголовок раздела «Контроль доступа разрешает чтение при сбое»

MemoryAccessGrant сопоставляет роль агента и домен одному из трёх уровней разрешений:

Разрешение Значение
none Нет доступа
read Может искать и извлекать факты
write Требуется для propose_policy. Запись фактов (propose_fact, supersede_fact) идёт без разрешения

Асимметрия — мягкость к чтению, строгость к записи политик — это осознанный компромисс. Память приносит больше пользы, когда циркулирует, а запрет на чтение порождает агента, который молча знает меньше, вместо агента, который сообщает о проблеме. Отказ в записи политики, напротив, заметен и исправим, поэтому именно там и стоит принуждение. Новому домену сразу задаётся write для всех ролей; ужесточить его потом можно только правкой через RPC, потому что интерфейса разрешений нет.

У каждого агента есть AgentWorkingMemory — черновик в свободной форме, привязанный к рабочему пространству и агенту. Он переживает запуски, приватён для этого агента и подставляется в его промпт при каждом запуске. Именно там живёт «я остановился на середине рефакторинга auth» — состояние, которое стоит перенести в следующий запуск, но не стоит повышать до долговечного факта.

Что на самом деле попадает в промпт агента

Заголовок раздела «Что на самом деле попадает в промпт агента»

При запуске преамбула памяти собирается ровно из трёх вещей:

  • Каждая активная политика рабочего пространства — строками - [domain] rule.
  • Собственная рабочая память агента — дословно.
  • Отобранный по ключевым словам короткий список фактов для этой задачи — не более пяти, в пределах бюджета ~1,200 символов и только если описание задачи не короче 20 символов. Более короткие задачи не получают фактов вовсе.

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

На этом пути разрешения доступа не проверяются. Что нашёл короткий список, то агент и видит.

Доступный агентам инструмент search_memory имеет три режима, и это действительно разные виды поиска:

  • keyword — только FTS5.
  • semantic — результаты BM25 и векторного поиска, объединённые взаимным ранговым слиянием.
  • hybrid (по умолчанию) — многоголосое извлечение: четыре ранжированных голоса сливаются, затем диверсифицируются.

Четыре голоса — лексический (FTS), семантический (векторный KNN), временной (недавние активные факты) и графовый — двухшаговый обход эпизодических рёбер от сильнейших лексических и семантических затравок. Графовый голос — причина, по которой эпизодические рёбра вообще существуют: он выводит на поверхность факт, связанный с вашим ответом, хотя ни одно ваше слово с ним не совпадает. Голоса взвешиваются по классифицированному намерению запроса (семантический по умолчанию весит больше всего, затем графовый и лексический, затем свежесть), оценка каждого кандидата масштабируется его затуханием по Вейбуллу, а набор результатов диверсифицируется по MMR, чтобы пять пересказов одного факта не вытеснили четыре разных.

Поиск по памяти в десктопном и веб-клиенте — отдельный, более простой путь: RPC-операция memory_fact.search работает только по FTS5, потому что тонкий клиент не может передать эмбеддинг запроса, а гибридный путь остаётся внутри хоста. Поэтому ранжирование, которое вы видите в браузере памяти, — не то, что агент получает от search_memory. Это ожидаемо, а не ошибка, но это значит, что «я искал и не нашёл» в интерфейсе не доказывает, что агент не найдёт.

Браузер памяти находится в разделе Настройки → Рабочее пространство → Память (/workspaces/<id>/settings/memory), с вкладками «Факты», «Политики» и «Граф знаний».

Там есть асимметрия, которая удивляет людей: память можно редактировать и удалять, но нельзя создавать. Ни на вкладке «Факты», ни на вкладке «Политики» нет кнопки добавления. Создание выполняется на стороне агента — через propose_fact и propose_policy (для замены — supersede_fact / supersede_policy). remember записывает элемент горячего уровня, привязанный к сессии, который consolidate_memory позже может повысить до факта; record_observation и update_my_notes пишут приватный черновик, подставляемый при запуске. Браузер — это интерфейс для просмотра и исправления, а не для создания, поэтому если вы хотите, чтобы факт попал в память, проще всего сказать об этом агенту.

Две операции обслуживания тоже запускает агент, а не расписание: consolidate_memory объединяет и прореживает накопленные факты, а harmonize_memory согласует представления, разошедшиеся между агентами. list_memory_conflicts показывает, что уже зафиксировало обнаружение конфликтов. Ничто не запускает их за вас по таймеру. Решения со встреч попадают в домен decisions, когда шаг сохранения встречи их записывает; это не таймер по завершённым запускам агентов.