AI Platform Docs
Администрирование

Руководство администратора Memory Service

Архитектура, конфигурация и эксплуатация управляемого сервиса памяти агентов Платформы ИИ.

Назначение и область применения

Настоящее руководство определяет порядок развёртывания, настройки, сопровождения и проверки сервиса Platform Memory в контуре заказчика. Документ предназначен для администратора платформы и предполагает владение основами администрирования Linux, Docker, Kubernetes, Helm и HTTP API.

Platform Memory — единый управляемый слой памяти платформы. Агент получает персистентную память: search перед ответом, add после ответа. Извлечение фактов, дедупликация, гибридный поиск, изоляция по скоупам и история изменений выполняются сервисом, а не каждым агентом отдельно.

Память не заменяет RAG. Platform RAG отвечает за корпус документов; Platform Memory — за знания о пользователе, агенте и сессии. Сборка промпта комбинирует оба источника.

Публичный контракт совместим с mem0 (add / search / get_all / history / delete). Пути платформы — /v1/*. Платформенные отличия: идентичность вызывающего не берётся из тела запроса, запись асинхронна, инференс и эмбеддинг идут только через AI Gateway.

Потребители обращаются к сервису через платформенный SDK (MemoryClient), ноду PlatformMemory в low-code или HTTP API. Порядок работы разработчика с SDK и нодой в настоящем документе не рассматривается. Контракты зафиксированы в platform-memory-specs/contracts.md, продуктовые требования — в platform-memory-specs/memory-service-prd.md, схема потоков — в platform-memory-specs/MEMORY.md.


Условные обозначения

Параметры, зависящие от конкретной поставки (реестр образов, доменные имена, адреса PostgreSQL, OpenSearch, RabbitMQ и AI Gateway), приведены как типовые и сопровождаются пометкой «уточняется при внедрении».

Конфигурация задаётся файлом YAML (переменная окружения MEMORY_CONFIG) и может быть переопределена переменными с префиксом MEMORY__ (вложенность — через __, например MEMORY__POSTGRES__DSN). Секреты в Kubernetes не размещаются в values и передаются через Secret.

Чарт Helm helm/platform-memory устанавливает прикладную нагрузку API. PostgreSQL, RabbitMQ, OpenSearch и AI Gateway — внешние зависимости и в чарт не входят. Для завершения асинхронной записи (POST /v1/memories) необходим процесс platform-memory-worker; в Docker Compose он поднимается рядом с API, в текущем чарте отдельный Deployment воркера ещё не описан (см. п. 2.5).


Термины и сокращения

Термин, сокращениеОпределение
Контур заказчикаСетевая и вычислительная среда, в которой развёрнут сервис
Memory APIStateless HTTP-сервис (platform-memory-api), порт 8091
WorkerПроцесс platform-memory-worker: извлечение фактов из очереди memory.add
Fact / запись памятиАтомарный факт о пользователе, агенте или задаче (поле memory)
СкоупГраница изоляции: user_id (из идентичности), agent_id, run_id
WorkspaceРабочая область платформы (X-Workspace-Id); факты разных workspace не смешиваются
infer: trueLLM-извлечение фактов из messages (асинхронно, через воркер и AI Gateway)
infer: falseПрямой импорт сообщений как фактов без вызова LLM
Event storeТаблица platform_memory.memory_event — источник истины по async add
SearchСинхронный гибридный поиск: эмбеддинг запроса + OpenSearch (семантика + BM25), упаковка в token_budget
AI GatewayЕдинственный разрешённый путь к LLM и модели эмбеддинга
OpenSearchИндекс фактов: вектор + BM25 (index_alias вида mem-facts-<env>)
PostgreSQLМетаданные, события async-обработки, история изменений записей
RabbitMQУведомления о заданиях add (exchange: memory.add, очередь memory.add.jobs, DLX/DLQ)
Fail-closedПри недоступности очереди запись не считается принятой: событие помечается FAILED, клиент получает 503
Helm / чарт / релизПакетный менеджер Kubernetes; пакет приложения; установленный экземпляр
mem0OSS-контракт и алгоритмы add/search, на которых построена реализация

1. Архитектура сервиса

1.1. Общая схема

Сервис состоит из двух прикладных нагрузок без локального состояния: API (синхронное чтение и приём записи) и воркер извлечения (асинхронный write-path). Состояние хранится во внешних сервисах данных. Модели вызываются только через AI Gateway.

memory-architecture.drawio.png

Разделение ответственности: агент не проектирует хранилище и пайплайн извлечения. Platform Memory принимает ход диалога, извлекает факты вне критического пути ответа пользователю и отдаёт релевантные факты в пределах бюджета токенов.

1.2. Состав компонентов

КомпонентНазначениеПримечание
platform-memory-apiHTTP API: add, search, list, history, events, /healthStateless. Контейнерный порт 8091; в Compose публикуется как 8093
platform-memory-workerОбработка add: claim события → mem0 Memory.add → индекс и историяМасштабируется независимо (worker.concurrency)
PostgreSQLEvent store, история записей, служебные сообщения mem0Схема platform_memory
RabbitMQУведомления о заданиях (memory.add / memory.add.jobs / DLX memory.add.dlx / DLQ memory.add.dlq)Не хранит состояние задания; источник истины — PostgreSQL
OpenSearchИндекс фактов: kNN + BM25Алиас вида mem-facts-dev / mem-facts-prod
AI GatewayЭмбеддинг запросов/фактов и LLM-извлечение (infer: true)Ключ шлюза — только в Secret

Helm-чарт helm/platform-memory создаёт Deployment API, Service (ClusterIP, порт 8091), ConfigMap, ServiceAccount и опционально Ingress. Зависимости чартом не устанавливаются.

1.3. Потоки данных

Запись (POST /v1/memories). Клиент передаёт messages и минимум один скоуп (agent_id или run_id). Идентичность (workspace_id, user_id) берётся из заголовков, не из тела. API создаёт событие PENDING в PostgreSQL, публикует уведомление в RabbitMQ и сразу отвечает 202 с event_id. Если публикация в очередь не удалась, событие помечается FAILED, клиент получает 503 queue_unavailable.

Воркер захватывает событие (RUNNING, в API отображается как PENDING), вызывает пайплайн mem0: при infer: true — LLM через AI Gateway с дедупликацией; при infer: false — сохранение сообщений без LLM. Результат пишется в OpenSearch и историю PostgreSQL; статус события — SUCCEEDED или FAILED.

Поиск (POST /v1/memories/search). Синхронно: эмбеддинг запроса через AI Gateway, гибридный поиск в OpenSearch (семантика + BM25), упаковка результатов в token_budget. Обязательны фильтры со скоупом.

Список и забвение. GET /v1/memories возвращает факты по agent_id / run_id в рамках workspace и пользователя. DELETE /v1/memories удаляет записи по фильтру (право на забвение); user_id в запросе не может отличаться от идентичности вызывающего.

История. GET /v1/memories/{memory_id}/history отдаёт журнал ADD / UPDATE / DELETE из PostgreSQL.

1.4. Минимальные ресурсы

Значения ориентировочные и уточняются по нагрузке (раздел 8). Для пилотного стенда (проверка API и одного агента):

РесурсМинимум (пилот)Рекомендуется (пром)
Процессор (API + worker)2 ядра4–8 ядер
Оперативная память4 ГБ8–16 ГБ
OpenSearch512 МБ heap (Compose)отдельный кластер, реплики индекса
PostgreSQL1 ГБвнешний отказоустойчивый кластер
Диск20 ГБ (индекс + WAL)по объёму фактов
ОСLinux x86-64, Docker Compose v2 или Kubernetes 1.27+—

Запросы чарта по умолчанию: API — 100m CPU / 256Mi RAM (лимит 1Gi).

Языковые модели и эмбеддинги размещаются за AI Gateway, вне сервиса. Требования к GPU определяются выбранной моделью, а не Platform Memory.


2. Установка и развёртывание

Основной способ пилотных и локальных стендов — Docker Compose. Для промышленных сред — Kubernetes + Helm.

2.1. Предварительные требования

  • Linux x86-64 (см. 1.4).
  • Docker Engine и Docker Compose версии 2 или кластер Kubernetes с Helm 3.
  • Доступ к реестру образов либо возможность собрать образ из исходного кода.
  • Для полного цикла add/search: доступные PostgreSQL 16, RabbitMQ 3, OpenSearch 2.x, AI Gateway.

Проверка Docker:

docker --version
docker compose version

Проверка Kubernetes / Helm:

kubectl version --client
helm version

2.2. Получение дистрибутива

Исходный код и чарт поставляются репозиторием сервиса. Сборка образа:

docker build -t platform-memory:<tag> .

Образ запускается от UID/GID 10001 (non-root), корневая ФС в Kubernetes — read-only. В контуре заказчика используется согласованный реестр (пример dev-поставки: docker-ppbd-prod.sfera-t1.ru/dassist-docker-release/gpt/image/platform-memory, тег уточняется при внедрении). После сборки образ публикуется в реестр, доступный узлам кластера.

2.3. Настройка конфигурации

Образец — config/config_template.yaml. Для Compose внутри сети Docker — config/config.docker.yaml. Рабочий файл задаётся MEMORY_CONFIG. Секреты (DSN, пароли, ключ AI Gateway) не хранятся в Git; для локального стенда допустимы dev-значения только во внутреннем контуре.

Обязательные группы параметров до запуска:

ГруппаНазначениеДействие
postgres.dsnПодключение к БД (postgresql+asyncpg://…)Задать устойчивый пароль; схема platform_memory
rabbitmq.*Брокер write-pathХост, пользователь, пароль, exchange/queue/dlx/dlq
opensearch.hostsИндекс фактовURL кластера; index_alias вида mem-facts-<env>
embedding.model / dimensionМодель и размерность вектораДолжны совпадать с mapping OpenSearch (по умолчанию 1024)
ai_gateway.url / api_key / llm_modelЭмбеддинг и LLM-извлечениеURL шлюза; ключ только в Secret

Переопределение из окружения (примеры):

export MEMORY_CONFIG=/app/config/config.yaml
export MEMORY__POSTGRES__DSN='postgresql+asyncpg://user:pass@postgres:5432/platform_memory'
export MEMORY__RABBITMQ__HOST=rabbitmq
export MEMORY__RABBITMQ__PASSWORD='<password>'
export MEMORY__OPENSEARCH__USERNAME='<user>'
export MEMORY__OPENSEARCH__PASSWORD='<password>'
export MEMORY__AI_GATEWAY__URL='https://<ai-gateway>/v1'
export MEMORY__AI_GATEWAY__API_KEY='<api-key>'

При app.create_schema_on_startup: true API при старте создаёт схему PostgreSQL. Для промышленного контура порядок миграций согласовывается отдельно; откат Helm не откатывает схему БД.

Внимание. Размерность эмбеддинга (embedding.dimension и opensearch.embedding_dimension) закрепляется за индексом. Смена модели/размерности без переиндексации сделает векторный поиск несовместимым.

2.4. Развёртывание в Docker Compose

Файл docker-compose.yml поднимает API, worker и зависимости: PostgreSQL, RabbitMQ, OpenSearch. AI Gateway в Compose не входит: эмбеддинг и infer: true требуют доступного шлюза (либо ai_gateway.dry_run: true — только дымовая проверка без реальной модели).

Публикуемые порты Compose:

СервисПорт на хостеНазначение
API8093 → 8091HTTP API
PostgreSQL5435 → 5432БД сервиса
RabbitMQ AMQP5674 → 5672Очередь add
RabbitMQ management15674 → 15672UI брокера
OpenSearch9202 → 9200Поиск / индекс

Вариант A. Инфраструктура в Docker, приложение на хосте

Соответствует config/config_template.yaml с правкой портов под таблицу выше (в шаблоне могут быть другие publish-порты — сверяйте с docker-compose.yml).

docker compose up -d postgres rabbitmq opensearch

# из корня репозитория, Python 3.11+
cp config/config_template.yaml config/config.yaml
# поправить DSN/хосты на 127.0.0.1 и порты 5435 / 5674 / 9202
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
export MEMORY_CONFIG=config/config.yaml
platform-memory-api
# во втором терминале:
platform-memory-worker

API слушает api.port из конфига (по умолчанию 8091). Если запускаете через uvicorn как в README репозитория, порт может быть 8093 — сверяйте фактическую команду.

Проверка:

curl -fsS http://127.0.0.1:8091/health

Ожидается "status": "ok" по компонентам postgres, opensearch, rabbitmq.

Вариант B. Полный стек в Compose

Контейнеры api и worker ходят к зависимостям по именам сервисов Compose (postgres, rabbitmq, opensearch). Образец — config/config.docker.yaml.

docker compose up -d --build
docker compose ps
docker compose logs -f api worker
curl -fsS http://127.0.0.1:8093/health

Интерактивная спецификация API: http://127.0.0.1:8093/docs (Swagger UI) и http://127.0.0.1:8093/redoc.

Остановка:

docker compose down
# с удалением томов данных:
docker compose down -v

2.5. Развёртывание в Kubernetes (Helm)

Чарт: helm/platform-memory. Канонические команды также приведены в helm/platform-memory/README.md и docs/helm-deployment.md.

Подготовка

  1. Собрать и опубликовать образ.
  2. Проверить сетевую доступность PostgreSQL, RabbitMQ, OpenSearch и AI Gateway из целевого пространства имён.
  3. Создать Secret с учётными данными (не помещать их в values):
kubectl -n <namespace> create secret generic platform-memory-secrets \
  --from-literal=postgres-dsn='postgresql+asyncpg://user:pass@host:5432/platform_memory' \
  --from-literal=opensearch-username='<username>' \
  --from-literal=opensearch-password='<password>' \
  --from-literal=ai-gateway-api-key='<api-key>'

Пароль RabbitMQ при необходимости добавьте в тот же Secret и пробросьте MEMORY__RABBITMQ__PASSWORD.

  1. Подготовить values окружения (образцы: helm/platform-memory/values.yaml, values-dev.yaml, values-prod.example.yaml).

Сопоставление ключей Secret в values:

image:
  repository: <registry>/platform-memory
  tag: <image-tag>

config:
  api:
    host: 0.0.0.0
    port: 8091
  app:
    environment: prod
    create_schema_on_startup: true
  postgres:
    schema_name: platform_memory
    pool_size: 5
    echo: false
  rabbitmq:
    host: rabbitmq.example
    port: 5672
    username: memory
    virtual_host: /
    exchange: memory.add
    queue: memory.add.jobs
    dlx: memory.add.dlx
    dlq: memory.add.dlq
    prefetch: 16
    delivery_limit: 5
    heartbeat: 60
    routing_key: memory.add
  opensearch:
    hosts:
      - https://opensearch.example:9200
    verify_certs: true
    timeout: 30
    index_alias: mem-facts-prod
    embedding_dimension: 1024
    auto_clear_cluster_blocks: false
  embedding:
    model: bge-m3
    dimension: 1024
  ai_gateway:
    url: https://ai-gateway.example/v1
    timeout: 120
    batch_size: 32
    dry_run: false
    llm_model: <model-id>
  log:
    level: INFO
    format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"

secretEnv:
  existingSecret: platform-memory-secrets
  variables:
    MEMORY__POSTGRES__DSN: postgres-dsn
    MEMORY__OPENSEARCH__USERNAME: opensearch-username
    MEMORY__OPENSEARCH__PASSWORD: opensearch-password
    MEMORY__AI_GATEWAY__API_KEY: ai-gateway-api-key

Секция rabbitmq в values.yaml чарта по умолчанию может отсутствовать — её необходимо задать в values окружения, иначе API возьмёт значения по умолчанию (127.0.0.1), непригодные в кластере.

Установка

helm lint helm/platform-memory
helm template platform-memory helm/platform-memory -n <namespace> -f values-<env>.yaml

helm upgrade --install platform-memory helm/platform-memory \
  -n <namespace> --create-namespace \
  -f values-<env>.yaml \
  --atomic --wait --timeout 10m

kubectl -n <namespace> rollout status deployment/platform-memory --timeout=5m
kubectl -n <namespace> get pods,svc

Если имя релиза не platform-memory, фактическое имя Deployment смотрите через helm get manifest <release> или kubectl get deploy -l app.kubernetes.io/instance=<release>.

Проверка с порта кластера:

kubectl -n <namespace> port-forward svc/platform-memory 8091:8091
curl -fsS http://127.0.0.1:8091/health

При включённом Ingress (ingress.enabled: true) задайте ingress.hosts[].host и при необходимости TLS. Снаружи публикуется только API.

Воркер в Kubernetes

Текущий чарт создаёт один Deployment с командой образа platform-memory-api. Без platform-memory-worker запросы POST /v1/memories принимаются (202), но события остаются в PENDING. До появления Deployment воркера в чарте воркер запускают тем же образом с командой platform-memory-worker и тем же ConfigMap/Secret, что и API (уточняется при внедрении). В Docker Compose воркер уже описан сервисом worker.

Особенности промышленного контура

  • Образы запускаются от UID/GID 10001, runAsNonRoot, без привилегий, read-only root filesystem, /tmp — emptyDir.
  • Конфиг монтируется ConfigMap по пути /app/config/config.yaml (MEMORY_CONFIG).
  • Probes: startup/liveness/readiness на GET /health.
  • terminationGracePeriodSeconds: 30.
  • Пример dev-values (values-dev.yaml) подтягивает DSN из platform-services-db и учётные данные OpenSearch из api-keys-secret; для prod используйте secretEnv как в values-prod.example.yaml.

3. Подключение моделей

Сервис не содержит собственной языковой модели. Все вызовы эмбеддинга и LLM-извлечения идут через AI Gateway. Ключи инференса хранятся у шлюза; в конфигурации Memory задаётся URL шлюза, ключ доступа к нему и идентификатор модели.

embedding:
  model: bge-m3
  dimension: 1024

ai_gateway:
  url: https://<ai-gateway>/v1
  timeout: 120.0
  batch_size: 32
  dry_run: false
  llm_model: <идентификатор модели у шлюза>
НазначениеГде задаётсяПримечание
Эмбеддинг фактов и запросовembedding.model + dimensionДолжно совпадать с opensearch.embedding_dimension
LLM-извлечениеai_gateway.llm_modelИспользуется при infer: true
Dry-run шлюзаai_gateway.dry_runТолько дымовая проверка конвейера без модели

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

infer: false позволяет записать готовый факт без вызова LLM (миграция, системные факты, явное «запомни это») — дешевле и предсказуемее для нагрузочных проверок записи.


4. Доступ и изоляция памяти

4.1. Идентичность вызывающего

На текущем релизе идентичность передаётся заголовками. Поля workspace_id / user_id в теле запроса не доверяются.

ЗаголовокНазначение
X-Workspace-IdРабочая область (обязателен)
X-User-IdПользователь (обязателен; скоуп user_id для фактов)

Без заголовков API отвечает 422. Целевой контракт (JWT платформы + SpiceDB check на memory_collection, fail-closed) описан в PRD (SEC-1) и в текущем API не включён.

4.2. Скоупы

Факты изолируются по комбинации workspace, user_id, agent_id, run_id. Для add и list обязателен минимум один из agent_id / run_id. Поиск требует filters со скоупом. Удаление по фильтру не позволяет указать чужой user_id (403 Wrong user ID).

4.3. Право на забвение

DELETE /v1/memories с фильтром удаляет релевантные факты в OpenSearch и пишет события DELETE в историю. В ответе — deleted_count и confirmation_id для журнала операций.


5. Безопасность

5.1. Секреты

В Secret / защищённом хранилище: DSN PostgreSQL, пароль RabbitMQ, учётные данные OpenSearch, ключ AI Gateway. Файл values и ConfigMap не содержат паролей.

Права на локальный конфиг с секретами:

chmod 600 config/config.yaml

Ключи выдаются по принципу наименьших полномочий; при компрометации отзываются и перевыпускаются.

5.2. Сетевые ограничения

Наружу публикуется только API (ClusterIP + Ingress, порт 8091 / TLS). Воркер, PostgreSQL, RabbitMQ, OpenSearch во внешнюю сеть не публикуются.

ИсточникПортПротоколНазначение
Потребители (SDK, low-code, интеграции)8091 / 443HTTP/HTTPSMemory API
API / worker5432PostgreSQLEvent store и история
API / worker5672AMQPОчередь add
API / worker9200HTTP/HTTPSOpenSearch
API / worker443HTTPSAI Gateway
Администраторы22 / API KubernetesSSH / kubectlСопровождение

Management-порт RabbitMQ (15672) на промышленных контурах наружу не публикуется.

5.3. Хранение данных

Факты хранятся в контуре: PostgreSQL (события, история), OpenSearch (текст и векторы). Целевой контур предусматривает Guardrails на записи (маскирование ПД до сохранения) и immutable audit каждой операции (SEC-2, SEC-4) — на текущем релизе отдельные клиенты Guardrails/Audit в поставку не входят; администратор фиксирует это как ограничение MVP.

Персональные факты в долговременной памяти обрабатываются в контуре заказчика. Передача во внешние LLM без шлюза и правовых оснований недопустима.

5.4. Резервное копирование

Объекты копирования: PostgreSQL (event store и история), индексы OpenSearch, файл/Secret конфигурации. RabbitMQ некритичен как источник истины.

Логическая выгрузка БД (Compose):

docker compose exec -T postgres \
  pg_dump -U postgres platform_memory > platform_memory_db_$(date +%F).sql

В Kubernetes (внешний кластер PostgreSQL — штатными средствами кластера):

kubectl -n <namespace> exec -T <под_postgresql> -- \
  pg_dump -U <user> platform_memory > platform_memory_db_$(date +%F).sql

Снимки OpenSearch выполняются штатными средствами кластера (snapshot repository) для алиаса mem-facts-<env>. Копии хранятся отдельно от контура приложения; периодически проверяется восстановление.

5.5. Восстановление

  1. Развернуть ту же версию сервиса (раздел 2) с прежними секретами и той же размерностью эмбеддинга.
  2. Восстановить PostgreSQL (схема platform_memory).
  3. Восстановить снимки OpenSearch (алиас mem-facts-<env>).
  4. Запустить API и worker; проверить /health, контрольный add/search.

6. Обновление сервиса

Перед обновлением — резервное копирование (п. 5.4) и окно обслуживания.

6.1. Docker Compose

docker compose down
# обновить код / тег образа
docker compose build
docker compose up -d
docker compose logs -f api worker

Сверить config_template.yaml с рабочим конфигом на предмет новых параметров.

6.2. Kubernetes (Helm)

helm upgrade --install platform-memory helm/platform-memory \
  -n <namespace> \
  -f values-<env>.yaml \
  --atomic --wait --timeout 10m

6.3. Схема базы данных

При app.create_schema_on_startup: true API создаёт/догоняет объекты схемы при старте. Эксплуатация начинается после успешного /health и отсутствия ошибок создания схемы в журнале API.

Откат Helm не отменяет изменения схемы и данных внешних хранилищ.

6.4. Откат

helm -n <namespace> history platform-memory
helm -n <namespace> rollback platform-memory <REVISION> --wait --timeout 10m
kubectl -n <namespace> rollout status deployment/platform-memory --timeout=5m

При несовместимых миграциях откат версии выполняется вместе с восстановлением БД и индекса из копии, снятой до обновления.


7. Мониторинг и журналы

7.1. Состояние сервисов

Docker Compose

docker compose ps
docker compose logs -f api
docker compose logs -f worker
curl -fsS http://127.0.0.1:8093/health

Kubernetes

kubectl -n <namespace> get pods -l app.kubernetes.io/instance=platform-memory
kubectl -n <namespace> logs deploy/platform-memory --tail=200
kubectl -n <namespace> top pods

GET /health возвращает status: ok | degraded и статусы postgres, opensearch, rabbitmq. Probes Kubernetes используют этот путь.

Дополнительно контролируются: число событий PENDING/FAILED в memory_event, глубина DLQ memory.add.dlq, латентность search, отставание извлечения (время PENDING → SUCCEEDED).

Целевые метрики PRD (OBS-1): memory_search_latency, memory_tokens_returned, memory_hit_rate, memory_extraction_lag, memories_total — подключаются к штатному стеку мониторинга контура (уточняется при внедрении).

7.2. Журналы

Уровень задаётся log.level (по умолчанию INFO). API пишет о приёме add (event_id, infer) и ошибках публикации в очередь. Воркер пишет о старте listener, захвате события (RUNNING), ошибках mem0/AI Gateway/индексации.

7.3. Типовые нарушения

ПризнакИсточникВероятная причина и действие
/health → degradedТело ответа detailsНедоступен Postgres, OpenSearch или RabbitMQ
422 / missing headerЖурнал APIНет X-Workspace-Id или X-User-Id
400 «At least one of agent_id or run_id»Тело запросаНет скоупа
503 queue_unavailableЖурнал API, RabbitMQБрокер недоступен; событие помечено FAILED
Add 202, событие зависло в PENDINGWorker, RabbitMQВоркер не запущен; нет потребителя очереди
Событие FAILEDЖурнал worker, поле errorОшибка AI Gateway, OpenSearch, пайплайна mem0
Search пустой при наличии фактовСкоупы, workspaceДругой agent_id/user_id/X-Workspace-Id; событие ещё не SUCCEEDED
Search медленныйAI Gateway, OpenSearchЭмбеддинг запроса; нехватка heap у индекса
403 на DELETEuser_id в queryПопытка удалить память другого пользователя

8. Производительность и масштабирование

8.1. Воркеры извлечения

Основной потребитель ресурсов при infer: true (LLM на каждый add). Параллелизм внутри процесса — worker.concurrency (по умолчанию 4). Prefetch RabbitMQ — rabbitmq.prefetch (16). После rabbitmq.delivery_limit (5) неуспешных доставок сообщение уходит в DLQ.

Горизонтальное масштабирование в Compose:

docker compose up -d --scale worker=3

В Kubernetes число экземпляров воркера задаётся отдельно от API (см. п. 2.5). API при росте search масштабируется увеличением replicaCount.

8.2. API

Stateless: увеличивайте число реплик Deployment. Пул БД — postgres.pool_size. Эмбеддинг запроса на каждый search идёт в AI Gateway — фактический предел латентности часто определяется шлюзом, а не API.

8.3. OpenSearch

Индексу выделяются CPU/RAM; kNN требователен к памяти. Шаблон индекса: platform_memory/resources/opensearch/index-template.json. Смена размерности эмбеддинга требует нового индекса и перезаписи фактов.

8.4. Ограничения

ПараметрНазначение
top_kSearch: 1–200 (по умолчанию 20); list: до 1000
token_budgetЛимит токенов в выдаче search
thresholdПорог релевантности (по умолчанию 0.1)
ai_gateway.timeout / batch_sizeТаймаут и пачки эмбеддинга
rabbitmq.delivery_limitПосле 5 неуспешных доставок — DLQ
Лимиты ресурсов контейнеровЗащита узла
Пропускная способность AI GatewayФактический предел add (infer) и search

9. Аварийные ситуации

9.1. Недоступность сервиса

  1. Проверить /health и Ingress/Service.
  2. По details определить отказавший компонент (БД, очередь, OpenSearch).
  3. Проверить поды API и worker, события Kubernetes, журналы.
  4. Перезапуск:
# Compose
docker compose restart api worker

# Kubernetes
kubectl -n <namespace> rollout restart deploy/platform-memory
  1. При переполнении диска — очистка журналов/образов, расширение томов OpenSearch/PostgreSQL.
  2. При повреждении данных — восстановление из копии (п. 5.5).
  3. Зафиксировать время, признаки, event_id, выдержки журналов, выполненные действия.

9.2. Эскалация

КатегорияПризнакиОтветственный
ФункциональноеНекорректные факты, скоупы, качество поискаВладелец агентов / функциональная команда
ИнфраструктурноеПоды, сеть, диски, Helm, зависимостиАдминистратор контура
ПлатформенноеДефект API/worker, контракт mem0, пайплайн извлеченияКоманда Platform Memory

Перед эскалацией: версия образа/чарта, описание, затронутые workspace/agent_id, event_id, журналы, время, уже выполненные действия. Контакты — приложение В.


10. Примеры запросов для проверки системы

Базовый URL локального Compose: http://127.0.0.1:8093. При запуске API на хосте с портом из конфига: http://127.0.0.1:8091. При port-forward Helm: http://127.0.0.1:8091. Ниже $BASE — выбранный URL.

export BASE=http://127.0.0.1:8093
export WS=ws-admin-check
export USER=user-admin-check
export AGENT=procurement-assistant-v1

Все вызовы кроме /health требуют заголовков X-Workspace-Id и X-User-Id.

10.1. Живучесть

curl -fsS "$BASE/health"

Ожидается HTTP 200 и JSON вида:

{
  "status": "ok",
  "components": {
    "postgres": "ok",
    "opensearch": "ok",
    "rabbitmq": "ok"
  },
  "details": {}
}

Если status равен degraded, смотрите details.<компонент>.error — процесс API запущен, но зависимость недоступна.

OpenAPI: $BASE/docs, $BASE/openapi.json.

10.2. Запись памяти (async add, infer)

curl -sS -X POST "$BASE/v1/memories" \
  -H "Content-Type: application/json" \
  -H "X-Workspace-Id: $WS" \
  -H "X-User-Id: $USER" \
  -d '{
    "messages": [
      {"role": "user", "content": "Я работаю в отделе закупок, отчёты нужны в xlsx"},
      {"role": "assistant", "content": "Понял, буду присылать xlsx"}
    ],
    "agent_id": "'"$AGENT"'",
    "run_id": "run-admin-check-1",
    "infer": true,
    "metadata": {"source": "admin-check"}
  }'

Ожидается 202:

{
  "event_id": "<uuid>",
  "status": "PENDING"
}

Без agent_id и run_id — 400. Без заголовков идентичности — 422. При недоступном RabbitMQ — 503 с error: queue_unavailable.

export EVENT_ID='<uuid из ответа>'

Для проверки записи без LLM (если шлюз ещё не готов):

curl -sS -X POST "$BASE/v1/memories" \
  -H "Content-Type: application/json" \
  -H "X-Workspace-Id: $WS" \
  -H "X-User-Id: $USER" \
  -d '{
    "messages": [
      {"role": "user", "content": "Предпочитает отчёты в формате xlsx"}
    ],
    "agent_id": "'"$AGENT"'",
    "infer": false
  }'

10.3. Статус события

curl -sS "$BASE/v1/events/$EVENT_ID" \
  -H "X-Workspace-Id: $WS" \
  -H "X-User-Id: $USER"

Ожидается 200. Цепочка: PENDING → SUCCEEDED | FAILED. Чужой workspace даёт 404.

while true; do
  st=$(curl -sS "$BASE/v1/events/$EVENT_ID" \
    -H "X-Workspace-Id: $WS" -H "X-User-Id: $USER" \
    | python3 -c "import sys,json; print(json.load(sys.stdin)['status'])")
  echo "status=$st"
  case "$st" in SUCCEEDED|FAILED) break ;; esac
  sleep 2
done

При SUCCEEDED в ответе будут memory_ids. При FAILED смотрите поле error и журнал worker. Если статус не меняется — воркер не запущен или нет потребителя очереди memory.add.jobs.

10.4. Список фактов

curl -sS "$BASE/v1/memories?agent_id=$AGENT&page_size=20" \
  -H "X-Workspace-Id: $WS" \
  -H "X-User-Id: $USER"

Ожидается 200, объект с count и массивом results (id, memory, скоупы, created_at). Без agent_id и run_id — 400.

10.5. Поиск

curl -sS -X POST "$BASE/v1/memories/search" \
  -H "Content-Type: application/json" \
  -H "X-Workspace-Id: $WS" \
  -H "X-User-Id: $USER" \
  -d '{
    "query": "в каком формате присылать отчёт",
    "filters": {"agent_id": "'"$AGENT"'"},
    "top_k": 5,
    "token_budget": 400,
    "threshold": 0.1,
    "explain": true
  }'

Ожидается 200:

{
  "results": [
    {
      "id": "<uuid>",
      "memory": "Предпочитает отчёты в формате xlsx",
      "agent_id": "procurement-assistant-v1",
      "score": 0.91,
      "created_at": "2026-08-18T10:12:00Z"
    }
  ],
  "tokens_returned": 48
}

Запрос с другим X-User-Id или X-Workspace-Id не должен возвращать факты стендовой проверки (изоляция скоупов).

10.6. История записи

export MEMORY_ID='<uuid из list или search>'

curl -sS "$BASE/v1/memories/$MEMORY_ID/history" \
  -H "X-Workspace-Id: $WS" \
  -H "X-User-Id: $USER"

Ожидается 200 и массив записей с event: ADD / UPDATE / DELETE.

10.7. Удаление по скоупу (право на забвение)

curl -sS -X DELETE "$BASE/v1/memories?agent_id=$AGENT" \
  -H "X-Workspace-Id: $WS" \
  -H "X-User-Id: $USER"

Ожидается 200:

{
  "message": "All relevant memories deleted",
  "deleted_count": 1,
  "confirmation_id": "<uuid>"
}

Повторный list/search по тому же агенту не должен возвращать удалённые факты. Попытка ?user_id=other-user при заголовке X-User-Id: $USER — 403.

После удаления контрольный search из п. 10.5 возвращает пустой results.

10.8. Негативные проверки

ПроверкаЗапросОжидание
Нет workspaceлюбой /v1/* без X-Workspace-Id422
Нет userбез X-User-Id422
Add без скоупаPOST /v1/memories только с messages400
List без скоупаGET /v1/memories400
Delete без фильтраDELETE /v1/memories400
Чужой user при deleteDELETE /v1/memories?user_id=other403
Несуществующее событиеGET /v1/events/{uuid}404
Очередь недоступнаPOST /v1/memories при остановленном RabbitMQ503 queue_unavailable

10.9. Что не вызывать на текущем релизе

Контракт (platform-memory-specs/contracts.md) описывает пути, которых в текущем API нет:

МетодПутьНазначение в контракте
GET/v1/memories/{memory_id}Одна запись
PUT/v1/memories/{memory_id}Изменение текста/метаданных
DELETE/v1/memories/{memory_id}Soft-delete одной записи
POST/v1/sessions/{session_id}/stateРабочая память / checkpoint
GET/v1/sessions/{session_id}/stateВосстановление checkpoint

Список, поиск, async add, статус события, история и удаление по скоупу — реализованы. JWT, SpiceDB, Guardrails и audit-клиент платформы — целевое состояние R1 по PRD, в текущей поставке не включены.


Приложение А. Ключевые параметры конфигурации

Перечень типовой; имена сверяются с config/config_template.yaml и helm/platform-memory/values.yaml. Переопределение — MEMORY__<СЕКЦИЯ>__<ПОЛЕ>.

ПараметрНазначение
MEMORY_CONFIGПуть к YAML (в контейнере /app/config/config.yaml или config.docker.yaml)
api.host / api.portСлушатель API (0.0.0.0:8091)
app.environmentМетка среды (dev / prod)
app.create_schema_on_startupСоздание схемы PostgreSQL при старте API
worker.concurrencyПараллелизм обработки событий в процессе worker (4)
postgres.dsnpostgresql+asyncpg://…
postgres.schema_nameПо умолчанию platform_memory
postgres.pool_sizeПул соединений (5)
rabbitmq.host / port / username / passwordБрокер
rabbitmq.exchange / queue / dlx / dlqmemory.add / memory.add.jobs / memory.add.dlx / memory.add.dlq
rabbitmq.prefetch / delivery_limit / heartbeat16 / 5 / 60
opensearch.hosts / index_aliasКластер и алиас (mem-facts-dev, mem-facts-prod)
opensearch.embedding_dimensionРазмерность kNN (1024)
opensearch.verify_certsTLS-проверка (в проде true)
embedding.model / dimensionМодель эмбеддинга у AI Gateway
ai_gateway.url / api_key / llm_modelШлюз моделей
ai_gateway.timeout / batch_size / dry_run120 / 32 / false
log.levelПодробность журналов
ingress.hostsВнешний DNS (Helm)
replicaCountРеплики API в чарте

Приложение Б. Контрольный перечень развёртывания

  • Подготовлены ресурсы и доступ к реестру образов.
  • Собран и опубликован образ одной версии для API и worker.
  • Заданы (или подняты) PostgreSQL, RabbitMQ, OpenSearch, AI Gateway.
  • Создан Secret; в values нет паролей.
  • Модель эмбеддинга и размерность согласованы с индексом OpenSearch.
  • Для Compose: проверен docker compose ps (сервисы api, worker, postgres, rabbitmq, opensearch) и /health.
  • Для Kubernetes: helm lint / helm template; релиз установлен с --atomic --wait.
  • Под API запущен platform-memory-worker (иначе add не завершится).
  • В Helm values заданы config.rabbitmq.* (не localhost).
  • Выполнены запросы раздела 10: health, add, event SUCCEEDED, search, list, history, delete.
  • Настроены снимки PostgreSQL и OpenSearch; проверена процедура восстановления.
  • Закрыты лишние порты; наружу только API.
  • Зафиксированы версия образа, версия чарта, контакты эскалации.

На этой странице

Назначение и область примененияУсловные обозначенияТермины и сокращения1. Архитектура сервиса1.1. Общая схема1.2. Состав компонентов1.3. Потоки данных1.4. Минимальные ресурсы2. Установка и развёртывание2.1. Предварительные требования2.2. Получение дистрибутива2.3. Настройка конфигурации2.4. Развёртывание в Docker ComposeВариант A. Инфраструктура в Docker, приложение на хостеВариант B. Полный стек в Compose2.5. Развёртывание в Kubernetes (Helm)ПодготовкаУстановкаВоркер в KubernetesОсобенности промышленного контура3. Подключение моделей4. Доступ и изоляция памяти4.1. Идентичность вызывающего4.2. Скоупы4.3. Право на забвение5. Безопасность5.1. Секреты5.2. Сетевые ограничения5.3. Хранение данных5.4. Резервное копирование5.5. Восстановление6. Обновление сервиса6.1. Docker Compose6.2. Kubernetes (Helm)6.3. Схема базы данных6.4. Откат7. Мониторинг и журналы7.1. Состояние сервисов7.2. Журналы7.3. Типовые нарушения8. Производительность и масштабирование8.1. Воркеры извлечения8.2. API8.3. OpenSearch8.4. Ограничения9. Аварийные ситуации9.1. Недоступность сервиса9.2. Эскалация10. Примеры запросов для проверки системы10.1. Живучесть10.2. Запись памяти (async add, infer)10.3. Статус события10.4. Список фактов10.5. Поиск10.6. История записи10.7. Удаление по скоупу (право на забвение)10.8. Негативные проверки10.9. Что не вызывать на текущем релизеПриложение А. Ключевые параметры конфигурацииПриложение Б. Контрольный перечень развёртывания