Neo4j + hooks: унифицированная память для Claude Code, Codex, Cursor | AiManual
AiManual Logo Ai / Manual.
10 Май 2026 Гайд

Унифицированная память для AI-агентов: как связать Claude Code, Codex и Cursor через Neo4j и хуки

Гайд по созданию единой памяти для AI-агентов на Neo4j и хуках. Избавляемся от vendor lock-in, объединяем Claude Code, OpenAI Codex и Cursor.

Ты когда-нибудь переключался между Claude Code, Codex и Cursor в одном проекте? Первые 10 минут — эйфория: каждый агент хорош по-своему. А потом приходит боль. Claude Code запомнил архитектуру, но Codex о ней не знает. Cursor нарезал рефакторинг, но контекст потерялся. Фрагментация памяти съедает время, деньги и нервы. Vendor lock-in душит, а альтернатив нет. Или есть?

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

Почему агенты — как рыбы с короткой памятью?

Каждый AI-coding агент живёт в своём пузыре. Claude Code использует внутренние файлы CLAUDEMD и сессионные контексты. OpenAI Codex опирается на историю чата в API. Cursor хранит «память» в локальных кэшах и правилах .cursorrules. Никто не синхронизируется.

Результат: ты объясняешь архитектуру заново, тратишь токены, теряешь время. А если проект большой — агенты начинают «тупить» и молчать, как описано в гайде по observability для Cursor и Claude Code. Проблема не в AI, а в отсутствии общей «долгосрочной памяти».

«В теории это работает так: каждый агент пишет и читает из одного графа знаний. На практике — упирается в vendor lock-in и архитектурные костыли».

Звучит логично, но есть нюанс. Готовая графовая память на SQLite (как в статье про SQLite-решение) — хорошая база, но для мультиагентной среды нужна более мощная связка. Именно тут на сцену выходят Neo4j и хуки.

Архитектура: как заставить агентов говорить на одном языке

Вместо того чтобы пилить велосипед, я взял за основу подход из статьи про архитектуру коллективного разума. Там семь «мозгов» объединены через единый брокер. Здесь мы делаем то же самое, но через графовую БД и MCP-протокол.

💡
MCP (Memory Communication Protocol) — легковесный протокол поверх HTTP/2, который мы используем для синхронизации. По сути, каждый агент через хук отправляет JSON-событие в Neo4j, а другие агенты подписываются на изменения.

Как это выглядит на диаграмме (мысленно):

  1. Claude Code завершает задачу — хук post-complete отправляет в Neo4j узлы: Решение: переписать модуль auth, Файл: auth.py, Зависимость: JWT.
  2. Codex стартует новую задачу — хук pre-start читает из Neo4j последние решения, связанные с путём проекта, и добавляет их в промпт.
  3. Cursor получает уведомление через WebSocket и обновляет свой .cursorrules, чтобы не наступить на грабли.

Графовая модель Neo4j идеальна для этой задачи: отношения между узлами (файл-функция-баг-решение) позволяют агентам видеть не просто плоские факты, а контекст. Никакой реляционной грязи.

Пошаговый план: от нуля до работающей связки

Я буду показывать на конкретных конфигах. Все примеры — с моего GitHub-репозитория (актуальны на май 2026).

1 Поднимаем Neo4j с графовой схемой

Ставим Docker Compose (последняя версия Neo4j 5.25 на момент написания):

version: '3.9'
services:
  neo4j:
    image: neo4j:5.25-enterprise
    ports:
      - 7687:7687  # bolt
      - 7474:7474  # browser
    volumes:
      - ./data:/data
      - ./plugins:/plugins
      - ./import:/import
    environment:
      - NEO4J_AUTH=neo4j/your_password
      - NEO4J_ACCEPT_LICENSE_AGREEMENT=yes
      - NEO4J_PLUGINS='["apoc", "graph-data-science"]'

Схема памяти (создаём constraints и индексы):

CREATE CONSTRAINT memory_id IF NOT EXISTS FOR (m:Memory) REQUIRE m.mem_id IS UNIQUE;
CREATE INDEX memory_agent IF NOT EXISTS FOR (m:Memory) ON (m.agent);
CREATE INDEX memory_timestamp IF NOT EXISTS FOR (m:Memory) ON (m.timestamp);

// Узлы-категории
CREATE (a:Memory {
  mem_id: randomUUID(),
  agent: 'claude-code',
  type: 'decision',
  content: 'Переписать auth на JWT + refresh',
  file_path: 'src/auth.py',
  timestamp: datetime()
})

Теперь каждый агент будет писать сюда факты.

2 Пишем хук для Claude Code

Anthropic Claude Code поддерживает кастомные хуки через переменную CLAUDE_CODE_HOOKS_DIR. Создаём скрипт, который после каждого завершённого действия шлёт данные в Neo4j.

#!/bin/bash
# post-complete.sh
# Вызывается после завершения задачи Claude Code
# Переменные окружения: MEMORY_URI, MEMORY_USER, MEMORY_PASS

EVENT_JSON=$(cat $1)
# Предполагаем, что $1 — JSON с полями agent, type, content, file_path

cat <

Регистрируем хук в CLAUDE.md:

hooks:
  post-complete: './hooks/claude-post-complete.sh'

Ошибка: не указывай пароль в скрипте напрямую. Используй переменные окружения или Vault. Иначе пароль попадёт в лог гита — проверено на горьком опыте.

3 Обучаем Codex через pre-start хук

OpenAI Codex в режиме агента (версия gpt-4.1, последняя на май 2026) позволяет задать системный промпт, который динамически генерируется перед каждым запуском. Мы используем Python-скрипт, который тянет последние 10 релевантных фактов из Neo4j.

#!/usr/bin/env python3
# pre-start-codex.py
"""Генерирует system prompt с памятью из Neo4j для Codex"""
import requests, json

MEMORY_URI = "http://localhost:7474"
NEO4J_USER = "neo4j"
NEO4J_PASS = "your_password"

def fetch_memories(path: str, limit: int = 10) -> list:
    query = """
    MATCH (m:Memory)
    WHERE m.file_path STARTS WITH $path
    RETURN m ORDER BY m.timestamp DESC LIMIT $limit
    """
    with requests.Session() as s:
        s.auth = (NEO4J_USER, NEO4J_PASS)
        s.headers.update({"Accept": "application/json"})
        r = s.post(f"{MEMORY_URI}/db/neo4j/tx/commit", json={
            "statements": [{"statement": query, "parameters": {"path": path, "limit": limit}}]
        })
        return r.json()

if __name__ == "__main__":
    import sys
    project_path = sys.argv[1] if len(sys.argv) > 1 else "/"
    memories = fetch_memories(project_path)
    prompt_extension = "\n".join([f"- {m['row']['m.data.content']} // {m['row']['m.data.agent']}" for m in memories.get('results',[])])
    print(f"Актуальный контекст проекта:\n{prompt_extension}")

Интеграция происходит через обёртку: вместо прямого вызова Codex, вызываем этот скрипт, он дополняет промпт, затем передаёт управление агенту.

4 Cursor: подписка на обновления через WebSocket

Cursor (v0.48, последняя стабильная) поддерживает кастомные команды и .cursorrules, которые можно динамически обновлять. Мы добавили сервис, который слушает изменения Neo4j через neo4j-streams и пишет в .cursorrules актуальные факты.

# Запускаем слушатель изменений (используем Kafka Connect + neo4j-connector)
# Или проще: polling каждые 5 секунд
while true; do
  NEW_FACTS=$(curl -s -u neo4j:pass "http://localhost:7474/db/neo4j/cypher" \
    -d '{"query":"MATCH (m:Memory) WHERE m.timestamp > datetime() - duration("PT10S") RETURN m"}')
  if [ "$NEW_FACTS" != "$PREV" ]; then
    echo $NEW_FACTS > .cursorrules
    kill -SIGUSR1 $(pgrep cursor) # перезагрузка правил
  fi
  PREV=$NEW_FACTS
  sleep 5
done

Этот скрипт — MVP. В бою используй полноценный CDC (Change Data Capture) через Debezium, чтобы не нагружать Neo4j.

Нюансы и грабли: как НЕ надо делать

Я собрал топ ошибок, которые вылезли в моей песочнице (и которые повторяют почти все):

  • Синхронизация без версионирования. Один агент пишет «исправить баг A», второй тут же пишет «переписать модуль» и баг A считается неактуальным. Решение: добавлять поле status: active|superseded|done и не удалять старые записи, а помечать их.
  • Latency при запросах. Если каждый pre-start хук делает запрос к Neo4j (пусть даже локальному), то запуск агента тормозит на 200-500 мс. Решение: кэшировать последние 20 записей в Redis или файле .memory_cache.json, обновлять каждые 10 секунд.
  • Переполнение контекста. Agent получает 50 фактов из памяти — и начинает галлюцинировать, смешивая неактуальное с актуальным. Решение: добавить скоринг по релевантности (похожесть пути, timestamp, вес узла). В Neo4j это делается через apoc.text.levenshteinDistance или GDS similarity.
  • Безопасность. В хуках пароль в plain text — классика. Используйте Vault или хотя бы chmod 600. Лучше — сегментируйте память per-user через tenant_id.

Запоминай: графовая память на Neo4j — это не просто «ещё одна база данных». Это способ связывать разрозненные решения агентов в единую семантическую сеть. Без этого любой «коллективный разум» будет амнезийным стариком.

Куда копать дальше?

Уже сейчас можно пойти глубже:

  • Интегрировать OS Agent (типа AI-IQ на SQLite) как лёгкую прослойку для автономных сценариев без MCP — например, когда агенту нужно быстро записать факт без цикла синхронизации.
  • Посмотреть, как эта архитектура обсуждается в контексте совместной работы нескольких Claude Code (статья про handoffs и rollup’ы).
  • Если хочется полного контроля — пиши свой MCP-сервер на Rust (Golang?) с нуля.

Главный урок: не пытайся заставить агентов быть «умнее». Просто дай им общую память. Они сами разберутся.


Дата публикации: 10 мая 2026. Версии инструментов: Neo4j 5.25, Claude Code 0.3.x, OpenAI Codex (gpt-4.1), Cursor 0.48.

Подписаться на канал