causal-memory — причинная память для AI-агентов
📂 Исходный код на GitHubcausal-memory — локальный слой причинной памяти для AI-агентов на Rust. Он объединяет факты, временное состояние и связи decision → outcome в SQLite, использует тормозящие и возбуждающие causal edges, гиппокампальный spreading activation, RRF-поиск и SWR-консолидацию. MCP-сервер работает через stdio и HTTP, поддерживает multi-tenant изоляцию и Python bindings. Apache 2.0.
Большинство систем памяти для AI-агентов хорошо отвечают на вопрос «что агент уже знал?». Но после нескольких compaction циклов хуже всего сохраняется причинная информация: почему было принято решение, какое действие привело к ошибке и какой вариант уже дал плохой результат. causal-memory добавляет именно этот слой — локальную память, где факты, временное состояние и цепочки decision → outcome хранятся вне контекстного окна агента.
Проект написан на Rust и распространяется как MCP-сервер для stdio и HTTP. В одной базе SQLite он объединяет семь типов связей, поиск фактов и причинных эпизодов, прямое и обратное распространение активации, reinforcement повторных совпадений, Q-value динамику и SWR-консолидацию. Благодаря этому агент может не только вспомнить прошлый опыт, но и проследить его причину, сравнить альтернативы или запросить прогноз последствий нового действия.
Почему обычного transcript недостаточно
Compaction сжимает историю диалога, чтобы освободить место в контекстном окне. README проекта приводит эксперимент grok-build: после одной компрессии текстовое воспоминание и причинная таблица ещё доступны полностью, а после пяти компрессий текст сохраняется только на 45%, тогда как внешняя причинная таблица остаётся на 100%.
Причина проста: если causal edges лежат в SQLite, механизм управления контекстом не может стереть или переписать их. Агент после новой сессии может снова запросить прошлое решение, найти связанный результат и получить предупреждение до повторения уже известной ошибки. Схема архитектуры и интерактивная версия доступны в документации проекта.
Единая модель памяти
В системе одновременно хранятся несколько типов записей:
- плоские факты о пользователе, проекте и окружении;
- причинные связи от решения к результату;
- временное состояние и контекст, при котором принималось решение;
- повторные совместные активации событий;
- межзадачные паттерны, найденные при консолидации.
Каждое причинное ребро имеет собственный коэффициент распространения:
| Тип | Коэффициент | Смысл |
|---|---|---|
caused |
+1.0 | действие вызвало результат |
fact |
+0.8 | семантическая связь с фактом |
meta |
+0.6 | связь между задачами или паттернами |
enabled |
+0.5 | действие облегчило другой результат |
co_occurrence |
динамический | события часто происходят вместе |
prevented |
−0.3 | действие предотвратило негативный результат |
no_effect |
0.0 | причинной связи нет |
Последние две строки особенно важны. Положительные связи отвечают на вопрос «что привело к успеху?», а prevented позволяет учитывать действия, которые остановили ошибку. Проект называет эту комбинацию excitatory/inhibitory duality и сопоставляет тормозящие рёбра с GABA.
Как работает retrieval
Сырые реплики сначала попадают в session_logs только для аудита и replay. В поисковый путь попадают только извлечённые факты и причинные связи. Такой write-time gatekeeping не позволяет BM25 и embeddings индексировать весь шум разговора.
Поиск объединяет BM25 и семантическое cosine similarity через Reciprocal Rank Fusion. Граф хранится в компактной CSR-структуре: прямой multi-hop обход находит возможные последствия, обратный — исходную причину. prevented-рёбра распространяют отрицательную активацию, поэтому защитное действие не превращается в ложное утверждение, что соответствующая ошибка обязательно повторится.
Повторная совместная активация укрепляет связь по механизму Hebbian LTP. Хорошие решения получают более высокий Q-value, а изменения полезности распространяются к родительским решениям. Команда causal-memory sleep выполняет SWR-цикл: создаёт неизменяемую дельту и клон графа, усиливает повторно посещённые связи, ослабляет неиспользуемые и применяет garbage collection только к связям, которые одновременно слабые, давно неактивные и ни разу не открытые. Цикл также запускается автоматически, когда novelty entropy превышает порог.
Инструменты для агента
MCP-интерфейс предоставляет 17 операций. Их можно разделить на несколько рабочих циклов:
- Запись.
record_decisionсохраняет связьdecision → outcome,rememberизвлекает факты, уроки и связи из свободного текста, аrecord_factдобавляет устойчивый факт с областью действия и confidence. - Recall.
search_causal,search_factsиsearch_memoryищут причинные эпизоды, факты или объединённую выдачу.causal_directoryдаёт компактный указатель известных связей для system prompt. - Объяснение.
trace_causeищет непосредственную причину сбоя, аtrace_cause_chainвыполняет многошаговый обратный обход. - Проверка гипотез.
intervention_queryпрогнозирует последствия действия и выдаёт safe, warning или danger.counterfactual_queryсравнивает записанные результаты альтернатив, аprediction_reportпоказывает точность прогнозов. - Исправление памяти.
invalidate_decisionскрывает ошибочный урок, но сохраняет его для аудита;resolve_updatesпомечает старую связь как superseded и позволяет новому результату обновить вывод агента.
search_patterns находит межзадачные связи similar_to, repeated, contradicts и refines, а reconstruct_lesson собирает связный вывод из подграфа вокруг найденного эпизода.
Установка и MCP-конфигурация
Собрать сервер из исходников можно стандартной командой:
git clone https://github.com/JingxuanC/causal-memory.git
cd causal-memory
cargo build --release
Если Rust toolchain не нужен, доступна Python-версия с готовым CLI:
pip install causal-memory
causal-memory
Пакет также содержит bundled skill, который объясняет агенту, когда вызывать memory tools. Его установка вместе с сервером и MCP-регистрацией выполняется через install.sh либо npx skills add JingxuanC/causal-memory@causal-memory.
Конфигурация stdio-сервера для Claude Code, Cursor, Codex и других MCP-клиентов выглядит так:
{
"mcpServers": {
"causal-memory": {
"command": "/path/to/causal-memory/target/release/causal-memory",
"env": {
"CAUSAL_MEMORY_DB": "~/.local/share/causal-memory/causal.db"
}
}
}
}
Проект предоставляет Python bindings через PyO3. Они открывают тот же фасад Memory, который использует MCP-сервер, поэтому запись решения и прогноз можно вызвать непосредственно из Python.
HTTP, embeddings и изоляция tenants
Для удалённых агентов бинарник запускает MCP Streamable HTTP:
causal-memory http --port 9938
На том же порту доступны Prometheus-метрики, health checks и debug-эндпоинты, возвращающие seeds, hops и provenance результата recall. Recall corpus и debug-данные защищаются отдельным bearer token через CAUSAL_MEMORY_HTTP_AUTH_TOKEN.
CAUSAL_MEMORY_TOKENS_FILE включает multi-tenant режим: /mcp проверяет bearer token и открывает отдельную SQLite-базу для каждого tenant. Базы создаются лениво, неизвестный token не создаёт файл, а при временно недоступном конфиге сохраняется последняя валидная карта. Этот режим нужен удалённым multi-agent системам; локальный stdio-вариант остаётся без аутентификации.
Семантические embeddings опциональны. Можно использовать локальную ONNX-модель BAAI/bge-small-en-v1.5 или совместимый HTTP API. Без них поиск деградирует до BM25, но MCP-сервер и причинный граф продолжают работать.
Что показывают бенчмарки
Основной benchmark проекта — CausalEval, построенный на детерминированно сгенерированных причинных DAG. В версии v13 он содержит 140 вопросов и 20 графов. causal-memory получает 78% суммарно: 100% на обновлении устаревшего вывода, 95% на counterfactual comparison, 75% на intervention и 80% на inhibition. Перенос урока между задачами остаётся слабым местом — 20%.
На классических benchmark фактического запоминания проект не превосходит mem0: 79.1% против 91.6% на LoCoMo и 67.4% против 71.8% на Memora MPA. Это соответствует позиции авторов — их основное отличие находится в причинных рассуждениях, а не в хранении фактов. Подробности протокола и различия между single-model и platform stacks описаны в документации LongMemEval.
Статус и ограничения
Версия 0.9.3 помечена как alpha. README сообщает о 368 прошедших тестах и чистом Clippy, а также о готовых stdio/HTTP transports, Python bindings, локальных embeddings, multi-tenant HTTP и интеграциях с Hermes и DeepSeek Harness. Не готовы TypeScript bindings, отдельный benchmark точности forward simulation и проверка круглосуточной production-эксплуатации.
Проект стоит рассматривать не как универсальную замену векторной памяти, а как локальный backend для engineering lessons и причинных рассуждений. Его сильная сторона — traceability: агент может связать прошлое решение с результатом, найти цепочку до первопричины и получить falsifiable prediction до следующего изменения кода. Авторы также связывают дизайн с исследовательскими заметками по архитектурам памяти и агентным фреймворкам.