Руководство администратора ИС "Платформа ИИ"
ООО "ГК "Иннотех", домен Искусственный интеллект, 2026 г.
Глоссарий
| Термин / Аббревиатура | Расшифровка / Описание |
|---|---|
| A2A | Agent-to-Agent протокол (версия 1.0) |
| Agent Registry | Каталог агентов: REST API, поиск, авторизация, мониторинг рабочих нагрузок в Kubernetes |
| Kubernetes Reconciler | Сервис Agent Registry, автоматически обнаруживающий и наблюдающий за рабочими нагрузками |
| Outbox Relay | Компонент Agent Registry, публикующий зафиксированные события в Redpanda |
| Search Indexer | Компонент Agent Registry, обновляющий разрешения SpiceDB и документы OpenSearch |
| Search Reindex | Задание Agent Registry для построения нового поколения поискового индекса |
| Retention | Задание Agent Registry, применяющее сроки хранения данных |
| Поток (Flow) | Визуальный граф (набор связанных узлов/компонентов), который описывает логику агента |
| Low-code IDE | Адаптированная версия LangFlow — среда визуального редактирования Потока (Flow) |
| Low-code Runtime | Среда выполнения агентов с низкой кодовой базой; исполняет одну версию одного агента |
| Garden | Единый инструмент сборки и деплоя компонентов платформы |
| Helm | Система управления пакетами Kubernetes, используемая через Garden |
| PostgreSQL | Каноническое хранилище метаданных каталога и рабочих версий Flow |
| Alembic | Система миграций базы данных PostgreSQL |
| SpiceDB | Хранилище разрешений и проверок доступа |
| Redpanda | Канал изменений событий (Outbox), отключён по умолчанию |
| OpenSearch | Поисковая проекция, отключена по умолчанию |
| OpenTelemetry Collector | Сбор метрик, трассировок и журналов |
| Keycloak | Временный издатель OpenID Connect для разработки |
| AI Gateway | Платформенная служба маршрутизации запросов |
| MCP | Model Context Protocol |
| SSE | Server-Sent Events |
| SSO | Single Sign-On |
| OIDC | OpenID Connect |
| REST API | Application Programming Interface на основе HTTP |
| SBOM | Software Bill of Materials — перечень компонентов образа |
| FileRef | Ссылка на файл в объектном хранилище |
| lfx | Внутренний интерфейс LangFlow, не публикуется наружу |
| PlatformRAG | Платформенный сервис retrieval-augmented generation: реестр коллекций, приём нормализованных документов, гибридный поиск с фильтрацией по правам доступа |
| PlatformMemory | Управляемый сервис памяти агентов: персистентная память, поиск и дедупликация фактов |
| Principal | Пользователь или сервис в каталоге |
| Workspace | Рабочая область — контейнер агентов и участников |
| Team | Команда-владелец агента |
| traceId | Безопасный идентификатор события для связи логов и трассировок |
| Коллекция | Управляемый индекс знаний: профиль эмбеддинга, модель ACL, стратегия чанкинга, параметры поиска |
| Ingest | Асинхронный приём: регистрация задания → чанкинг → эмбеддинг → индексация |
| Retrieval | Синхронный поиск: гибридный kNN+BM25, слияние RRF, фильтр tenant+ACL, цитаты |
| RAG API | Stateless HTTP-сервис (platform-rag-api), порт 8090 |
| RAG Worker | Процесс platform-rag-worker, обрабатывающий задания ingest из RabbitMQ |
| Job store | Таблица platform_rag.ingest_job в PostgreSQL — источник истины по заданиям приёма |
| ACL | Список групп и субъектов на документе; перепроверяется в момент запроса |
| Act-цепочка | Делегированная идентичность пользователя (JWT / заголовки), по которой строится фильтр выдачи |
| Fail-closed | При недоступности AuthZ сервис отвечает 503 и не выдаёт данные |
| RRF | Reciprocal Rank Fusion — слияние ранжированных списков vector/BM25 |
| KEDA | Автомасштабирование воркеров по числу заданий PENDING в PostgreSQL |
| RabbitMQ | Брокер уведомлений ingest (exchange: rag.ingest, quorum-очередь rag.ingest.jobs) |
Общие сведения
Платформа ИИ обеспечивает создание, регистрацию, каталогизацию и вызов AI-агентов в среде Kubernetes. Платформа состоит из основных компонентов, каждый из которых имеет собственную границу данных и зону ответственности.
Low-code IDE — среда визуального редактирования Flow на основе адаптированной версии LangFlow. Она обеспечивает вход пользователей через платформенный SSO, отображение разрешённой палитры компонентов, серверную проверку схем, сохранение рабочих версий и передачу версионированных артефактов потребителям контракта. Low-code IDE не занимается исполнением запросов, развёртыванием среды выполнения или управлением записями каталога.
Low-code Runtime — неизменяемая среда выполнения, в которой один экземпляр выполняет одну версию одного агента. Runtime принимает Flow и манифест по токену, проверяет контрольные суммы, загружает Flow и публикует согласованные A2A и MCP интерфейсы. Внутренний административный API LangFlow и интерфейс lfx не публикуются наружу. Runtime не подключается к базе Low-code IDE и не загружает изменяемые рабочие копии.
Agent Registry — каталог агентов с REST API, поиском и авторизацией. Он автоматически обнаруживает рабочие нагрузки в Kubernetes через Reconciler (по Service и EndpointSlice), загружает карточки агентов, проверяет соответствие заявленных возможностей, управляет разрешениями через SpiceDB и обеспечивает транзакционную доставку событий через Redpanda. Поиск проекцируется в OpenSearch. Agent Registry не создаёт записи вручную — регистрация происходит автоматически.
Platform RAG — платформенный сервис уровня COMMON, предоставляющий управляемое извлечение знаний (retrieval-augmented generation): реестр коллекций, приём нормализованных документов, гибридный поиск с обязательной фильтрацией по правам доступа и выдачу фрагментов с цитатами. Потребители обращаются к сервису через санкционированные пути: платформенный SDK (platform-rag) или кастом-компонент low-code. Построение собственного retrieval внутри Flow (generic HTTP, ключи моделей во Flow, захардкоженные URL) не допускается. Platform RAG использует PostgreSQL (реестр коллекций и job store), RabbitMQ (очередь ingest), OpenSearch (индекс чанков: knn_vector + BM25), AI Gateway (эмбеддинг и реранк), SpiceDB (права на коллекцию) и S3/MinIO (staging документов).
Platform Memory — единый управляемый слой памяти платформы. Агент получает персистентную память: search перед ответом, add после ответа. Извлечение фактов, дедупликация, гибридный поиск, изоляция по скоупам и история изменений выполняются сервисом, а не каждым агентом отдельно. Память не заменяет RAG. Platform RAG отвечает за корпус документов; Platform Memory — за знания о пользователе, агенте и сессии. Сборка промпта комбинирует оба источника. Публичный контракт совместим с mem0 (add / search / get_all / history / delete). Сервис использует PostgreSQL (event store и история), RabbitMQ (уведомления о заданиях add), OpenSearch (индекс фактов: kNN + BM25) и AI Gateway (эмбеддинг и LLM-извлечение).
Все компоненты развёртываются через Garden — единый инструмент сборки и деплоя. Ручные helm upgrade, kubectl apply или docker-compose не образуют воспроизводимый путь поставки.
Архитектура
Компоненты платформы
| Компонент | Назначение | Основные сигналы |
|---|---|---|
| Agent Registry API | Каталог, получение записи и поиск с учётом прав доступа | Работоспособность, готовность, время ответа, коды 401/403/404/503 |
| Kubernetes Reconciler | Мониторинг Service, EndpointSlice и разрешённых HTTPRoute | Свежесть покрытия, ошибки наблюдения, повторный список, задержка согласования |
| Outbox Relay | Публикация зафиксированных событий в Redpanda | Возраст неопубликованной записи, попытки, срок владения, ошибки брокера |
| Search Indexer | Обновление разрешений SpiceDB и документов OpenSearch | Отставание группы потребителя, повторные события, ошибки проекции |
| Search Reindex | Построение нового поколения поискового индекса | Состояние задания, смещения разделов, количество документов, контрольный набор |
| Retention | Применение сроков хранения | Время завершения, ошибки удаления, сохранность неопубликованной очереди |
| Low-code IDE | Визуальное редактирование Flow, SSO, политика компонентов, серверная проверка и экспорт | Идентификаторы образов, версия LangFlow, версия политики, доступность БД рабочих версий |
| Low-code Runtime | Среда выполнения агентов с низкой кодовой базой | Готовность, карточка A2A/MCP, отсутствие перезапусков и ошибок AI Gateway |
| Platform RAG | Сервис retrieval-augmented generation: коллекции, приём документов, гибридный поиск с ACL | Работоспособность, готовность, статус заданий ingest, глубина очереди, латентность query |
| Platform Memory | Управляемый сервис памяти агентов: async add, search, list, history, delete | Работоспособность, готовность, статус событий add, глубина DLQ, латентность search, отставание извлечения |
Границы компонентов
Low-code IDE владеет:
- визуальным редактированием Flow;
- рабочими версиями Flow в своей базе;
- SSO входом пользователя;
- отображением разрешённой палитры компонентов;
- серверной проверкой и экспортом;
- передачей версионированных данных потребителю контракта Agent Publisher.
Low-code IDE не владеет:
- исполнением промышленного запроса;
- развёртыванием Low-code Runtime;
- записями Agent Registry и разрешениями SpiceDB;
- прямой загрузкой в объектное хранилище в обход Agent Publisher;
- открытыми секретами поставщиков моделей.
Low-code Runtime: один Deployment исполняет одну версию одного агента. Все экземпляры используют одинаковые исходные данные, манифест, образ и настройки. Наружу предоставляются только согласованные A2A и MCP интерфейсы.
Agent Registry: PostgreSQL хранит метаданные. Redpanda, SpiceDB и OpenSearch являются производными или внешними проекциями и восстанавливаются из метаданных и событий.
Platform RAG: PostgreSQL хранит реестр коллекций и job store (platform_rag). OpenSearch — производная проекция чанков (индекс rag-kb-{env}). RabbitMQ и S3 — вспомогательные каналы ingest. AI Gateway и SpiceDB — внешние зависимости. Helm-чарт устанавливает только прикладные нагрузки api и worker; зависимости чартом не устанавливаются.
Platform Memory: PostgreSQL хранит event store и историю записей (схема platform_memory). OpenSearch — индекс фактов (kNN + BM25, алиас mem-facts-{env}). RabbitMQ — очередь уведомлений add. AI Gateway — эмбеддинг и LLM-извлечение. Helm-чарт устанавливает только прикладную нагрузку api; worker запускается отдельно. Зависимости чартом не устанавливаются.
Агент принадлежит команде. Владелец (owner) получает права view и diagnose, но не invoke. Агент привязан к рабочей области. Явные права на использование (invoke) агента могут быть выданы пользователю (principal) и сервису (service). Пользователь является членом команды-владельца. Пользователь имеет роль в рабочей области: member даёт право view к агентам в этом workspace; admin даёт право manage и diagnose.
Неизменяемые входные данные Low-code Runtime
Перед развёртыванием фиксируются:
| Данные | Требование |
|---|---|
| Образ | Неизменяемый идентификатор, полный SBOM и файл блокировки зависимостей |
source.json | JSON Flow и SHA-256 |
manifest.json | platform.low-code.publish-manifest/v1, SHA-256 и ссылка на исходные данные |
| Политика компонентов | Версия, соответствующая разрешённому набору поставки |
| Карточка A2A или описание MCP | Совпадает с манифестом и фактическими возможностями |
| Настройки выпуска | Версия манифестов Kubernetes, ресурсов и регистрационных меток |
Исправление любого байта создаёт новую версию и новую контрольную сумму. Изменять файл внутри работающего контейнера запрещено.
Последовательность запуска Low-code Runtime
- Получить исходный Flow и манифест по токену либо ограниченному полномочию.
- Ограничить тип содержимого, размер и время получения.
- Проверить SHA-256 обоих файлов.
- Проверить Flow, идентичность агента, политику и совместимость с
lfx. - Повторно проверить компоненты, исполняемый код и отсутствие секретов.
- Загрузить Flow через поддерживаемый интерфейс.
- Выполнить проверку эндпоинта без вызова модели.
- Сформировать карточку либо описание и сравнить с разрешёнными возможностями.
- Перейти в состояние готовности.
Регистрационный контракт
Одна сущность Service Kubernetes объявляет один протокол. Если один Deployment агента предоставляет A2A и MCP интерфейсы, создаются две сущности Service с разными логическими именами. Обязательные метки включают регистрацию, протокол, рабочую область, имя, версию, владельца и тип low-code. Аннотация версии контракта равна agent-platform.agent-registry.registration/v1.
Имя агента соответствует виду <domain>-<function>-v<major>, а основная версия имени совпадает с SemVer версии рабочей нагрузки.
Технический стек
Платформенные зависимости
| Зависимость | Назначение | По умолчанию |
|---|---|---|
| PostgreSQL 18 | Каноническое хранилище каталога | Включено |
| SpiceDB | Хранение разрешений и проверок доступа | Включено |
| OpenTelemetry Collector | Сбор метрик, трассировок и журналов | Включено |
| Redpanda | Канал изменений событий (Outbox) | Отключено |
| OpenSearch | Поисковая проекция | Отключено |
Примечание: Redpanda и OpenSearch отключены в профиле
dev-ai-devпо умолчанию. Компоненты Outbox Relay и Search Indexer также отключены, так как зависят от этих служб.
Зафиксированные версии
| Зависимость | Версия поставки |
|---|---|
| Kubernetes | 1.36.x (исходная точная версия 1.36.2) |
| PostgreSQL | 18.4.0; базовый образ и chart 18.8.4 |
| SpiceDB | 1.54.0 |
| Redpanda Community | сервер 26.1.13, chart 26.1.9 |
| OpenSearch | 3.7.0 |
| OpenTelemetry Collector | образ 0.156.0, chart 0.165.0 |
LangFlow / lfx | 1.11.1 |
Основное обновление PostgreSQL на существующем постоянном томе требует отдельной проверки pg_upgrade. В одноразовой среде разработки том можно пересоздать после удаления выпуска Garden; данные промышленной среды так обрабатывать нельзя.
Среда развёртывания
Garden — единственный поддерживаемый инструмент сборки и развёртывания компонентов. Ручные helm upgrade, kubectl apply не образуют воспроизводимый путь поставки.
Образы платформы публикуются в выделенное хранилище артефактов (nexus и т.п.), доступное из узлов кластера dev-ai-dev.
Среды
| Среда | Назначение | Способ доступа | Ограничения |
|---|---|---|---|
dev-ai-dev | Общая среда разработки | Переадресация портов; имя узла предварительное | DNS и TLS не считаются принятыми до договора с DevOps |
st | Интеграционная проверка | Статические адреса среды | Требует собственных зависимостей и подтверждающих материалов |
prod | Не реализована | — | Нужны внешние зависимости, секреты, TLS, масштабирование и порядок отката |
Пространство имен разработчика имеет вид ap-st. Изменять чужое пространство имен и кластерные ресурсы запрещено.
Разделение образов и профили среды
Профиль среды dev-ai-dev хранится в файле deploy/values/dev-ai-dev.yaml. Основные параметры:
| Параметр | Значение |
|---|---|
| Пространство имён | ap-st |
| Контекст Kubernetes | ai-dev |
| kubeconfig | ~/.kube/ai-dev |
| Реестр образов | nexus.inno.tech:19108/ap |
| Режим TLS реестра | false (insecure=false) |
| OIDC-издатель | http://localhost:18081/realms/ap-dev |
| Workspace ID | ap-dev |
| Keycloak Realm | ap-dev |
Включённые и отключённые компоненты в dev-ai-dev
| Компонент | Статус | Причина |
|---|---|---|
| Agent Registry API | Включено | Основной сервис |
| Kubernetes Reconciler | Включено | Обнаружение рабочих нагрузок |
| Outbox Relay | Отключено | Зависит от Redpanda |
| Search Indexer | Отключено | Зависит от OpenSearch |
| Redpanda | Отключено | Не требуется для базового контура |
| OpenSearch | Отключено | Не требуется для базового контура |
| PostgreSQL | Включено | Каноническое хранилище |
| SpiceDB | Включено | Хранение разрешений |
| OpenTelemetry Collector | Включено | Наблюдаемость |
| Документация поставки | Включено | Документация поставки |
| Low-code IDE | Отключено | Поставляется отдельным контуром |
| Platform RAG | Отключено | Поставляется отдельным компонентом |
| Platform RAG API | Отключено | Поставляется отдельным компонентом |
| Platform RAG Worker | Отключено | Поставляется отдельным компонентом |
| Platform Memory | Отключено | Поставляется отдельным компонентом |
| Platform Memory API | Отключено | Поставляется отдельным компонентом |
| Platform Memory Worker | Отключено | Поставляется отдельным компонентом |
Развертывание
Примечание: Инструкция приведена для кластера
ai-dev(ST). Для других сред порядок аналогичен с учётом соответствующего профиля Garden.
Предварительные условия
- Docker доступен текущему пользователю.
- Garden версии
0.14.20установлен. - Файл
kubeconfigдля кластераai-devдоступен по пути~/.kube/ai-dev. - Файл
kubeconfigсодержит контекстai-dev. - Команды выполняются из корня репозитория
agent-platform.
Шаг 1. Проверка конфигурации
Из корня репозитория выполните валидацию:
garden validate --env stПроверка должна завершиться до сборки образов. Если ошибка не исправлена, развёртывание будет прервано. Возможные причины ошибок:
- неверное пространство имён;
- занят один из фиксированных портов
18080–18083; - отсутствует файл
kubeconfig; - недоступен реестр образов.
Шаг 2. Аутентификация в реестре образов
Garden автоматически выполняет действие run.image-registry-auth перед сборкой. Он:
- Выполняет вход в реестр.
- Создаёт или обновляет секрет
ap-image-pull-secretв целевом пространстве имён для возможности загрузки образов.
Ручная аутентификация не требуется. Учётные данные реестра не выводятся в журналы.
Шаг 3. Развёртывание
Запустите развёртывание:
garden deploy --env st --yesGarden выполняет следующие действия по порядку:
- Проверяет доступ к кластеру Kubernetes и реестру образов.
- Собирает образы Agent Registry, Low-code Runtime и документации поставки.
- Публикует образы в
nexus. - Применяет версионированный Helm-чарт
agent-platform. - Поднимает PostgreSQL, SpiceDB и OpenTelemetry Collector.
- Выполняет миграции базы данных (Alembic).
- Запускает рабочие нагрузки Agent Registry.
- Запускает Low-code Runtime.
- Запускает документацию поставки.
Примечание: Таймаут развёртывания для
stсоставляет 300 секунд. Если кластер загружен, поды могут завершать инициализацию дольше обычного. В этом случае проверьте статус подов и журналы перед повторным запуском.
Шаг 4. Проверка развёртывания
Проверка подов
kubectl -n ap-st get podsОжидаемые поды:
| Под | Статус |
|---|---|
ap-agent-registry-api | Running |
ap-agent-registry-kubernetes-reconciler | Running |
ap-agent-registry-low-code-agent | Running |
ap-team-docs-web | Running |
ap-agent-registry-keycloak | Running |
ap-agent-registry-postgresql | Running |
ap-agent-registry-spicedb | Running |
ap-agent-registry-opentelemetry-collector | Running |
Проверка служб и переадресации портов
kubectl -n ap-st get svcПроверка Swagger UI
- Откройте браузером
https://docs.ai-dev.inno.tech. - Нажмите кнопку Authorize.
- Выберите тип аутентификации
oauth2Password. - Укажите имя пользователя
workspace-adminи парольworkspace-admin. - Укажите
client_id=agent-registry-st, секрет клиента оставьте пустым. - Выполните запрос
GET /api/v1/agents?limit=20.
Ожидаемый результат — как минимум два агента:
sdk-smoke-v1с типом реализацииsdk;lowcode-linguist-v1с типом реализацииlow-code.
Обнаружение агентов выполняется асинхронно. Первый пустой ответ допустимо повторить через несколько секунд.
Проверка Low-code Runtime
Подтвердите работоспособность среды выполнения:
- Неразрушающая проверка (
/health/live) возвращает200. - Проверка готовности (
/health/ready) возвращает200. - Карточка агента A2A содержит регистрационные метки.
- Версия агента автоматически появляется в каталоге Agent Registry.
Примечание: Проверка вызова модели требует действительного ключа AI Gateway. Без ключа допустима только проверка обнаружения и связности.
Доступные адреса
| Компонент | URL |
|---|---|
| Платформа ИИ | https://api-gw.ai-dev.inno.tech/agent-registry |
| Keycloak | https://api-gw.ai-dev.inno.tech/keycloak |
| Low-code fixture | https://api-gw.ai-dev.inno.tech/a2a/lowcode-linguist-v1 |
| Low-code IDE | https://ide.ai-dev.inno.tech |
| Team Docs | https://docs.ai-dev.inno.tech |
Правила работы в среде
- Писать только в пространство имён
ap-st. - Запрещено изменять GatewayClass, Gateway, IngressClass, cluster-операторы и чужие пространства имён.
- Cluster-scoped RBAC выключен в Helm-значениях.
- Создание и ротация секретов требуют отдельного подтверждения человека.
- Garden system-метаданные направляются в целевое пространство имён, а не в общий
garden-system.
Устранение неполадок
Поды не переходят в состояние Running
- Проверьте статус подов:
kubectl -n ap-st get pods --sort-by=.metadata.creationTimestamp - Просмотрите журналы проблемного пода:
kubectl -n ap-st logs <pod-name> --tail=200 - Проверьте события:
kubectl -n ap-st get events --sort-by=.lastTimestamp - Наиболее частая причина — pods не готовы, а не сбой Helm. Повторите
garden deployпосле устранения причины.
Занятые порты
Garden использует фиксированные локальные порты 18080–18083. Если один из них занят, развёртывание завершается ошибкой до начала rollout. Освободите порт или завершите процесс, использующий его.
Ошибка аутентификации реестра
Если действие run.image-registry-auth завершается ошибкой:
- Проверьте доступность
nexus. - Убедитесь, что учётные данные реестра корректны.
- Проверьте, что kubeconfig содержит контекст
ai-dev.
Ошибка миграции базы данных
- Остановите развёртывание.
- Сохраните журнал миграции Alembic.
- Восстановите совместимый образ приложения.
- Убедитесь, что
alembic checkне выдаёт ошибок перед повторной попыткой.
Фикстуры пользователей
При развёртывании создаются ролеориентированные пользователи Keycloak:
| Пользователь | Роль | Пароль |
|---|---|---|
workspace-admin | Администратор рабочей области | workspace-admin |
agent-invoker | Вызывающий агент | agent-invoker |
unauthorized-user | Запрещённый пользователь (тест) | unauthorized-user |
Пароль каждого фикстурного пользователя совпадает с именем. Эти учётные записи создаются только в non-production средах и не переносятся в промышленную эксплуатацию.
Фикстуры агентов
По умолчанию создаются два тестовых агента:
| Агент | Тип реализации | Описание |
|---|---|---|
sdk-smoke-v1 | sdk | Дымовой тест агента |
lowcode-linguist-v1 | low-code | Агент Low-code Runtime |
Завершение работы
Для полного удаления развёртывания:
garden deploy --env st --uninstallИли удалите пространство имён вручную:
kubectl delete namespace ap-stПримечание: При удалении пространства имён все данные PostgreSQL, SpiceDB и OpenSearch будут безвозвратно удалены.
Сводная таблица команд
| Действие | Команда |
|---|---|
| Валидация конфигурации | garden validate --env st |
| Развёртывание | garden deploy --env st --yes |
| Проверка подов | kubectl -n ap-st get pods |
| Проверка служб | kubectl -n ap-st get svc |
| Удаление развёртывания | garden deploy --env st --uninstall |
Материалы для фиксации результата
При развёртывании сохраните:
- точную команду, среду и время выполнения;
- версии Garden, Docker и Kubernetes;
- пространство имён и версии действий Garden;
- идентификаторы собранных образов;
- результаты миграций базы данных;
- проверки работоспособности подов;
- результаты тестирования API;
- ограничения среды (отключённые компоненты, внутрикластерные DNS).
Не сохраняйте в журнале учётные данные, токены и пользовательские запросы.
Развертывание SDK агента
Как работает регистрация
В Agent Registry нет отдельной операции создания агента. Регистрация выполняется автоматически после развёртывания рабочей нагрузки и k8s сущности Service с регистрационными метками в доверенном пространстве имён Kubernetes.
Agent Registry:
- обнаруживает
Service; - проверяет метки, аннотации и привязку пространства имён к рабочему пространству;
- дожидается готового адреса из принадлежащей службе
EndpointSlice; - загружает карточку агента по внутреннему адресу службы;
- проверяет A2A 1.0, имя, версию, навыки и заявленные возможности;
- добавляет разрешённую проекцию агента в каталог.
Объектом регистрации является Service, а не Deployment или отдельный Pod. Перезапуск экземпляра не создаёт новую запись, пока служба и логическая версия агента остаются прежними.
Что подготовить заранее
До развёртывания запросите у владельца среды:
- точное пространство имён, включённое в состав доверенных в Agent Registry;
- идентификатор рабочего пространства для регистрационной метки;
- идентификатор команды из доверенного каталога владельцев;
- разрешённый способ доставки через Garden и Helm;
- требования среды к внутреннему TLS и публичному маршруту;
- права на просмотр и, при необходимости, вызов зарегистрированного агента.
Имя агента имеет форму <domain>-<function>-v<major> и должно быть допустимым DNS именем длиной не более 63 символов. Суффикс имени должен совпадать с основной частью SemVer: версии 1.0.0 соответствует суффикс -v1.
Подготовка карточки агента
Агент должен возвращать карточку по адресу /.well-known/agent-card.json, если в аннотации службы не указан другой безопасный абсолютный путь.
Минимальный пример для A2A 1.0 HTTP+JSON:
{
"name": "finance-invoice-v1",
"description": "Проверяет счет и извлекает структурированные поля.",
"supportedInterfaces": [
{
"url": "https://agent.example/a2a/finance-invoice-v1",
"protocolBinding": "HTTP+JSON",
"protocolVersion": "1.0"
}
],
"version": "1.2.0",
"capabilities": {
"streaming": true,
"pushNotifications": false,
"extendedAgentCard": false
},
"defaultInputModes": ["application/json", "text/plain"],
"defaultOutputModes": ["application/json"],
"skills": [
{
"id": "invoice_parsing",
"name": "Разбор счета",
"description": "Извлекает нормализованные поля из счета.",
"tags": ["invoice", "finance"],
"examples": ["Извлеки поставщика, сумму и НДС из этого счета"]
}
]
}Значения name и version должны точно совпадать с метками службы. В поставке 2026.3.3 для HTTP+JSON подтверждена возможность streaming. Не объявляйте неподдерживаемую возможность: Agent Registry не запускает агент для пробного вызова во время регистрации и полагается на правдивую неизменяемую карточку и проверку совместимости до развёртывания.
Публикация Service
Рабочая нагрузка должна иметь именованный порт и проверку готовности. Рядом с ней опубликуйте службу с селектором:
apiVersion: v1
kind: Service
metadata:
name: finance-invoice-v1
namespace: finance
labels:
agent-platform.inno.tech/registrable: "true"
agent-platform.inno.tech/protocol: a2a
agent-platform.inno.tech/workspace: finance
agent-platform.inno.tech/agent-name: finance-invoice-v1
agent-platform.inno.tech/version: "1.2.0"
agent-platform.inno.tech/owner: team-finance-ai
agent-platform.inno.tech/implementation-type: sdk
annotations:
agent-platform.inno.tech/registration-contract: agent-platform.agent-registry.registration/v1
agent-platform.inno.tech/card-path: /.well-known/agent-card.json
agent-platform.inno.tech/service-port: a2a
spec:
type: ClusterIP
selector:
app.kubernetes.io/name: finance-invoice-v1
ports:
- name: a2a
protocol: TCP
port: 8443
targetPort: a2aОбязательные значения:
| Поле | Требование |
|---|---|
registrable | Только строка true |
protocol | a2a |
workspace | Совпадает с доверенной привязкой пространства имён |
agent-name | Совпадает с карточкой и основной частью версии |
version | SemVer без метаданных сборки |
owner | Существующий идентификатор команды |
implementation-type | sdk |
registration-contract | Точная ревизия agent-platform.agent-registry.registration/v1 |
service-port | Имя единственного порта A2A |
Поддерживается служба ClusterIP с селектором. Не используйте ExternalName, службу без селектора, созданный вручную EndpointSlice или publishNotReadyAddresses: true.
Проверка регистрации
Сначала проверьте готовность рабочей нагрузки и принадлежность адреса службе:
kubectl --namespace finance get service/finance-invoice-v1 --output=wide
kubectl --namespace finance get endpointslice \
--selector kubernetes.io/service-name=finance-invoice-v1 \
--output=wideДля диагностики в непроизводственной среде получите у владельца среды разрешённый тестовый адрес и проверьте карточку:
curl --fail --silent --show-error \
"${AGENT_TEST_URL}/.well-known/agent-card.json" \
| jq '{name, version, supportedInterfaces, capabilities, skills}'Схему внутреннего соединения и доверенный сертификат выбирает среда. Не отключайте проверку TLS ради диагностики.
После асинхронного обнаружения запросите каталог с пользовательским токеном:
curl --fail --silent --show-error \
"${REGISTRY_URL}/api/v1/agents?workspaceId=finance&protocol=a2a&implementationType=sdk&limit=20" \
--header "Authorization: Bearer [REDACTED]" \
| jq '.items[] | select(.name == "finance-invoice-v1") | {
id,
name,
implementationType,
lifecycleStatus,
selectedVersion
}'Успешная запись имеет состояние active, тип реализации sdk и выбранную версию, совпадающую с карточкой. Отсутствие публичного интерфейса при этом означает, что доверенный маршрут ещё не готов; это не ошибка регистрации.
Проверка потоковой передачи A2A
Если карточка содержит streaming: true, до публикации версии проверьте фактический HTTP+JSON SSE-путь. Для контролируемой непроизводственной среды:
message_id="$(python3 -c 'import uuid; print(uuid.uuid4())')"
curl --no-buffer --fail-with-body --show-error \
--request POST "${AGENT_TEST_URL}/message:stream" \
--header 'A2A-Version: 1.0' \
--header 'Accept: text/event-stream' \
--header 'Content-Type: application/a2a+json' \
--data-binary @- <<JSON
{
"message": {
"messageId": "${message_id}",
"role": "ROLE_USER",
"parts": [
{
"text": "Проверь тестовый документ",
"mediaType": "text/plain"
}
]
}
}
JSONПоток должен начинаться отправленной задачей, содержать рабочее состояние и последовательные обновления результата, а завершаться терминальным состоянием. Разрыв соединения, повторная подписка и получение завершенной задачи должны соответствовать A2A 1.0. Agent Registry сохраняет возможность потоковой передачи в каталоге, но не выполняет этот тест вместо разработчика.
Разбор ошибки регистрации
| Наблюдение | Возможная причина | Действие |
|---|---|---|
| Агент отсутствует в каталоге | Пространство имён не входит в состав доверенных или нет прав наблюдения | Обратиться к владельцу Agent Registry; не добавлять обходную ручную запись |
Состояние rejected | Метки, имя, версия, путь или карточка не прошли проверку | Сверить службу и карточку, затем опубликовать исправленную неизменяемую версию |
Состояние degraded | Нет пригодного готового адреса или карточка временно недоступна | Проверить готовность экземпляров, EndpointSlice, порт и внутренний TLS |
Запись active, но интерфейса нет | Не принят маршрут Platform Agent Gateway или нет права вызова | Проверить маршрут и отношение agent#invoke у владельца среды |
| Карточка доступна напрямую, но Registry её не принимает | Имя или версия карточки расходятся с метками либо заявлена неподтверждённая возможность | Исправить контракт и повторить поставку |
Важно: При обращении в поддержку передавайте имя агента, версию, пространство имён, время развёртывания и безопасный
traceId. Не передавайте токен, секрет модели, внутренние учётные данные и полный закрытый запрос.
Обновление зарегистрированного агента
Карточка и возможности опубликованной версии неизменяемы. При изменении поведения, навыков, входных данных или возможностей:
- назначьте новую SemVer;
- согласованно обновите карточку, образ и метку версии службы;
- повторите проверки A2A и готовности;
- дождитесь появления новой выбранной версии в Agent Registry;
- сохраняйте предыдущую версию как явную точку отката на принятый срок.
При переходе с 1.x на 2.x измените суффикс логического имени с -v1 на -v2. Не меняйте содержимое уже опубликованной версии без изменения SemVer.
Граница безопасности
- Не помещайте ключи, токены и внутренние адреса в метки или описание карточки.
- Не публикуйте сырой адрес
Serviceкак пользовательский интерфейс. - Не считайте регистрацию разрешением на просмотр или вызов.
- Не передавайте исходный пользовательский токен непосредственно SDK-агенту.
- В производственной среде вызывайте агент только через интерфейс Platform Agent Gateway, возвращенный Agent Registry после проверки прав.
Обновление и откат
Поддерживаемая граница
Для версии 2026.3.3 подтверждается установка в непромышленных средах. Порядок промышленного обновления не считается принятым до появления всех неизменяемых артефактов, проверки внешних зависимостей и испытанного отката.
Обновление рассматривается как согласованное изменение трёх компонентов, даже если они поставляются разными проектами. Нельзя обновлять Low-code IDE, Low-code Runtime без проверки уже сохраненных и пригодных для отката Flow.
Подготовка
Зафиксируйте текущее и целевое состояние:
| Область | Что записать |
|---|---|
| Agent Registry | Идентификаторы образов, версию OpenAPI, Alembic, схему SpiceDB, поколение OpenSearch и версию chart |
| Low-code Runtime | Идентификатор образа, политику компонентов, Flow A2A/MCP/FileRef |
| Low-code IDE | Идентификаторы клиентского и серверного образов, версию LangFlow, базу рабочих версий, политику и проверяющий модуль |
| Артефакт агента | Версию, SHA-256 исходных данных и манифеста, список пригодных для отката версий |
| Среда | Kubernetes, внешние зависимости, значения Garden и пространство имен |
Проверьте резервное копирование и фактическую возможность восстановления PostgreSQL Agent Registry и базы Low-code IDE. Для OpenSearch достаточно пересоздания из метаданных.
Проверка совместимости Flow Low-code
Для каждого активного и пригодного для отката Flow:
- экспортируйте исходные данные прежней версией Low-code IDE;
- проверьте их целевым проверяющим модулем и политикой;
- загрузите и выполните путь целевой версией Low-code Runtime;
- сравните входы, выходы, карточку A2A, описание MCP и контрольные примеры;
- зафиксируйте необходимость миграции либо заблокируйте обновление;
- не изменяйте сохранённый источник автоматически при запуске.
Если PlatformRAG или PlatformMemory появляются в новой политике, это отдельное изменение возможностей с собственными контрактами и не может включаться только обновлением версии.
Проверка Agent Registry
До обновления:
- выполните сравнение OpenAPI и машинных схем;
- проверьте применение и понижение версии Alembic на одноразовой базе;
- подтвердите совместимость схемы SpiceDB и читателей/писателей;
- проверьте повторную доставку Redpanda и пересоздание OpenSearch;
- выполните разрешённые, запрещённые, межпространственные запросы и отказ SpiceDB;
- проверьте регистрацию службы Low-code Runtime целевой формы.
Порядок обновления
- Остановите развёртывание новых версий Flow пользователями.
- Создайте резервные копии метаданных и зафиксируйте текущее состояние.
- Выполните все проверки совместимости Flow Low-code.
- Обновите репозиторий до новой версии поставки.
- Запустите
garden validate --env TARGET. - Запустите
garden deploy --env TARGET --yesдля компонентов этого репозитория. - Дождитесь миграции PostgreSQL, схемы SpiceDB, топиков Redpanda и поисковой схемы.
- Дождитесь готовности всех процессов Agent Registry, Low-code IDE и проверочного Low-code Runtime.
- Выполните вход, создание, сохранение, проверку и повторяемый экспорт.
- Воспроизведите общий путь от создания Flow агента до автоматического обнаружения и вызова.
- Разрешите создание новых рабочих версий Flow только после успешной проверки.
Условия немедленной остановки
Остановите обновление, если:
- миграция данных завершилась ошибкой;
- прежний Flow Low-code не проходит целевую проверку;
- карточка или описание агента объявляет отсутствующую возможность;
- Low-code IDE может передать непроверенный или содержащий секрет источник;
- Agent Registry возвращает недоступный объект;
- новый экземпляр Reconciler не получил свежее полное наблюдение;
- поисковая проекция не сходится с метаданными.
Критерии завершения
Обновление завершено только когда:
- образы, настройки, схемы данных и внешние зависимости совместимы;
- активные и откатные Flow Low-code прошли проверку;
- Low-code IDE создаёт повторяемый Flow;
- Low-code Runtime готов и исполняет принятый профиль;
- Agent Registry автоматически обнаруживает его и соблюдает отрицательные проверки доступа;
- сохранены контрольные суммы и очищенные результаты проверки;
- подтверждён применимый путь отката.
Откат
Принцип: Откат возвращает всю систему к заранее проверенной комбинации образов, настроек, схем данных, артефактов агента и внешних зависимостей. Возврат одного образа без проверки совместимости данных и Flow Low-code не считается безопасным.
Исходный файл Flow не исправляется во время отката. Выбирается предыдущая версия с известной контрольной суммой и подтверждённой совместимостью.
Ограничение текущего релиза: Ввиду того, что текущий релиз является первым, процедура отката к предыдущей версии не предусмотрена.
Мониторинг состояния и обслуживание
Ежедневная проверка состояния
Agent Registry
Проверьте:
- работоспособность и готовность API;
- актуальность данных мониторинга Service и EndpointSlice в Kubernetes;
- лидера сервиса Kubernetes Reconciler;
- возраст самой старой неопубликованной записи транзакционной очереди;
- отставание обработчика Redpanda;
- состояние SpiceDB и OpenSearch;
- завершение задания хранения и удаления устаревших данных.
Low-code Runtime
Для каждой поставленной версии проверьте:
- идентификатор образа;
- SHA-256 исходного Flow и манифеста;
- ответ эндпоинта проверки работоспособности процесса;
- ответ эндпоинта проверки готовности Flow;
- соответствие карточки A2A и описания MCP фактическим возможностям агента;
- отсутствие перезапусков, таймаутов и ошибок AI Gateway;
- отсутствие секретов и содержимого запросов в журналах.
Low-code IDE
Проверьте:
- идентификаторы клиентского и серверного образов;
- доступность входа через платформенный SSO;
- запрет доступа для пользователя без нужной роли;
- согласованную версию клиентской и серверной частей;
- доступность хранилища рабочих версий;
- версию политики компонентов и проверяющего модуля;
- отсутствие внешних поставщиков и открытых секретов в экспортируемой схеме;
- передачу Flow на контрактном примере Agent Publisher.
Значение проверок состояния
- Проверка работоспособности сообщает только о живом процессе. Она не должна выполнять дорогой вызов модели.
- Готовность Agent Registry требует исправной БД с метаданными, настройки удостоверений и функционирующего процесса мониторинга развёрнутых в Kubernetes агентов.
- Готовность Low-code Runtime требует успешно загруженной Flow, манифеста, рабочего эндпоинта, карточки и критической конфигурации.
- Доступность клиентской части Low-code IDE не доказывает готовность серверной проверки, хранилища и входа.
- Отказ SpiceDB запрещает защищённые операции. Отказ AI Gateway или OpenSearch отключает поиск, но не обязан останавливать просмотр списка.
Безопасный сбор сведений
После явного выбора контекста и пространства имён допустимы команды чтения:
kubectl -n "$REGISTRY_NAMESPACE" get deploy,pod,svc,endpointslice,job,lease
kubectl -n "$REGISTRY_NAMESPACE" get events --sort-by=.lastTimestamp
kubectl -n "$REGISTRY_NAMESPACE" logs \
deploy/ap-agent-registry-kubernetes-reconciler --all-pods --tail=200
kubectl -n "$REGISTRY_NAMESPACE" logs \
deploy/ap-agent-registry-api --all-pods --tail=200Важно: Не помещайте значение токена, текст карточки, запрос поиска, вектор и внутренний адрес в запрос.
Диагностика Agent Registry
Устаревшие данные мониторинга Kubernetes
Признак: алерт AgentRegistryObservationCoverageStale, потеря готовности Reconciler или исчезновение доступных интерфейсов.
- Проверьте возраст покрытия, ошибки данных мониторинга, ответы
410, ограничение запросов Kubernetes и лидера сервисов Reconciler.
| Возраст покрытия | Поведение |
|---|---|
| ≤ 30 с | Покрытие свежее, ресурсы доступны |
| > 30 с | Покрытие устарело |
| > 300 с ±20 % | Периодический full resync — полное подтверждение наличия/отсутствия |
- Убедитесь, что потоки Service и EndpointSlice свежие для каждого явно сопоставленного пространства имён.
- Проверьте только права
get/list/watchчерез RoleBinding. Чтение Secret, Pod, Deployment и всего кластера не требуется. - При
410 Goneдождитесь полного повторного списка. - При перезапуске лидера сервисов Reconciler новый владелец должен сначала выполнить полную синхронизацию и только потом считать покрытие свежим.
Потеря готовности агента
Проверьте все EndpointSlice, принадлежащие сервису агента: управляющий контроллер, тип адреса, порт и признаки ready, serving, terminating.
При отсутствии доступного EndpointSlice:
- агент не доступен из обычной выдачи для вызова;
- удаляется публичный интерфейс;
- инициируется отзыв разрешений доступа (SpiceDB) и поисковой проекции.
Восстанавливайте исходный агентский сервис или Low-code Runtime. Пересозданный сервис получает новый UID и проходит полную проверку.
Ошибка разрешений SpiceDB
Признак: AgentRegistryPermissionCleanupFailing или ответы authorization_unavailable.
- Считайте затронутый агент недоступным до завершения восстановления.
- Проверьте состояние SpiceDB и код ошибки авторизационного запроса.
- После восстановления дождитесь повторной операции Reconciler.
- Убедитесь, что разрешения владельца и рабочей области удалены либо созданы в соответствии с текущим состоянием.
Откат БД SpiceDB не приведёт к восстановлению.
Отказ поиска
- При отказе AI Gateway поиск возвращает
503. - При отказе OpenSearch поиск возвращает
503. - Просмотр списка и одной записи продолжается, если PostgreSQL и SpiceDB исправны.
- После восстановления создайте новое поколение индекса.
- Переключайте псевдоним только после проверки количества, контрольного набора и догонки потока событий.
- Храните прежнее поколение не менее семи дней для быстрого возврата.
Не редактируйте отдельные документы OpenSearch вручную.
Задержка транзакционной очереди
Признак: AgentRegistryOutboxPublishFailing или рост возраста самой старой неопубликованной записи.
- Проверьте Redpanda, права на топик, срок хранения и владельца блокировки.
- Не меняйте
published_atвручную. - После истечения периода блокировки запись должна стать доступной повторной попытки.
- Повторная доставка допустима: Search Indexer устраняет повторы по идентификатору события и версии агрегата.
- После восстановления убедитесь, что очередь сокращается, а группа потребителя продвигается.
Миграции и восстановление
Задание миграции и проверка при запуске используют транзакционную блокировку PostgreSQL. При ошибке:
- остановите деплой версии;
- сохраните номер Alembic и ошибку базы;
- верните совместимый образ приложения;
- выполняйте понижение версии схемы только после проверки сохранности данных;
- не запускайте разрушительный SQL из интерактивного контейнера.
Цели восстановления: Agent Registry — RTO 60 минут и RPO 5 минут; SpiceDB — RTO 30 минут и RPO 5 минут.
OpenSearch восстанавливается из метаданных и не имеет внутреннего механизма, гарантирующего сохранность.
Диагностика Low-code Runtime
Проверки состояния
| Маршрут | Значение | Не доказывает |
|---|---|---|
/health/live | Процесс работает | Исправность Flow, модели и доступа |
/health/ready | Артефакт, манифест, точка входа и критическая настройка приняты | Качество ответа модели и право конкретного пользователя |
/.well-known/agent-card.json | Карточка A2A выбранной версии | Право вызова; публичный клиент получает маршрут через Agent Registry |
Проверка готовности не должна выполнять тяжёлый запрос к модели. Фактическая готовность AI Gateway подтверждается отдельной сквозной проверкой.
Типичные причины неготовности
| Признак | Проверка | Безопасное действие |
|---|---|---|
| Несовпадение SHA-256 | Сравнить байты файла, путь и ожидаемый SHA-256 | Повторно разместить файл Flow как новую версию |
component_not_allowed | Найти узел и версию политики в результате проверки | Исправить Flow в Low-code IDE; не отключать проверку |
| Несовместимость среды исполнения | Сверить версию lfx и набор совместимости | Заблокировать обновление либо создать совместимый Flow |
advertised_capability_unavailable | Сравнить манифест, карточку и исполняемый путь | Убрать неподдерживаемую возможность и создать новую версию |
| Ошибка AI Gateway | Проверить целевой профиль, срок полномочия, ограничение времени | Исправить настройку платформенной службы; не передавать пользовательский токен |
| Ошибка FileRef | Проверить цель, операцию, срок, размер, тип и SHA-256 | Получить новый FileRef; не передавать прямой URL |
| Превышение нагрузки | Проверить параллельность, очередь и сроки | Вернуть 429, применить ограниченную повторную попытку только для безопасного чтения |
Наблюдаемость
Для диагностики достаточно идентификатора агента и версии, версии Flow, хеш-префикса, traceId, кода ошибки.
Условие успешной эксплуатации
Версия считается исправной, когда готовность агента устойчива, карточка соответствует поведению, A2A и MCP проходят согласованный набор проверок, неверные FileRef и права отклоняются до выполнения, а Agent Registry автоматически обнаруживает рабочую нагрузку развёрнутого агента.
Диагностика Low-code IDE
Предварительные проверки
Перед открытием доступа пользователям зафиксируйте:
- идентификаторы клиентского и серверного образов;
- полный SBOM обоих образов и отчёт чистой сборки;
- версию LangFlow, версию адаптации и совместимую версию схемы данных;
- версию политики компонентов;
- версию проверяющего модуля и JSON Schema Flow и манифеста;
- адрес и конфигурацию платформенного поставщика токенов доступа;
- карту ролей Low-code IDE к рабочим областям;
- доступность базы рабочих версий;
- адрес потребителя контракта Agent Publisher либо контрактный пример для этой поставки.
Вход и доступ
Проверьте четыре состояния:
| Состояние | Ожидаемое поведение |
|---|---|
| Пользователь не вошёл | Перенаправление к платформенному поставщику токенов без показа закрытых схем |
| Токен не действителен | Отказ с понятным сообщением и без создания локального сеанса |
| Пользователь вошёл, но не имеет права | Отказ без раскрытия схем и состава чужой рабочей области |
| Пользователь имеет право | Доступ только к разрешённой рабочей области и операциям роли |
Идентификатор пользователя, рабочая область и роли из формы, URL или неподписанного заголовка не являются источником полномочий.
Политика компонентов
Запрет должен действовать на двух уровнях:
- клиентская палитра не показывает недоступный компонент;
- серверная проверка отклоняет вручную добавленный или изменённый JSON.
| Platform RAG | Платформенный сервис retrieval-augmented generation: реестр коллекций, приём нормализованных документов, гибридный поиск с фильтрацией по правам доступа |
После изменения политики повторно проверьте все активные и пригодные для отката версии Flow. Нельзя автоматически изменять уже зафиксированные исходные данные.
Сохранение
Серверная часть должна:
- сохранять рабочую версию в правильной рабочей области;
- предотвращать перезапись зафиксированной версии;
- формировать устойчивую SHA-256;
- возвращать версию проверяющего модуля и политики;
- отделять предупреждение от блокирующей ошибки;
- не включать секрет в исходные данные и сообщение об ошибке.
Повторный экспорт одной неизменённой версии должен давать те же байты и контрольную сумму.
Первичная диагностика
Клиент открывается, но данные не загружаются. Проверьте совместимость клиентской и серверной версий, состояние API, срок сеанса и права рабочей области.
Сохранение не работает. Проверьте доступность базы, миграцию, ограничение размера и конфликт версии. Сохраните рабочую копию пользователя безопасным способом; не записывайте JSON в произвольную таблицу вручную.
Передача недоступна. Сохраните проверенную версию и контрольные суммы. Не выполняйте прямую публикацию. Для 2026.3.3 передайте артефакт оператору по утверждённой ручной процедуре и зафиксируйте отсутствие Agent Publisher как ограничение.
Первичная диагностика происшествия
- Зафиксируйте среду, контекст, пространство имён, версию выпуска и время.
- Определите затронутый пользовательский шаг: вход, редактирование, проверка, запуск среды исполнения, обнаружение, поиск или вызов.
- Зафиксируйте идентификаторы образов, версии схемы и манифеста без их чувствительного содержимого.
- Проверьте компонент-владелец, затем его непосредственные зависимости.
- Сохраните события, показатели и очищенные журналы с
traceId. - Убедитесь, что отказ доступа, устаревшие данные мониторинга или неверный маршрут не обходятся временной настройкой.
- Остановите развёртывание версии, если нарушены граница доступа, контрольная сумма, регистрационный контракт или соответствие заявленных возможностей.
- Откатывайте только заранее проверенную совместимую комбинацию образов, конфигурации, схем данных и внешних зависимостей.
Данные, которые нельзя сохранять
Не включайте в журналы, трассировки и материалы проверки:
- исходный пользовательский токен и короткоживущие полномочия;
- ключи, пароли и значения Vault;
- текст пользовательского запроса и ответа модели;
- содержимое файлов и подписанный FileRef;
- полный экспорт схемы, если в нём могут быть закрытые данные;
- вектор запроса и закрытые внутренние адреса;
- карточки и описания протокола без очистки чувствительных полей.
Для связи событий используйте безопасные идентификаторы агента, версии, Flow, хеш-префикс, traceId и время.
Безопасное восстановление
- Исправляйте исходную рабочую нагрузку или конфигурацию и дожидайтесь согласования состояния.
- После ответа Kubernetes
410 Goneразрешите Reconciler выполнить полную повторную синхронизацию. - Не помечайте запись транзакционной очереди опубликованной вручную.
- Повреждённый поисковый индекс заменяйте новым поколением и переключайте псевдоним только после проверки количества и контрольного набора.
- При несовпадении артефакта Low-code Runtime создавайте новую версию; не исправляйте файл внутри контейнера.
- При ошибке Low-code IDE сохраняйте рабочую версию и результат проверки; не передавайте непроверенный JSON оператору.
- При ошибке миграции остановите развёртывание и следуйте плану миграции.
Agent Registry — каталог агентов с REST API, поиском и авторизацией. Он автоматически обнаруживает рабочие нагрузки в Kubernetes через Reconciler (по Service и EndpointSlice), загружает карточки агентов, проверяет соответствие заявленных возможностей, управляет разрешениями через SpiceDB и обеспечивает транзакционную доставку событий через Redpanda. Поиск проекцируется в OpenSearch. Agent Registry не создаёт записи вручную — регистрация происходит автоматически.
Platform Memory — единый управляемый слой памяти платформы. Агент получает персистентную память: search перед ответом, add после ответа. Извлечение фактов, дедупликация, гибридный поиск, изоляция по скоупам и история изменений выполняются сервисом, а не каждым агентом отдельно. Память не заменяет RAG. Platform RAG отвечает за корпус документов; Platform Memory — за знания о пользователе, агенте и сессии. Сборка промпта комбинирует оба источника. Публичный контракт совместим с mem0 (add / search / get_all / history / delete). Сервис использует PostgreSQL (event store и история), RabbitMQ (уведомления о заданиях add), OpenSearch (индекс фактов: kNN + BM25) и AI Gateway (эмбеддинг и LLM-извлечение). Порт API — 8091. Helm-чарт устанавливает только прикладную нагрузку api; worker запускается отдельно. Зависимости чартом не устанавливаются.
| Low-code Runtime | Среда выполнения агентов с низкой кодовой базой; исполняет одну версию одного агента | Agent Registry: PostgreSQL хранит метаданные. Redpanda, SpiceDB и OpenSearch являются производными или внешними проекциями и восстанавливаются из метаданных и событий. | Low-code IDE | Отключено | Поставляется отдельным контуром |
Platform RAG
Platform RAG — платформенный сервис уровня COMMON, предоставляющий управляемое извлечение знаний (retrieval-augmented generation): реестр коллекций, приём нормализованных документов, гибридный поиск с обязательной фильтрацией по правам доступа и выдачу фрагментов с цитатами.
Архитектура
Сервис состоит из двух прикладных нагрузок без локального состояния: API и воркер ingest. Всё состояние хранится во внешних сервисах данных. Модели вызываются только через AI Gateway. Авторизация коллекций — SpiceDB; видимость чанков — ACL документа, выведенный из act-цепочки вызывающего.
| Компонент | Назначение | Примечание |
|---|---|---|
platform-rag-api | HTTP API: коллекции, приём документов, статус заданий, поиск, /health | Stateless, горизонтально масштабируется. Порт 8090 |
platform-rag-worker | Обработка ingest: staging → chunk → embed → index | Масштабируется независимо, в т.ч. через KEDA |
| PostgreSQL | Реестр коллекций и источник истины по заданиям ingest | Схема platform_rag |
| RabbitMQ | Уведомления о заданиях (exchange: rag.ingest, quorum-очередь rag.ingest.jobs, DLX/DLQ) | Не хранит состояние задания |
| OpenSearch | Индекс чанков: embedding (kNN), текст BM25, tenant_id, acl, version | Алиас вида rag-kb-{env} |
| S3 / MinIO | Staging канонического JSON на время задания (payload_uri) | В локальном Compose допускается s3.dry_run: true |
| AI Gateway | Эмбеддинг и реранк | Идентификаторы моделей задаются профилями, не хардкодом в коде |
| SpiceDB | Права на коллекцию: owner / reader / writer | Fail-closed при недоступности |
| Keycloak | Проверка JWT при auth.enabled: true | В dev идентичность задаётся заголовками |
Helm-чарт helm/platform-rag создаёт Deployment *-api, Deployment *-worker, Service (ClusterIP, порт 8090), ConfigMap, ServiceAccount и опционально Ingress и KEDA ScaledObject. Зависимости чартом не устанавливаются.
Потоки данных
Приём документа. Клиент вызывает POST /v1/documents:submit. API проверяет право записи в коллекцию, регистрирует задание в PostgreSQL (PENDING), сохраняет канонический JSON в S3 и публикует уведомление в RabbitMQ. Воркер захватывает задание (RUNNING), выполняет чанкинг, эмбеддинг через AI Gateway и bulk-индексацию в OpenSearch, затем переводит задание в DONE или FAILED. Повторная отправка с тем же (tenant, collection, doc_id, content_hash, idempotency_key) возвращает DEDUPLICATED.
Поиск. Клиент вызывает POST /v1/query. API авторизует доступ к коллекции (SEC prior), строит эмбеддинг запроса через AI Gateway, выполняет гибридный поиск (kNN + BM25) со слиянием RRF, обязательно фильтрует выдачу по tenant_id и ACL вызывающего (SEC posterior) и возвращает цитаты (doc_id, chunk_id, фрагмент, оценка).
Идемпотентность и надёжность очереди. Источник истины — PostgreSQL. RabbitMQ доставляет уведомление; при потере сообщения фоновая сверка выбирает зависшие PENDING и публикует повторно. Воркеры идемпотентны.
Минимальные ресурсы
| Ресурс | Минимум (пилот) | Рекомендуется (пром) |
|---|---|---|
| Процессор (API + worker) | 2 ядра | 4–8 ядер |
| Оперативная память | 4 ГБ | 8–16 ГБ |
| OpenSearch | 2 ГБ heap | отдельный кластер, реплики индекса |
| PostgreSQL | 1 ГБ | внешний отказоустойчивый кластер |
| Диск | 20 ГБ (индекс + WAL) | по объёму коллекций |
| ОС | Linux x86-64, Docker Compose v2 или Kubernetes 1.27+ | — |
Запросы чарта по умолчанию: API — 100m CPU / 256Mi RAM (лимит 1Gi); worker — 250m CPU / 512Mi RAM (лимит 2Gi).
Развёртывание
Предварительные требования
- Linux x86-64; Docker Engine и Docker Compose v2 или кластер Kubernetes с Helm 3.
- Доступ к реестру образов либо возможность собрать образ из исходного кода.
- Для полного цикла ingest/query: доступные PostgreSQL 16, RabbitMQ 3, OpenSearch 2.x, объектное хранилище S3-совместимое, AI Gateway, SpiceDB.
Проверка Docker:
docker --version
docker compose versionПроверка Kubernetes / Helm:
kubectl version --client
helm versionПолучение дистрибутива
Исходный код и чарт поставляются репозиторием сервиса. Сборка образа:
docker build -t platform-rag:<tag> .В контуре заказчика используется согласованный реестр. После сборки образ публикуется в реестр, доступный узлам кластера.
Настройка конфигурации
Образец — config/config_template.yaml. Рабочий файл — config/config.yaml (путь задаётся RAG_CONFIG). Секреты (DSN, пароли, ключи) не хранятся в Git.
Обязательные группы параметров до запуска:
| Группа | Назначение | Действие |
|---|---|---|
postgres.dsn | Подключение к БД (postgresql+asyncpg://…) | Задать устойчивый пароль; схема platform_rag |
rabbitmq.* | Брокер ingest | Хост, пользователь, пароль, exchange/queue/dlx/dlq |
opensearch.hosts | Индекс чанков | URL кластера; index_alias вида rag-kb-<env> |
s3.* | Staging документов | Endpoint, bucket, ключи; для пилота без MinIO — dry_run: true |
ai_gateway.url / api_key | Эмбеддинг и реранк | URL шлюза; ключ только в Secret |
embedding_profiles | Профиль модели и размерность | Закрепляется за коллекцией; смена — через переиндексацию |
spicedb.* | Авторизация коллекций | В проде enabled: true, TLS, не insecure |
auth.* | Проверка JWT | В проде enabled: true и параметры Keycloak |
Переопределение из окружения (примеры):
export RAG_CONFIG=/app/config/config.yaml
export RAG__POSTGRES__DSN='postgresql+asyncpg://[REDACTED]@postgres:5432/platform_rag'
export RAG__RABBITMQ__PASSWORD='[REDACTED]'
export RAG__S3__ACCESS_KEY_ID='<key>'
export RAG__S3__SECRET_ACCESS_KEY='<secret>'
export RAG__OPENSEARCH__USERNAME='<user>'
export RAG__OPENSEARCH__PASSWORD='[REDACTED]'
export RAG__AI_GATEWAY__API_KEY='[REDACTED]'
export RAG__SPICEDB__ENABLED=true
export RAG__AUTH__ENABLED=trueПри app.create_schema_on_startup: true API при старте создаёт схему PostgreSQL. Для промышленного контура порядок миграций согласовывается отдельно; откат Helm не откатывает схему БД.
Внимание. Профиль эмбеддинга (
model+dimension) закрепляется за коллекцией. Смена профиля без версионируемой переиндексации сделает векторный поиск несовместимым.
Развёртывание в Docker Compose
Файл docker-compose.yml поднимает прикладные сервисы и зависимости: PostgreSQL, RabbitMQ, OpenSearch, SpiceDB (с отдельной БД и миграцией схемы). MinIO и AI Gateway в Compose не входят: для пилота без объектного хранилища используется s3.dry_run: true.
Публикуемые порты Compose:
| Сервис | Порт на хосте | Назначение |
|---|---|---|
| API | 8095 → 8090 | HTTP API |
| PostgreSQL | 5433 → 5432 | БД сервиса |
| RabbitMQ | 5672, 15672 | AMQP и management UI |
| OpenSearch | 9201 → 9200 | Поиск / индекс |
| SpiceDB | 50051, 8443 | gRPC / HTTP |
Вариант A. Инфраструктура в Docker, приложение на хосте:
docker compose up -d postgres rabbitmq opensearch spicedb-postgres
docker compose up spicedb-migrate
docker compose up -d spicedb
# из корня репозитория, Python 3.11+
pip install -e .
export RAG_CONFIG=config/config.yaml
platform-rag-api
# во втором терминале:
platform-rag-workerПроверка:
curl -fsS http://127.0.0.1:8090/healthОжидается "status": "ok" по компонентам postgres, rabbitmq, s3, opensearch. При s3.dry_run: true проверка S3 считается успешной без реального бакета.
Вариант B. Полный стек в Compose:
docker compose up -d --build
docker compose ps
docker compose logs -f api worker
curl -fsS http://127.0.0.1:8095/healthОстановка:
docker compose down
# с удалением томов данных:
docker compose down -vРазвёртывание в Kubernetes (Helm)
Чарт: helm/platform-rag. Канонические команды также приведены в helm/platform-rag/README.md и docs/helm-deployment.md.
Подготовка
- Собрать и опубликовать образ.
- Проверить сетевую доступность PostgreSQL, RabbitMQ, S3, OpenSearch, AI Gateway и SpiceDB из целевого пространства имён.
- Создать Secret с учётными данными (не помещать их в values):
kubectl -n <namespace> create secret generic platform-rag-secrets \
--from-literal=postgres-dsn='postgresql+asyncpg://[REDACTED]@host:5432/platform_rag' \
--from-literal=postgres-dsn-sync='postgresql://[REDACTED]@host:5432/platform_rag' \
--from-literal=rabbitmq-password='[REDACTED]' \
--from-literal=s3-access-key-id='<access-key>' \
--from-literal=s3-secret-access-key='<secret-key>' \
--from-literal=opensearch-username='<username>' \
--from-literal=opensearch-password='[REDACTED]' \
--from-literal=ai-gateway-api-key='[REDACTED]'- Подготовить values окружения (образцы:
helm/platform-rag/values.yaml,values-dev.yaml,values-prod.example.yaml).
Установка
helm lint helm/platform-rag
helm template platform-rag helm/platform-rag -n <namespace> -f values-<env>.yaml
helm upgrade --install platform-rag helm/platform-rag \
-n <namespace> --create-namespace \
-f values-<env>.yaml \
--atomic --wait --timeout 10m
kubectl -n <namespace> rollout status deployment/platform-rag-api --timeout=5m
kubectl -n <namespace> rollout status deployment/platform-rag-worker --timeout=5m
kubectl -n <namespace> get pods,svcПроверка с порта кластера:
kubectl -n <namespace> port-forward svc/platform-rag 8090:8090
curl -fsS http://127.0.0.1:8090/healthПри включённом Ingress (ingress.enabled: true) задайте ingress.hosts[].host и при необходимости TLS. Снаружи публикуется только API; воркер наружу не выставляется.
Особенности промышленного контура
- Образы запускаются от UID/GID
10001,runAsNonRoot, без привилегий, read-only root filesystem,/tmp—emptyDir. - Конфиг монтируется ConfigMap по пути
/app/config/config.yaml. - Probes API: startup/liveness/readiness на
GET /health. terminationGracePeriodSeconds: 60— чтобы воркер успел завершить текущее задание.- При полной замене блока
configсохраните секцииapi,embedding_profiles,rerank_profiles,chunking,paths,logиз значений чарта, если не меняете их намеренно.
Автомасштабирование воркеров (KEDA)
Источник истины backlog — SQL, не глубина очереди RabbitMQ:
SELECT COUNT(*) FROM platform_rag.ingest_job WHERE status = 'PENDING'Включение в values (см. values-prod.example.yaml):
worker:
autoscaling:
enabled: true
minReplicas: 1
maxReplicas: 10
targetQueryValue: "4"
authentication:
existingSecret: [REDACTED]
connectionKey: postgres-dsn-syncТребования: KEDA в кластере; ключ Secret с libpq-строкой postgresql://… (SQLAlchemy postgresql+asyncpg://… скейлер не принимает). При включённом autoscaling поле replicas у Deployment воркера не задаётся — число реплик принадлежит KEDA.
Подключение моделей
Сервис не содержит собственной языковой модели. Все вызовы эмбеддинга и реранка идут через AI Gateway. Ключи инференса хранятся у шлюза; в конфигурации RAG задаётся только URL шлюза и ключ доступа к нему.
Профили задаются в конфигурации:
embedding_profiles:
text-default-v1:
profile_id: text-default-v1
model: bge-m3
dimension: 1024
normalize: true
rerank_profiles:
rerank-default-v1:
profile_id: rerank-default-v1
model: bge-m3
candidates: 20| Назначение | Где задаётся | Примечание |
|---|---|---|
| Эмбеддинг | embedding_profile_id коллекции | Изменение требует новой версии индекса |
| Реранк | retrieval_defaults.rerank_profile_id и флаг rerank в запросе | Только из числа одобренных профилей |
| Размерность вектора | embedding_profiles.*.dimension | Должна совпадать с mapping OpenSearch (knn_vector) |
Для закрытого контура используется шлюз в контуре заказчика. Передача содержимого документов во внешние сетевые сервисы без правовых оснований недопустима.
ai_gateway.dry_run: true возвращает нулевые векторы фиксированной размерности — только для проверки конвейера без модели. Для приёмки качества поиска dry-run не используется.
Авторизация и доступ
Две плоскости идентичности
Каждый вызов несёт тенант и идентичность вызывающего. В режиме разработки (auth.enabled: false) идентичность передаётся заголовками. В промышленном режиме (auth.enabled: true) обязателен Authorization: Bearer [REDACTED].
| Заголовок | Назначение |
|---|---|
X-Tenant-Id | Тенант (обязателен всегда) |
X-User-Id | Пользователь (dev; в проде — из JWT sub / user_id) |
X-Groups | Группы через запятую (dev; в проде — claim groups) |
X-Principals | Дополнительные principals (dev) |
X-Agent-Id | Идентификатор агента (dev; в проде — claim agent_id) |
Authorization | Bearer JWT при auth.enabled: true |
X-Trace-Id | Корреляция (поиск прокидывает в meta.trace_id) |
Фильтр выдачи строится по правам пользователя, а не агента: один и тот же агент для разных пользователей возвращает разный набор чанков.
SpiceDB
Модель прав:
collection.owner— пользователь-владелец;collection.reader— пользователь, группа или агент (чтение / поиск);collection.writer— интеграционный сервис (запись /submit_documents);document.view— членviewer_groupилиparent->read.
При недоступности SpiceDB сервис отвечает 503 authz_unavailable (fail-closed), а не «пропускает» запрос.
ACL документа
В приватной коллекции пустой ACL при upsert недопустим: документ отклоняется (empty_acl_policy: reject) либо индексируется с самой строгой видимостью (strictest). Политика задаётся на коллекции и значением app.empty_acl_policy.
Отзыв прав действует на следующем запросе: ACL перепроверяются в момент retrieval, переиндексация для отзыва не требуется.
Безопасность
Секреты
В Secret / защищённом хранилище: DSN PostgreSQL, пароль RabbitMQ, ключи S3, учётные данные OpenSearch, ключ AI Gateway, preshared key SpiceDB. Файл values и ConfigMap не содержат паролей.
Права на локальный config.yaml с секретами:
chmod 600 config/config.yamlСетевые ограничения
Наружу публикуется только API (ClusterIP + Ingress, порт 8090 / TLS). Воркер, PostgreSQL, RabbitMQ, OpenSearch, SpiceDB во внешнюю сеть не публикуются.
| Источник | Порт | Протокол | Назначение |
|---|---|---|---|
| Потребители (SDK, low-code, интеграции) | 8090 / 443 | HTTP/HTTPS | RAG API |
| API / worker | 5432 | PostgreSQL | Реестр и job store |
| API / worker | 5672 | AMQP | Очередь ingest |
| API / worker | 9200 | HTTPS | OpenSearch |
| API / worker | 50051 | gRPC | SpiceDB |
| Worker / API | 443 | HTTPS | AI Gateway, S3 |
Хранение данных
Документы и чанки хранятся в контуре: PostgreSQL (метаданные, jobs), OpenSearch (текст и векторы), S3 (staging). Каждая операция ingest и query подлежит аудиту (минимум: trace_id, операция, идентичность обеих плоскостей, тенант, коллекция).
Резервное копирование
Объекты копирования: PostgreSQL (реестр и job store), индексы OpenSearch, при необходимости бакет staging, файл/Secret конфигурации. RabbitMQ некритичен как SoT.
Логическая выгрузка БД (Compose):
docker compose exec -T postgres \
pg_dump -U postgres platform_rag > platform_rag_db_$(date +%F).sqlВ Kubernetes:
kubectl -n <namespace> exec -T <под_postgresql> -- \
pg_dump -U <user> platform_rag > platform_rag_db_$(date +%F).sqlСнимки OpenSearch выполняются штатными средствами кластера (snapshot repository). Копии хранятся отдельно от контура приложения; периодически проверяется восстановление.
Восстановление
- Развернуть ту же версию сервиса с прежними секретами и профилями эмбеддинга.
- Восстановить PostgreSQL (схема
platform_rag). - Восстановить снимки OpenSearch (алиас
rag-kb-<env>). - Запустить API и worker; проверить
/health, список коллекций и контрольныйquery.
Обновление сервиса
Перед обновлением — резервное копирование и окно обслуживания.
Docker Compose
docker compose down
# обновить код / тег образа
docker compose build
docker compose up -d
docker compose logs -f api workerСверить config_template.yaml с рабочим конфигом на предмет новых параметров.
Kubernetes (Helm)
helm upgrade --install platform-rag helm/platform-rag \
-n <namespace> \
-f values-<env>.yaml \
--atomic --wait --timeout 10mСхема базы данных
При app.create_schema_on_startup: true API создаёт/догоняет объекты схемы при старте. Эксплуатация начинается после успешного /health и отсутствия ошибок создания схемы в журнале API.
Откат Helm не отменяет изменения схемы и данных внешних хранилищ.
Откат
helm -n <namespace> history platform-rag
helm -n <namespace> rollback platform-rag <REVISION> --wait --timeout 10m
kubectl -n <namespace> rollout status deployment/platform-rag-api --timeout=5m
kubectl -n <namespace> rollout status deployment/platform-rag-worker --timeout=5mПри несовместимых миграциях откат версии выполняется вместе с восстановлением БД из копии, снятой до обновления.
Мониторинг
Состояние сервисов
Docker Compose
docker compose ps
docker compose logs -f api
docker compose logs -f worker
curl -fsS http://127.0.0.1:8095/healthKubernetes
kubectl -n <namespace> get pods -l app.kubernetes.io/instance=platform-rag
kubectl -n <namespace> logs deploy/platform-rag-api --tail=200
kubectl -n <namespace> logs deploy/platform-rag-worker --tail=200
kubectl -n <namespace> top podsGET /health возвращает status: ok | degraded и статусы postgres, rabbitmq, s3, opensearch. Probes Kubernetes используют этот путь.
Дополнительно контролируются: число PENDING/FAILED в ingest_job, глубина DLQ rag.ingest.dlq, латентность query, ошибки AI Gateway.
Журналы
Уровень задаётся log.level (по умолчанию INFO). Воркер пишет о старте listener, захвате job, ошибках эмбеддинга и индексации. Корреляция — trace_id.
Типовые нарушения
| Признак | Источник | Вероятная причина и действие |
|---|---|---|
/health → degraded | Тело ответа details | Недоступен Postgres, RabbitMQ, S3 или OpenSearch |
401 Missing X-Tenant-Id | Журнал API | Нет заголовка тенанта |
401 Missing bearer token | Журнал API | Включён auth.enabled, нет JWT |
403 на коллекции | SpiceDB | Нет read/write/owner |
503 authz_unavailable | SpiceDB | Шлюз авторизации недоступен — не «обходить» |
Submit 202, job завис в PENDING | Worker, RabbitMQ | Воркер не запущен; нет потребителя; сбой публикации |
Job FAILED | Журнал worker, поле error | Ошибка AI Gateway, OpenSearch, S3; неверный профиль |
| Query пустой при наличии документов | ACL, группы | Вызывающий не в acl.groups; неверный тенант |
| Индексация медленная | KEDA, PENDING count | Нехватка воркеров; лимит AI Gateway |
Производительность и масштабирование
Воркеры ingest
Основной потребитель ресурсов при загрузке знаний. Число реплик — worker.replicaCount или KEDA по PENDING (целевое значение targetQueryValue, по умолчанию 4 задания на реплику). Параллелизм внутри процесса — app.worker_concurrency (по умолчанию 4). Prefetch RabbitMQ — rabbitmq.prefetch (16).
API
Stateless: увеличивайте api.replicaCount. Пул БД — postgres.pool_size. Эмбеддинг запроса на каждый query идёт в AI Gateway — фактический предел латентности часто определяется шлюзом, а не API.
OpenSearch
Индексу выделяются CPU/RAM; mapping knn_vector требователен к памяти. Смена размерности эмбеддинга требует нового шаблона и переиндексации.
Аварийные ситуации
Недоступность сервиса
- Проверить
/healthи Ingress/Service. - По
detailsопределить отказавший компонент (БД, очередь, S3, OpenSearch). - Проверить поды API и worker, события Kubernetes, журналы.
- Перезапуск:
# Compose
docker compose restart api worker
# Kubernetes
kubectl -n <namespace> rollout restart deploy/platform-rag-api
kubectl -n <namespace> rollout restart deploy/platform-rag-worker- При переполнении диска — очистка журналов/образов, расширение PVC OpenSearch/PostgreSQL.
- При повреждении данных — восстановление из копии.
- Зафиксировать время, признаки,
trace_id, выдержки журналов, выполненные действия.
Эскалация
| Категория | Признаки | Ответственный |
|---|---|---|
| Функциональное | Некорректная выдача, ACL, качество поиска | Владелец знаний / функциональная команда |
| Инфраструктурное | Поды, сеть, диски, Helm, зависимости | Администратор контура |
| Платформенное | Дефект API/worker, контракт, SpiceDB-схема | Команда Platform RAG |
Перед эскалацией: версия образа/чарта, описание, затронутые коллекции, trace_id, журналы, время, уже выполненные действия.
Platform Memory
Назначение и область применения
Platform Memory — единый управляемый слой памяти платформы. Агент получает персистентную память: search перед ответом, add после ответа. Извлечение фактов, дедупликация, гибридный поиск, изоляция по скоупам и история изменений выполняются сервисом, а не каждым агентом отдельно.
Память не заменяет RAG. Platform RAG отвечает за корпус документов; Platform Memory — за знания о пользователе, агенте и сессии. Сборка промпта комбинирует оба источника.
Публичный контракт совместим с mem0 (add / search / get_all / history / delete). Пути платформы — /v1/*. Платформенные отличия: идентичность вызывающего не берётся из тела запроса, запись асинхронна, инференс и эмбеддинг идут только через AI Gateway.
Архитектура сервиса
Сервис состоит из двух прикладных нагрузок без локального состояния: API (синхронное чтение и приём записи) и воркер извлечения (асинхронный write-path). Состояние хранится во внешних сервисах данных. Модели вызываются только через AI Gateway.
| Компонент | Назначение | Примечание |
|---|---|---|
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 |
Потоки данных
Запись (POST /v1/memories). Клиент передаёт messages и минимум один скоуп (agent_id или run_id). Идентичность (workspace_id, user_id) берётся из заголовков, не из тела. API создаёт событие PENDING в PostgreSQL, публикует уведомление в RabbitMQ и сразу отвечает 202 с event_id. Если публикация в очередь не удалась, событие помечается FAILED, клиент получает 503 queue_unavailable.
Воркер захватывает событие (RUNNING), вызывает Flow 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.
Минимальные ресурсы
Значения ориентировочные и уточняются по нагрузке. Для пилотного стенда (проверка 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+ | — |
Языковые модели и эмбеддинги размещаются за AI Gateway, вне сервиса. Требования к GPU определяются выбранной моделью, а не Platform Memory.
Установка и развёртывание
Основной способ пилотных и локальных стендов — Docker Compose. Для промышленных сред — Kubernetes + Helm.
Предварительные требования
- Linux x86-64.
- Docker Engine и Docker Compose версии 2 или кластер Kubernetes с Helm 3.
- Доступ к реестру образов либо возможность собрать образ из исходного кода.
- Для полного цикла add/search: доступные PostgreSQL 16, RabbitMQ 3, OpenSearch 2.x, AI Gateway.
Получение дистрибутива
Сборка образа:
docker build -t platform-memory:<tag> .Образ запускается от UID/GID 10001 (non-root), корневая ФС в Kubernetes — read-only. В контуре заказчика используется согласованный реестр. После сборки образ публикуется в реестр, доступный узлам кластера.
Настройка конфигурации
Образец — config/config_template.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://[REDACTED]@postgres:5432/platform_memory'
export MEMORY__RABBITMQ__HOST=rabbitmq
export MEMORY__RABBITMQ__PASSWORD='[REDACTED]'
export MEMORY__OPENSEARCH__USERNAME='<user>'
export MEMORY__OPENSEARCH__PASSWORD='[REDACTED]'
export MEMORY__AI_GATEWAY__URL='https://<ai-gateway>/v1'
export MEMORY__AI_GATEWAY__API_KEY='[REDACTED]'При app.create_schema_on_startup: true API при старте создаёт схему PostgreSQL. Для промышленного контура порядок миграций согласовывается отдельно; откат Helm не откатывает схему БД.
Внимание. Размерность эмбеддинга (embedding.dimension и opensearch.embedding_dimension) закрепляется за индексом. Смена модели/размерности без переиндексации сделает векторный поиск несовместимым.
Развёртывание в Docker Compose
Файл docker-compose.yml поднимает API, worker и зависимости: PostgreSQL, RabbitMQ, OpenSearch. AI Gateway в Compose не входит.
Публикуемые порты Compose:
| Сервис | Порт на хосте | Назначение |
|---|---|---|
| API | 8093 → 8091 | HTTP API |
| PostgreSQL | 5435 → 5432 | БД сервиса |
| RabbitMQ AMQP | 5674 → 5672 | Очередь add |
| RabbitMQ management | 15674 → 15672 | UI брокера |
| OpenSearch | 9202 → 9200 | Поиск / индекс |
Проверка:
curl -fsS http://127.0.0.1:8091/healthОжидается "status": "ok" по компонентам postgres, opensearch, rabbitmq.
Развёртывание в Kubernetes (Helm)
Чарт: helm/platform-memory.
Подготовка
- Собрать и опубликовать образ.
- Проверить сетевую доступность PostgreSQL, RabbitMQ, OpenSearch и AI Gateway из целевого пространства имён.
- Создать Secret с учётными данными:
kubectl -n <namespace> create secret generic platform-memory-secrets \
--from-literal=postgres-dsn='postgresql+asyncpg://[REDACTED]@host:5432/platform_memory' \
--from-literal=opensearch-username='<username>' \
--from-literal=opensearch-password='[REDACTED]' \
--from-literal=ai-gateway-api-key='[REDACTED]'- Подготовить values окружения (образцы:
values.yaml,values-dev.yaml,values-prod.example.yaml).
Секция 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> port-forward svc/platform-memory 8091:8091
curl -fsS http://127.0.0.1:8091/healthВоркер в Kubernetes
Без 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.
Подключение моделей
Сервис не содержит собственной языковой модели. Все вызовы эмбеддинга и LLM-извлечения идут через AI Gateway. Для закрытого контура используется шлюз в контуре заказчика. Передача фактов о пользователях во внешние сетевые сервисы без правовых оснований недопустима.
infer: false позволяет записать готовый факт без вызова LLM (миграция, системные факты, явное «запомни это») — дешевле и предсказуемее для нагрузочных проверок записи.
Доступ и изоляция памяти
Идентичность вызывающего
На текущем релизе идентичность передаётся заголовками. Поля workspace_id / user_id в теле запроса не доверяются.
| Заголовок | Назначение |
|---|---|
X-Workspace-Id | Рабочая область (обязателен) |
X-User-Id | Пользователь (обязателен; скоуп user_id для фактов) |
Без заголовков API отвечает 422. Целевой контракт (JWT платформы + SpiceDB check на memory_collection, fail-closed) описан в PRD и в текущем API не включён.
Скоупы
Факты изолируются по комбинации workspace, user_id, agent_id, run_id. Для add и list обязателен минимум один из agent_id / run_id. Поиск требует filters со скоупом. Удаление по фильтру не позволяет указать чужой user_id (403 Wrong user ID).
Право на забвение
DELETE /v1/memories с фильтром удаляет релевантные факты в OpenSearch и пишет события DELETE в историю. В ответе — deleted_count и confirmation_id для журнала операций.
Безопасность
Секреты
В Secret / защищённом хранилище: DSN PostgreSQL, пароль RabbitMQ, учётные данные OpenSearch, ключ AI Gateway. Файл values и ConfigMap не содержат паролей.
Права на локальный конфиг с секретами:
chmod 600 config/config.yamlКлючи выдаются по принципу наименьших полномочий; при компрометации отзываются и перевыпускаются.
Сетевые ограничения
Наружу публикуется только 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) на промышленных контурах наружу не публикуется.
Хранение данных
Факты хранятся в контуре: PostgreSQL (события, история), OpenSearch (текст и векторы). Персональные факты в долговременной памяти обрабатываются в контуре заказчика. Передача во внешние LLM без шлюза и правовых оснований недопустима.
Резервное копирование
Объекты копирования: 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>.
Восстановление
- Развернуть ту же версию сервиса с прежними секретами и той же размерностью эмбеддинга.
- Восстановить PostgreSQL (схема
platform_memory). - Восстановить снимки OpenSearch (алиас
mem-facts-<env>). - Запустить API и worker; проверить
/health, контрольныйadd/search.
Обновление сервиса
Перед обновлением — резервное копирование (п. 5.4) и окно обслуживания.
Docker Compose
docker compose down
# обновить код / тег образа
docker compose build
docker compose up -d
docker compose logs -f api workerСверить config_template.yaml с рабочим конфигом на предмет новых параметров.
Kubernetes (Helm)
helm upgrade --install platform-memory helm/platform-memory \
-n <namespace> \
-f values-<env>.yaml \
--atomic --wait --timeout 10mОткат
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При несовместимых миграциях откат версии выполняется вместе с восстановлением БД и индекса из копии, снятой до обновления.
Мониторинг и журналы
Состояние сервисов
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).
Журналы
Уровень задаётся log.level (по умолчанию INFO). API пишет о приёме add (event_id, infer) и ошибках публикации в очередь. Воркер пишет о старте listener, захвате события (RUNNING), ошибках mem0/AI Gateway/индексации.
Типовые нарушения
| Признак | Источник | Вероятная причина и действие |
|---|---|---|
/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, Flow mem0 |
| Search пустой при наличии фактов | Скоупы, workspace | Другой agent_id/user_id/X-Workspace-Id; событие ещё не SUCCEEDED |
| Search медленный | AI Gateway, OpenSearch | Эмбеддинг запроса; нехватка heap у индекса |
403 на DELETE | user_id в query | Попытка удалить память другого пользователя |
Производительность и масштабирование
Воркеры извлечения
Основной потребитель ресурсов при 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 (уточняется при внедрении). API при росте search масштабируется увеличением replicaCount.
API
Stateless: увеличивайте число реплик Deployment. Пул БД — postgres.pool_size. Эмбеддинг запроса на каждый search идёт в AI Gateway — фактический предел латентности часто определяется шлюзом, а не API.
Ограничения
| Параметр | Назначение |
|---|---|
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 |
Аварийные ситуации
Недоступность сервиса
- Проверить
/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, выдержки журналов, выполненные действия.
Эскалация
| Категория | Признаки | Ответственный |
|---|---|---|
| Функциональное | Некорректные факты, скоупы, качество поиска | Владелец агентов / функциональная команда |
| Инфраструктурное | Поды, сеть, диски, Helm, зависимости | Администратор контура |
| Платформенное | Дефект API/worker, контракт mem0, Flow извлечения | Команда Platform Memory |
Перед эскалацией: версия образа/чарта, описание, затронутые workspace/agent_id, event_id, журналы, время, уже выполненные действия.
Примеры запросов для проверки системы
Базовый 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.
Живучесть
curl -fsS "$BASE/health"Ожидается HTTP 200 и JSON вида:
{
"status": "ok",
"components": {
"postgres": "ok",
"opensearch": "ok",
"rabbitmq": "ok"
},
"details": {}
}Запись памяти (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 из ответа>'
curl -sS "$BASE/v1/events/$EVENT_ID" \
-H "X-Workspace-Id: $WS" \
-H "X-User-Id: $USER"Ожидается 200. Цепочка: PENDING → SUCCEEDED | FAILED.
Список фактов
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).
Поиск
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 с фактами, score и tokens_returned.
История записи
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.
Удаление по скоупу (право на забвение)
curl -sS -X DELETE "$BASE/v1/memories?agent_id=$AGENT" \
-H "X-Workspace-Id: $WS" \
-H "X-User-Id: $USER"Ожидается 200: deleted_count и confirmation_id.
Попытка ?user_id=other-user при заголовке X-User-Id: $USER — 403.
Негативные проверки
| Проверка | Запрос | Ожидание |
|---|---|---|
| Нет 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 |
Ключевые параметры конфигурации
| Параметр | Назначение |
|---|---|
MEMORY_CONFIG | Путь к YAML (в контейнере /app/config/config.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) |
embedding.model / dimension | Модель эмбеддинга у AI Gateway |
ai_gateway.url / api_key / llm_model | Шлюз моделей |
ai_gateway.timeout / batch_size / dry_run | 120 / 32 / false |
log.level | Подробность журналов |
replicaCount | Реплики API в чарте |