Общая память агента, проверяемая по мере изменения вашего кода.
Loom — это инструмент с открытым исходным кодом, построенный на базе ClickHouse. Он предоставляет агентам по написанию кода общий индекс кода и место для хранения полученных знаний, чтобы следующий сеанс не начинался с нуля.
Согласно нашим собственным тестам, внедрение Loom повысило средний показатель качества ответов на вопросы по коду ClickHouse с 0,78 до 0,84.
GroeneAI, наш автономный участник разработки, работает с пулл-реквестами ClickHouse с марта: воспроизводит сбои CI, ищет ошибки и недостающие тесты, а также сопровождает свои собственные PR в процессе проверки; к октябрю у него было более 3000 объединенных пулл-реквестов. Однако эти цифры скрывают раннюю слабость: каждый сеанс GroeneAI начинался практически с нуля.
Начинать с нуля стало настоящим бременем. У каждой ветки был относительно нормальный жизненный цикл: сборка, ночной запуск CI, рецензент, который возвращался позже на неделе, обходной путь, выявляющий тест, ставший нестабильным со вторника. Стандартные практики и причуды, которые накапливались, приводили к острой нехватке возможности начать работу с текущего состояния истории, не имея никакой памяти о линейной истории вообще. Без памяти агент перестраивает всю линейную историю, чтобы принять решение, которое необходимо в данный момент, или, что еще хуже, угадывает. С памятью он просто… помнит. В одном сеансе GroeneAI запомнил, что у конкретной логической ошибки было два места возникновения, а открытое исправление охватывало только одно, проверил код и указал сопровождающему на правильное место.
Поэтому мы отправились на поиски системы памяти. Мы запустили два самых мощных инструмента памяти для агентов, которые смогли найти, бок о бок на реальном трафике в течение трех месяцев, и оба улучшили ответы агента. Попутно они приняли более 82 000 записей в память и 328 миллионов символов собственных транскриптов агента, так что мы получили очень хорошее представление о том, что они могут, а что нет.
Инструменты памяти запоминали то, что агент писал о коде, но сами не могли видеть код. ClickHouse — это более 92 000 файлов и 318 000 коммитов в основной ветке, написанных примерно 2700 людьми за эти годы, а медианный файл был отредактирован шестью разными авторами. Для сравнения, это больше коммитов, чем в GCC, MySQL или Kubernetes. Никто не может (и не должен) держать в голове всю хронологию коммитов, и инструменты памяти тоже не могли. Хотя воспоминания о коде сохранялись, сам поиск кода оставался локальным. Локальный поиск кода вел собственный закрытый индекс и не мог сказать вам, какая функция вызывала какую или как все части сочетаются друг с другом. Поиск кода и рассуждения о нем должны были сходиться в одной системе, а не в двух, которые случайно оказались рядом в Terminal.app на ноутбуке разработчика.
На этом этапе мы прекратили оценку и начали разработку. Нам нужна была память, которая понимала бы репозиторий так же хорошо, как и транскрипты, которая позволяла бы нам повторно использовать то, что узнал GroeneAI, и делиться этим с людьми и другими агентами, не раскрывая ничего конфиденциального. Так появился Loom.
Loom хранит память и индекс кода в одной базе данных ClickHouse под одним набором прав доступа. Заметка сопровождающего сохраняется вместе с исходным кодом и привязывается к коду, который она описывает, поэтому позже можно определить, остается ли она точной. Каждый запуск также регистрируется: что загрузил агент, сколько это стоило и завершился ли он на самом деле.
Это проект с открытым исходным кодом, и любая команда может запустить его для своего репозитория со своими агентами.
Память и индекс кода отлично работают по отдельности, но они созданы для совместной работы! Клиент подключается через MCP, HTTP API или SDK для Python и TypeScript, и это одно соединение может сохранять воспоминания, искать код, записывать запуски и искать документы.
Как бы мы ни любили доверять броским авторитетным постам в блогах в наши дни, мы хотели бы объяснить некоторые концепции того, что отличает Loom от других инструментов памяти и какие проектные решения были приняты по пути.
Факты, предпочтения и пошаговые процедуры появляются при обычном поиске. Размышления о завершенной работе, прошлых событиях, справочные профили и черновики по текущей работе в основном остаются в стороне, пока что-то специально их не запросит.
Факты пересматриваются, а не просто накапливаются и устаревают. Скажем, агент отмечает в марте, что сервис по умолчанию использует max_threads: 16, а затем в июне узнает, что значение по умолчанию удвоилось. Июнь не стирает март, это новая версия того же факта, а старое значение все еще там, если вы спросите, что было правдой в апреле. Если два человека сохраняют противоречивые факты по схожим темам, Loom помечает это, а не просто выбирает один, а закрепление (pin) предотвращает автоматическую перезапись факта, который важен для кого-то. Как и ваш собственный мозг, воспоминания развиваются с новым контекстом, но сохраняют историю того, что вы узнали и когда! Просто приятно иметь возможность записать их в базу данных, вместо того чтобы перебирать все те тетради, которые собирают пыль под вашей детской кроватью.
Документы, процедуры и разовые задачи получают такое же отношение: доступны для поиска, когда это уместно, в остальное время не мешают. Факт о коде также сверяется с фактическим определением и помечается, если этот код меняется. Люди отлично запоминают состояние и изменения состояния в коде, за который они отвечают, но в постоянно растущем репозитории, таком как ClickHouse, было бы неразумно ожидать, что каждый человек будет централизовать состояние и изменения состояния работы каждого другого человека.
Прежде чем агент о чем-то спросит, Loom уже прочитал репозиторий: каждую функцию, каждый класс и то, какие из них вызывают другие. Спросите, где что-то реализовано или что вызывает данную функцию, и вы получите реальный код и пути к файлам, а не просто текст, который соответствует вашим поисковым запросам, или наше любимое: «Дайте мне прочитать код, прежде чем я на что-то отвечу!», сопровождаемое полным клонированием. Быстрый проход охватывает большинство языков; более медленный, точный с точки зрения компилятора проход подстраховывает его для крупных, и побеждает тот, который точнее.
Тот же индекс сообщает Loom, когда сохраненная память может устареть. Если в заметке говорится, что функция утекает буфер при двойном вызове, а эта функция переименовывается, Loom отслеживает переименование. Если вместо этого функция переписывается, заметка помечается для проверки, а не просто тихо устаревает. Ничего не переписывается автоматически. Помеченная память просто отображается как измененная, чтобы тот, кто прочитает ее в следующий раз, знал, что нужно перепроверить. Представьте себе кучу стикеров на вашем ментальном мониторе, которые указывают на все те моменты, когда вы понимали, что вам нужно что-то поискать, чтобы оставаться экспертом в предметной области… может быть, это было бы неплохо. Но было бы еще лучше, если бы каждый мог использовать стикеры друг друга, чтобы у нас не было сотен банков памяти, производящих сотни одних и тех же или похожих фактов. Было бы здорово иметь возможность делиться ими, не так ли?
Допустим, один разработчик использует Claude Code, чтобы выяснить, к чему приведет определенное изменение, а его коллега — Codex на другом ноутбуке, чтобы это изменение реализовать. Если они оба обращаются к одному и тому же развертыванию Loom, выводы Claude Code сразу же доступны при запуске Codex (включая исходный код и коммиты), поскольку оба агента читают и пишут в одно и то же пространство имен.
Вы можете настраивать, к какой именно стороне этого процесса имеет доступ каждый агент. Дело не в том, что мы просто объединили память всех участников в одно пространство имен и предложили им «бороться за выживание». Мы используем несколько отработанных сценариев:
- Однонаправленный: когда агент-исследователь выполняет запись, а агент-программист — чтение. Подходит для снижения затрат на инференс, когда основные ресурсы вкладываются в исследование и постановку задач. Это похоже на правило «семь раз отмерь, один раз отрежь», но вы помните буквально каждое измерение, которое когда-либо делали.
- Двунаправленный / многонаправленный: когда оба или все агенты выполняют чтение и запись. Подходит для внутренних баз знаний о корпоративной культуре и сленге. «К какой команде обратиться по теме X», «Канал в Slack лучше всего подходит для вопроса Y» и, что самое главное: «С чего это вдруг все стали использовать этот случайный эмодзи?».
- Промоушен из личного в общее: когда пользователь читает общее командное пространство имен, но пишет в свое собственное, а после готовности к публикации переносит данные на общий уровень. Команды могут настраивать пространство имен как открытое, доступное только по одобрению или закрытое — точно так же, как и любые другие средства контроля доступа. Подходит для команд, которым необходимо совместно поддерживать единый стиль и архитектурные решения своего кодовой базы (подсказка: ClickHouse), гарантируя, что воспоминания, подобно коду, можно проверять и поддерживать в актуальном состоянии.
Когда агент задает вопрос памяти, Loom не ограничивается одним поиском ближайших соседей. Система встраивает вопрос в векторное представление и выполняет несколько поисковых запросов в ClickHouse одновременно: векторный поиск по эмбеддингам фактов, текстовый поиск по ключевым словам с оценкой BM25 по тем же фактам, проход по буквальным фрагментам длинных значений и, если в вопросе упоминаются люди или службы, переход по графу сущностей. Каждый из этих этапов ограничивается пространствами имен, которые вызывающий абонент имеет право читать непосредственно в самом запросе, без последующей фильтрации.
Полученные результаты объединяются в единый рейтинг. Уверенность, происхождение и подкрепление из прошлых запусков могут скорректировать близкие значения, но их влияние ограничено, чтобы они не могли затмить более точное совпадение. Наконец, Loom проверяет показатель сырой схожести победителя без применения предыдущих весов. Если рейтинг схожести не превосходит результаты с менее релевантным ранжированием, поиск все равно возвращает совпадения, но сообщает агенту, что ответ неизвестен, и помечает их как слишком слабые для формирования ответа. Каждый результат содержит оценки, которые привели его к этой позиции.
Операции записи проходят аналогичную проверку. Новый факт оценивается по сравнению с его соседями перед сохранением: он может быть объединен, помечен как дубликат, отмечен как конфликт или отклонен. Каждая версия сохраняется, поэтому поиск можно выполнить по состоянию на определенную дату в прошлом. Подробный обзор изнутри представлен в документе memory architecture. Каждый из этих поисковых запросов представляет собой простой запрос ClickHouse к тем же таблицам.
Пожалуйста, постарайтесь сдержать удивление, но… мы храним воспоминания в ClickHouse. Неожиданно, мы знаем. Но если отбросить предвзятость, это чрезвычайно подходящее хранилище данных для такого типа информации!
Большинство систем управления памятью для агентов в итоге превращаются в груду разрозненных сервисов: один для векторного поиска, один для поиска по ключевым словам, один для графа связей, один для фоновых задач, один для аналитики. Каждый из них представляет собой еще один компонент, который нужно развертывать, защищать и поддерживать в синхронизированном состоянии.
Loom объединяет все это в одной базе данных ClickHouse: факты, эмбеддинги, полнотекстовый индекс, граф кода, состояние задач, а также данные о затратах и журнал аудита. Поиск ограничивается тем, что может видеть вызывающий абонент, а затем ранжируется с помощью упомянутых выше векторного поиска и поиска по алгоритму BM25. При этом данные об использовании хранятся прямо рядом со всем остальным, а не в отдельном аналитическом инструменте. Обновления, исправления и эмбеддинги используют движки хранения ClickHouse, настроенные под конкретные паттерны чтения и записи, а не единую универсальную таблицу для всего.
О, и конечно же, трекинг можно отправлять в лучший в своем классе инструмент наблюдаемости — Langfuse.
Эта настройка также позволяет легко понять, приносит ли все это реальную пользу. Каждый запуск регистрируется с указанием использованных данных и результатов, поэтому воспоминания, которые продолжают помогать, подкрепляются, а бесполезные — просто затухают. Чтобы детально изучить конкретный запрос, вызовы моделей, затраты или оценки извлечения, мы просто обращаемся к Langfuse.
Loom может работать как на самостоятельно управляемом ClickHouse, так и в ClickHouse Cloud. Требуется ClickHouse версии 26.5 или новее, а для ускорения векторного поиска рекомендуется версия 26.8 или новее.
Мы измеряли две вещи: во-первых, объясняет ли агент с поддержкой Loom код и находит ли нужный файл лучше, чем агент, использующий только grep, Read и Glob; во-вторых, превосходят ли извлеченные воспоминания передачу модели всей истории разговора. В обоих сравнениях использовались одни и те же вопросы и модели, причем Loom то включался, то отключался.
Для вопросов по программированию эталонный ответ содержит ключевые пункты, которые должен охватывать хороший ответ. Отдельная модель оценивает, сколько из этих пунктов покрывает реальный ответ агента, и существенно снижает оценку, если ответ напрямую противоречит эталону. На выборке из 24 вопросов по 3 запуска на каждый средний балл вырос с 0.78 до 0.84 (прирост примерно на 8%), а средняя стоимость одного вопроса снизилась с $0.212 до $0.17. В отдельной задаче по поиску файлов (36 вопросов по 10 запусков на каждый) точность увеличилась с 91.4% до 96.4% при сопоставим снижении затрат.
Мы не собираемся потрясать вас гигантскими ошеломляющими цифрами и утверждать, что ради них стоит мигрировать прямо сегодня, но прирост в +8% имеет огромное значение. Точно так же, как экономия -$0.042 и улучшение на +5%. Сам ClickHouse строился не за счет каких-то грандиозных изменений, внедренных после месяцев ожидания, а благодаря последовательному и постепенному прогрессу на протяжении более чем десятилетия заботы о проекте.
На 100 вопросах из LongMemEval-S та же модель давала более качественные ответы с воспоминаниями, извлеченными Loom (94%), чем при передаче всей истории разговора прямо в промпт (90%), при этом обрабатывая примерно на 90% меньше токенов. Сам по себе этот разрыв недостаточно велик, чтобы считаться статистически значимым, однако более весомым показателем является то, что memory.ask набирает 96.6% по всему бенчмарку из 500 вопросов при оценке официальным судьей — это ближе к тому, с чем вы столкнетесь при реальном использовании.
Полная методология и результаты по каждому вопросу находятся в папке benchmarks folder на GitHub.
Самый простой способ проверить, работает ли это на практике — попробовать применить инструмент к собственной кодовой базе!
Установите Docker и Docker Compose, а затем выполните:
Это запустит Loom и ClickHouse, дождется инициализации всех компонентов и выведет URL панели управления. Откройте http://localhost:7777/me и укажите ключи для моделей и эмбеддингов в разделе Настройки → Модели и ключи. В Loom встроены модели-заглушки, поэтому он работает вообще без каких-либо ключей. Просто вы не получите поиск по смыслу или генерацию ответов, пока не добавите настоящие ключи.
По умолчанию это персональная настройка: один человек, один или несколько агентов, работающие локально через localhost. Совместное использование в рамках команды с реальными учетными записями и правами доступа для пространств имен описано в руководстве по развертыванию для команд.
Для локального агента кодирования плагины Claude Code и Codex подключаются автоматически после индексации вашего репозитория. Они считывают ваши удаленные репозитории git, находят нужное пространство имен и начинают отправлять туда запросы. Cursor подключается через MCP. Если вы создаете что-то нестандартное, также доступны HTTP API и SDK для Python и TypeScript.
Лучший способ прочувствовать это — задать реальный вопрос по вашей собственной работе, например: «что сломается, если я изменю эту функцию?», проверить результат, сохранить находку и открыть ее снова в новой сессии. quickstartРуководство по первому агенту подробно описывает именно этот процесс. Следует учитывать один нюанс: индекс строится на основе зеркала сервера для ветки, с которой вы работаете, поэтому незакоммиченные изменения не появятся, пока вы их не закоммитите и не запушите!
Если вы хотите прочитать исходный код, чтобы подтвердить все наши утверждения, Loom доступен на GitHub под лицензией Apache-2.0. Запустите его на своем репозитории и сообщите нам, что он упускает.
Если вы когда-нибудь захотите заглянуть в хранилища памяти, которые мы создали для себя, ознакомьтесь с нашей страницей «Вакансии». ClickHouse всегда ищем таланты в новую эпоху агентного кодирования, которые могут делиться работой членов команды и использовать ее еще эффективнее.
Ссылки: first-agent tutorial












