Руководство администратора 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 API | Stateless 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: true | LLM-извлечение фактов из 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; пакет приложения; установленный экземпляр |
| mem0 | OSS-контракт и алгоритмы add/search, на которых построена реализация |
1. Архитектура сервиса
1.1. Общая схема
Сервис состоит из двух прикладных нагрузок без локального состояния: API (синхронное чтение и приём записи) и воркер извлечения (асинхронный write-path). Состояние хранится во внешних сервисах данных. Модели вызываются только через AI Gateway.

Разделение ответственности: агент не проектирует хранилище и пайплайн извлечения. Platform Memory принимает ход диалога, извлекает факты вне критического пути ответа пользователю и отдаёт релевантные факты в пределах бюджета токенов.
1.2. Состав компонентов
| Компонент | Назначение | Примечание |
|---|---|---|
platform-memory-api | HTTP API: add, search, list, history, events, /health | Stateless. Контейнерный порт 8091; в Compose публикуется как 8093 |
platform-memory-worker | Обработка add: claim события → mem0 Memory.add → индекс и история | Масштабируется независимо (worker.concurrency) |
| PostgreSQL | Event 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 ГБ |
| OpenSearch | 512 МБ heap (Compose) | отдельный кластер, реплики индекса |
| PostgreSQL | 1 ГБ | внешний отказоустойчивый кластер |
| Диск | 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 version2.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:
| Сервис | Порт на хосте | Назначение |
|---|---|---|
| API | 8093 → 8091 | HTTP API |
| PostgreSQL | 5435 → 5432 | БД сервиса |
| RabbitMQ AMQP | 5674 → 5672 | Очередь add |
| RabbitMQ management | 15674 → 15672 | UI брокера |
| OpenSearch | 9202 → 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-workerAPI слушает 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 -v2.5. Развёртывание в Kubernetes (Helm)
Чарт: helm/platform-memory. Канонические команды также приведены в helm/platform-memory/README.md и docs/helm-deployment.md.
Подготовка
- Собрать и опубликовать образ.
- Проверить сетевую доступность PostgreSQL, RabbitMQ, OpenSearch и AI Gateway из целевого пространства имён.
- Создать 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.
- Подготовить 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 / 443 | HTTP/HTTPS | Memory API |
| API / worker | 5432 | PostgreSQL | Event store и история |
| API / worker | 5672 | AMQP | Очередь add |
| API / worker | 9200 | HTTP/HTTPS | OpenSearch |
| API / worker | 443 | HTTPS | AI Gateway |
| Администраторы | 22 / API Kubernetes | SSH / 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. Восстановление
- Развернуть ту же версию сервиса (раздел 2) с прежними секретами и той же размерностью эмбеддинга.
- Восстановить PostgreSQL (схема
platform_memory). - Восстановить снимки OpenSearch (алиас
mem-facts-<env>). - Запустить 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 10m6.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/healthKubernetes
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 podsGET /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, событие зависло в PENDING | Worker, RabbitMQ | Воркер не запущен; нет потребителя очереди |
Событие FAILED | Журнал worker, поле error | Ошибка AI Gateway, OpenSearch, пайплайна mem0 |
| Search пустой при наличии фактов | Скоупы, workspace | Другой agent_id/user_id/X-Workspace-Id; событие ещё не SUCCEEDED |
| Search медленный | AI Gateway, OpenSearch | Эмбеддинг запроса; нехватка heap у индекса |
403 на DELETE | user_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_k | Search: 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. Недоступность сервиса
- Проверить
/healthи Ingress/Service. - По
detailsопределить отказавший компонент (БД, очередь, OpenSearch). - Проверить поды API и worker, события Kubernetes, журналы.
- Перезапуск:
# Compose
docker compose restart api worker
# Kubernetes
kubectl -n <namespace> rollout restart deploy/platform-memory- При переполнении диска — очистка журналов/образов, расширение томов OpenSearch/PostgreSQL.
- При повреждении данных — восстановление из копии (п. 5.5).
- Зафиксировать время, признаки,
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-Id | 422 |
| Нет user | без X-User-Id | 422 |
| Add без скоупа | POST /v1/memories только с messages | 400 |
| List без скоупа | GET /v1/memories | 400 |
| Delete без фильтра | DELETE /v1/memories | 400 |
| Чужой user при delete | DELETE /v1/memories?user_id=other | 403 |
| Несуществующее событие | GET /v1/events/{uuid} | 404 |
| Очередь недоступна | POST /v1/memories при остановленном RabbitMQ | 503 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.dsn | postgresql+asyncpg://… |
postgres.schema_name | По умолчанию platform_memory |
postgres.pool_size | Пул соединений (5) |
rabbitmq.host / port / username / password | Брокер |
rabbitmq.exchange / queue / dlx / dlq | memory.add / memory.add.jobs / memory.add.dlx / memory.add.dlq |
rabbitmq.prefetch / delivery_limit / heartbeat | 16 / 5 / 60 |
opensearch.hosts / index_alias | Кластер и алиас (mem-facts-dev, mem-facts-prod) |
opensearch.embedding_dimension | Размерность kNN (1024) |
opensearch.verify_certs | TLS-проверка (в проде true) |
embedding.model / dimension | Модель эмбеддинга у AI Gateway |
ai_gateway.url / api_key / llm_model | Шлюз моделей |
ai_gateway.timeout / batch_size / dry_run | 120 / 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.
- Зафиксированы версия образа, версия чарта, контакты эскалации.