# Акт сдачи-приёмки работ № 1

Акт №1 и приложения: архитектура, API-слой, индексы OpenSearch, RBAC, реестр критических данных, карточки агентов.

# Акт сдачи-приёмки работ № 1

## Этап 0 «Исследование и архитектура»

---

**Приложение №1 к Договору №04-002 от 24.04.2026** об оказании услуг между ООО «Экобанкинг» и ООО «АйТек»

---

г. Москва «» **\___\_**\_ 2026 г.

---

**ООО «Экобанкинг»** (далее -- Исполнитель) в лице **\_*\_, действующего на основании \_***\_, с одной стороны,

и

**ООО «АйТек»** (далее -- Заказчик) в лице **\_*\_, действующего на основании \_***\_, с другой стороны,

совместно именуемые «Стороны», составили настоящий Акт о нижеследующем.

---

## 1\. Предмет акта

В соответствии с Договором №04-002 от 24.04.2026 и Техническим заданием (Приложение №1) Исполнитель выполнил, а Заказчик принимает результаты работ по **Этапу 0 «Исследование и архитектура»** в рамках проекта «Разработка и внедрение мультиагентной AI-системы Grace CRM Assistant для отдела продаж ООО „АйТек"».

---

## 2\. Состав выполненных работ

В рамках Этапа 0 Исполнителем выполнены следующие работы и подготовлены соответствующие документы.

### 2\.1 Исследование API Grace CRM и схемы данных

Исполнителем проведено исследование REST API системы Grace CRM ([grace.i-tech.su](http://grace.i-tech.su)), включая:

-  инвентаризацию доступных API-эндпоинтов по сущностям: projects, clients, activities, tasks, comments, calculations, orders, users, objects;

-  исследование схемы базы данных MySQL Grace CRM (365 таблиц, ключевые домены: заказы, клиенты, проекты, расчёты, производство, платежи);

-  верификацию доступности данных через API и определение параметров инкрементальной синхронизации (`updated_since`);

-  выявление особенностей данных, критичных для архитектуры системы (поле `company_id`, NULL-контур, полиморфные связи комментариев).

**Результат:** зафиксирована модель данных Grace CRM, достаточная для проектирования агентов и схемы синхронизации.

---

### 2\.2 Проектирование индексов OpenSearch

Спроектирована и развёрнута структура из **15 индексов OpenSearch**, обеспечивающая поисковый и аналитический слой системы.

**Документ:** `01_opensearch_`[`schema.md`](http://schema.md)

| Группа                   | Индексы                                                                                                                                                                                         |
|--------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Контур продаж (Sales AI) | `itech_projects`, `itech_accounts`, `itech_calculations`, `itech_orders`, `itech_order_items`, `itech_comments`, `itech_contacts`, `itech_properties`, `itech_expected_payments`, `itech_users` |
| Продуктовый каталог      | `itech_nomenclatures`, `itech_calc_nomenclatures`, `itech_bom_components`, `itech_purchase_items`                                                                                               |
| Управление разработкой   | `itech_digital_requests`                                                                                                                                                                        |

Для каждого индекса определены: маппинг полей, типы данных, анализаторы (`ru_standard`, `standard`), правила фильтрации, связи между индексами.

**Текущее состояние:** OpenSearch развёрнут, все 15 индексов наполнены данными (\~225 000 документов), OpenSearch Dashboards доступны по адресу [`http://localhost:5601`](http://localhost:5601).

---

### 2\.3 Архитектура агентов обоих контуров

Спроектирована агентная архитектура системы с описанием каждого агента по продуктовому методу: продукт агента, внутренний клиент, механизм, триггер, входные данные, критерий выполнения.

**Документ:** `00_`[`architecture.md`](http://architecture.md)

**Контур 1 -- Sales AI (Grace CRM Assistant):**

| Агент                | Продукт                                                          |
|----------------------|------------------------------------------------------------------|
| Sync Agent           | Актуальный поисковый образ данных CRM в OpenSearch               |
| Quality Agent        | Ежедневный реестр проектов с критическими пробелами данных       |
| Recommendation Agent | Конкретный следующий шаг по каждому активному проекту            |
| Notification Agent   | Адресное уведомление через Mattermost (осн.) / Telegram (резерв) |
| Orchestrator         | Бесперебойная работа агентной системы как единого целого         |

**Контур 2 -- Knowledge AI (база знаний):**

| Агент        | Продукт                                                |
|--------------|--------------------------------------------------------|
| Ingest Agent | Проиндексированный документ в RAGflow с метаданными    |
| Query Agent  | Контекстный ответ с цитатой из источника за ≤ 5 секунд |
| Lint Agent   | Еженедельный отчёт о противоречиях и устаревших данных |

Для каждого агента зафиксированы: входные данные, индексы OpenSearch, формат выходного продукта, критерии качества.

---

### 2\.4 Схема интеграции Grace CRM -> OpenSearch

Спроектирована схема синхронизации данных из Grace CRM в OpenSearch через Sync Agent.

**Документ:** `02_integration_`[`schema.md`](http://schema.md)

Схема включает:

-  механизм запуска: CLI-команда с параметрами режима и периода;

-  два режима синхронизации: инкрементальный (каждые 15 минут, параметр `updated_since`) и полный (ежедневно в 02:00, полная пересборка индексов);

-  правила трансформации данных: денормализация, вычисляемые поля, нормализация форматов;

-  стратегию обработки конфликтов: последнее изменение по `updated_at` побеждает, idempotent upsert;

-  механизм retry и логирования ошибок;

-  требования к API Grace CRM для корректной работы интеграции.

---

### 2\.5 Спецификация API-слоя для внешних систем

Разработана спецификация API-слоя Grace CRM Assistant для интеграции с внешними системами (BI, ERP, 1С).

**Документ:** `03_api_`[`spec.md`](http://spec.md)

Спецификация включает:

-  базовые параметры (Base URL, аутентификация Bearer JWT, формат JSON);

-  эндпоинты группы «Данные CRM»: проекты, рекомендации, аналитика воронки, коэффициент качества (Кк), backlog;

-  эндпоинты группы «База знаний»: поиск, загрузка документов;

-  эндпоинты группы «Управление системой»: синхронизация, health check, метрики;

-  матрицу доступа по ролям к каждой группе эндпоинтов;

-  коды ошибок и лимиты запросов.

---

### 2\.6 Ролевая модель (RBAC)

Разработана ролевая модель системы для контуров Sales AI и Knowledge AI.

**Документ:** `04_`[`rbac.md`](http://rbac.md)

Модель включает:

-  6 ролей системы: `manager`, `rop`, `deputy_gd`, `admin`, `knowledge_manager`, `system`;

-  матрицу прав доступа по объектам: данные CRM, рекомендации, аналитика, база знаний, управление системой, уведомления;

-  правила изоляции данных: менеджер видит только свои проекты; данные о премиях (Кк) доступны только менеджеру и его РОПу; Зам. ГД видит только агрегированные данные;

-  требования к аутентификации (SSO через Grace CRM / JWT Bearer Token / API Key);

-  требования к audit log (хранение 12 месяцев, перечень обязательных событий).

---

### 2\.7 Выбор фреймворка и архитектура агентов базы знаний

Зафиксирован выбор технологического стека для реализации системы.

**Зафиксировано в:** `00_`[`architecture.md`](http://architecture.md), раздел 5

| Компонент          | Технология                                    | Обоснование                                                                  |
|--------------------|-----------------------------------------------|------------------------------------------------------------------------------|
| Агентный фреймворк | **Agno**                                      | Нативная поддержка Teams, on-premise, совместимость с RAGflow через tool API |
| LLM основной       | OpenAI GPT-4o / GPT-4o-mini                   | Function calling, высокое качество рассуждения                               |
| LLM резервный      | GigaChat / YandexGPT                          | Fallback без изменения логики агентов                                        |
| База знаний        | **RAGflow**                                   | Self-hosted, гибридный поиск, граф знаний, on-premise                        |
| Поисковый слой     | **OpenSearch 2.13**                           | 15 индексов CRM, развёрнут и наполнен                                        |
| Коммуникации       | **Mattermost** (осн.) + **Telegram** (резерв) | Adapter pattern, канал per-user                                              |
| Деплой             | **Docker Compose**                            | On-premise, инфраструктура I-TECH                                            |

---

### 2\.8 Работающее окружение для разработки

Развёрнуто и передано Заказчику рабочее окружение для начала Этапа 1:

| Компонент                            | Статус      | Адрес                                                      |
|--------------------------------------|-------------|------------------------------------------------------------|
| OpenSearch 2.13                      | ✅ Работает  | [`http://localhost:9200`](http://localhost:9200)           |
| OpenSearch Dashboards                | ✅ Работает  | [`http://localhost:5601`](http://localhost:5601)           |
| RAGflow                              | ✅ Развёрнут | [`http://localhost:9380`](http://localhost:9380)           |
| ETL-скрипт (Grace CRM -> OpenSearch) | ✅ Готов     | `scripts/mysql_to_`[`opensearch.py`](http://opensearch.py) |
| 15 индексов OpenSearch               | ✅ Наполнены | \~225 000 документов                                       |

---

## 3\. Соответствие требованиям ТЗ

| Требование Этапа 0 (ТЗ, раздел 6)                      | Выполнено                  | Документ                                                   |
|--------------------------------------------------------|----------------------------|------------------------------------------------------------|
| Исследование API Grace CRM и схемы MS SQL              | ✅                          | `00_`[`architecture.md`](http://architecture.md), раздел 3 |
| Проектирование индексов OpenSearch                     | ✅                          | `01_opensearch_`[`schema.md`](http://schema.md)            |
| Архитектура агентов обоих контуров                     | ✅                          | `00_`[`architecture.md`](http://architecture.md), раздел 4 |
| Выбор фреймворка агентов базы знаний                   | ✅                          | `00_`[`architecture.md`](http://architecture.md), раздел 5 |
| Ролевая модель (агенты продаж + база знаний)           | ✅                          | `04_`[`rbac.md`](http://rbac.md)                           |
| Схема интеграции (коннектор, периодичность, конфликты) | ✅                          | `02_integration_`[`schema.md`](http://schema.md)           |
| Спецификация API-слоя для внешних систем               | ✅                          | `03_api_`[`spec.md`](http://spec.md)                       |
| Работающее окружение для разработки                    | ✅                          | Артефакт (п. 2.8 настоящего Акта)                          |
| Согласование                                           | Подписание настоящего Акта | --                                                         |

---

## 4\. Открытые вопросы, перенесённые на Этап 1

Следующие вопросы выявлены в ходе Этапа 0 и требуют уточнения или реализации в рамках Этапа 1:

| \# | Вопрос                                                                                | Ответственный |
|----|---------------------------------------------------------------------------------------|---------------|
| 1  | Поддержка webhooks в API Grace CRM -- уточнить у разработчика Grace                   | Заказчик      |
| 2  | Лимиты запросов (rate limit) API Grace CRM -- получить от разработчика Grace          | Заказчик      |
| 3  | Финальная формула расчёта Кк и веса для каждой проверки -- утвердить у РОПа и Зам. ГД | Заказчик      |
| 4  | Конкретный сервер / инфраструктура для production-деплоя                              | Заказчик      |
| 5  | Список ответственных по ролям (knowledge_manager, admin)                              | Заказчик      |

---

## 5\. Стоимость и оплата

В соответствии с Договором №04-002 от 24.04.2026 стоимость работ по Этапу 0 составляет:

**\_*\_ рублей \_*\_ копеек (\_***\_ руб.  коп.), в том числе НДС %: \_*\__________\_ рублей.

Оплата производится в порядке, предусмотренном Договором.

---

## 6\. Заключение

Стороны подтверждают, что работы по Этапу 0 «Исследование и архитектура» выполнены Исполнителем в полном объёме, в соответствии с требованиями Технического задания и с надлежащим качеством.

Заказчик претензий по объёму, качеству и срокам выполненных работ не имеет.

Настоящий Акт составлен в двух экземплярах, имеющих равную юридическую силу, -- по одному для каждой из Сторон.

---

## 7\. Подписи сторон

|                       |                       |
|-----------------------|-----------------------|
| **ИСПОЛНИТЕЛЬ**       | **ЗАКАЗЧИК**          |
| ООО «Экобанкинг»      | ООО «АйТек»           |
|                       |                       |
| **\_________\_**\__\_ | **\_________\_**\__\_ |
| (подпись)             | (подпись)             |
|                       |                       |
| **\_________\_**\__\_ | **\_________\_**\__\_ |
| (ФИО, должность)      | (ФИО, должность)      |
|                       |                       |
| М.П.                  | М.П.                  |

---

## Приложения к настоящему Акту

1. `00_`[`architecture.md`](http://architecture.md) -- Техническое описание архитектуры Grace CRM Assistant

2. `01_opensearch_`[`schema.md`](http://schema.md) -- Схема индексов OpenSearch

3. `02_integration_`[`schema.md`](http://schema.md) -- Схема интеграции Grace CRM -> OpenSearch

4. `03_api_`[`spec.md`](http://spec.md) -- Спецификация API-слоя для внешних систем

5. `04_`[`rbac.md`](http://rbac.md) -- Ролевая модель (RBAC)

6. `05_agent_`[`cards.md`](http://cards.md) -- Карточки агентов (продуктовый подход)

# Техническое описание архитектуры — Grace CRM Assistant

**Версия:** 1\.0 **Дата:** 4 мая 2026

**Статус:** Этап 0 -- согласование файл 00\_[architecture.md](http://architecture.md)

**Проект:** Мультиагентная AI-система для отдела продаж I-TECH

---

## 1\. Назначение системы

Grace CRM Assistant -- мультиагентная AI-система, развёртываемая поверх корпоративной CRM Grace ([grace.i-tech.su](http://grace.i-tech.su)). Система выполняет advisory-функцию: анализирует данные CRM, контролирует качество данных, формирует рекомендации менеджерам, обеспечивает управленческий контроль -- не нарушая принципа **Grace CRM = source of truth**.

Все изменения в CRM производятся только через API Grace. Система не имеет прямого доступа к базе данных MySQL.

---

## 2\. Состав системы

Система включает два функциональных контура.

### Контур 1 -- Sales AI (Grace CRM Assistant)

| Агент                | Наименование            | Продукт агента                                           |
|----------------------|-------------------------|----------------------------------------------------------|
| Sync Agent           | Агент синхронизации     | Актуальный поисковый образ данных CRM в OpenSearch       |
| Quality Agent        | Агент контроля качества | Реестр проектов с критическими пробелами данных          |
| Recommendation Agent | Агент рекомендаций      | Конкретный следующий шаг по каждому активному проекту    |
| Notification Agent   | Агент уведомлений       | Доставленное уведомление с подтверждённой реакцией       |
| Orchestrator         | Оркестратор             | Бесперебойная работа агентной системы как единого целого |

### Контур 2 -- Knowledge AI (база знаний)

| Агент        | Наименование          | Продукт агента                                          |
|--------------|-----------------------|---------------------------------------------------------|
| Ingest Agent | Агент загрузки знаний | Проиндексированный документ в RAGflow с метаданными     |
| Query Agent  | Агент поиска знаний   | Контекстный ответ с цитатой из источника                |
| Lint Agent   | Агент аудита знаний   | Отчёт о противоречиях и устаревших данных в базе знаний |

---

## 3\. Архитектура решения

### 3\.1 Общая схема

```
┌─────────────────────────────────────┐
│         Grace CRM (MySQL)           │
│         source of truth             │
└──────────────┬──────────────────────┘
               │ API (REST)
               │ CLI-синхронизация
               ▼
┌──────────────────────────────────────┐
│           Sync Agent                 │
│         (Agno framework)             │
└──────┬──────────────────┬────────────┘
       │                  │
       ▼                  ▼
┌─────────────┐    ┌──────────────────┐
│  OpenSearch │    │     RAGflow      │
│  (15 индек- │    │  (база знаний,   │
│   сов CRM)  │    │   векторный      │
└──────┬──────┘    │   поиск)         │
       │           └──────┬───────────┘
       └────────┬──────────┘
                ▼
┌───────────────────────────────────────┐
│          Orchestrator (Agno)          │
│     управление, приоритизация, SLA    │
└──────┬───────────────┬────────────────┘
       │               │
       ▼               ▼
┌────────────┐  ┌─────────────────┐
│  Quality   │  │ Recommendation  │
│   Agent    │  │     Agent       │
└─────┬──────┘  └───────┬─────────┘
      │                 │
      └────────┬─────────┘
               ▼
┌──────────────────────────────────────┐
│          Notification Agent          │
│  Mattermost (основной) / Telegram    │
│  adapter pattern, канал per-user     │
└──────────────────────────────────────┘
```

### 3\.2 Слой данных

| Слой          | Система                  | Роль                                              |
|---------------|--------------------------|---------------------------------------------------|
| Источник      | Grace CRM (MySQL)        | Source of truth для операционных данных           |
| Поисковый     | OpenSearch (15 индексов) | Быстрый доступ, аналитика, downstream для агентов |
| Семантический | RAGflow                  | База знаний, векторный поиск, RAG                 |

### 3\.3 Ключевые принципы архитектуры

-  Grace CRM -- единственный источник операционных данных

-  AI-система выполняет advisory-функцию, не операционную

-  Все записи в CRM -- только через API Grace

-  Слабая связанность: агенты независимы, новые роли добавляются без изменения существующих

-  Событийная модель: cron-polling + ручной запуск (webhooks -- при наличии поддержки в API Grace)

-  On-premise развёртывание

---

## 4\. Описание агентов -- продуктовый подход

Каждый агент описывается через продуктовую формулу:

**Продукт × Внутренний клиент × Триггер × Критерий выполнения**

---

### 4\.1 Sync Agent -- Агент синхронизации

**Продукт:** Актуальный поисковый образ данных Grace CRM в OpenSearch -- гарантирующий, что любой запрос от downstream-агентов отражает реальное состояние CRM на момент последнего запуска.

| Параметр                | Содержание                                                                                           |
|-------------------------|------------------------------------------------------------------------------------------------------|
| **Внутренний клиент**   | Quality Agent, Recommendation Agent                                                                  |
| **Механизм**            | CLI -> API Grace CRM -> трансформация -> bulk index в OpenSearch                                     |
| **Триггер**             | Cron по расписанию + ручной запуск администратором                                                   |
| **Входные данные**      | API Grace CRM: projects, activities, clients, tasks, comments, calculations, orders, users, objects  |
| **Выходной продукт**    | Обновлённые индексы OpenSearch (15 индексов)                                                         |
| **Критерий выполнения** | Все индексы обновлены без ошибок; расхождение Grace CRM / OpenSearch = 0 по завершении синхронизации |

**Режимы работы:**

| Режим           | Триггер                                     | Что синхронизируется                                      |
|-----------------|---------------------------------------------|-----------------------------------------------------------|
| Инкрементальный | Cron каждые N минут                         | Изменения с последнего запуска (параметр `updated_since`) |
| Полный          | Ночной cron / ручной запуск администратором | Все сущности, полная пересборка индексов                  |

**Входные данные (API endpoints):**

```
GET /api/projects?updated_since=timestamp
GET /api/projects/{id}
GET /api/activities?updated_since=timestamp
GET /api/clients?updated_since=timestamp
GET /api/clients/{id}
GET /api/tasks?updated_since=timestamp
GET /api/comments?entity_type=&entity_id=
GET /api/calculations?updated_since=timestamp
GET /api/orders?updated_since=timestamp
GET /api/users
GET /api/objects?updated_since=timestamp
```

**Красный флаг:** ошибка синхронизации -> downstream-агенты работают на устаревших данных -> все рекомендации невалидны.

---

### 4\.2 Quality Agent -- Агент контроля качества данных

**Продукт:** Ежедневный реестр проектов с критическими пробелами данных -- для менеджеров и РОПа -- с указанием конкретного поля, ответственного и срока устранения.

| Параметр                | Содержание                                                                                          |
|-------------------------|-----------------------------------------------------------------------------------------------------|
| **Внутренний клиент 1** | Менеджер -- задача на заполнение по своим проектам                                                  |
| **Внутренний клиент 2** | РОП -- сводка по команде, эскалация при просрочке                                                   |
| **Триггер**             | Ежедневно в 09:00 + при изменении статуса проекта                                                   |
| **Входные данные**      | OpenSearch: `itech_projects`, `itech_calculations`, `itech_activities`; правила проверки из конфига |
| **Выходной продукт**    | Структурированный реестр: проект -> пробел -> ответственный -> срок; сигнал в Notification Agent    |
| **Критерий выполнения** | Доля проектов с полными данными ≥ 85%; каждый пробел имеет назначенного ответственного              |

**Правила проверки (настраиваются в конфиге):**

| Проверка          | Поле                                                                                 | Условие                                          |
|-------------------|--------------------------------------------------------------------------------------|--------------------------------------------------|
| Обязательные поля | `account_id`, `property_id`, `project_status_id`, `probability_new`, `forecast_date` | Не пусто                                         |
| Следующий шаг     | `next_action`, `next_action_date`                                                    | Заполнено и дата не в прошлом                    |
| Логика статусов   | `calculation_status`                                                                 | При статусе «КП выставлено» -- существует расчёт |
| Активность        | `last_activity_at`                                                                   | Не более 30 дней назад для активных проектов     |

---

### 4\.3 Recommendation Agent -- Агент рекомендаций

**Продукт:** Конкретный следующий шаг по каждому активному проекту -- для менеджера -- сформулированный на основе истории CRM и базы знаний RAGflow, доставляемый не позднее 2 часов после изменения статуса или по запросу.

| Параметр                | Содержание                                                                                                                    |
|-------------------------|-------------------------------------------------------------------------------------------------------------------------------|
| **Внутренний клиент**   | Менеджер (первично); РОП (при просрочке реакции)                                                                              |
| **Триггер**             | Изменение статуса проекта / запрос менеджера / просрочка контакта                                                             |
| **Входные данные**      | OpenSearch (`itech_projects`, `itech_calculations`, `itech_comments`, `itech_accounts`); RAGflow (кейсы, скрипты, возражения) |
| **Выходной продукт**    | Рекомендация: действие + срок + обоснование + ссылка на кейс из базы знаний                                                   |
| **Критерий выполнения** | Менеджер знает следующий шаг по каждому активному проекту; нет проектов без зафиксированного следующего действия              |

**Формат рекомендации:**

```
Проект: [название] | Клиент: [название] | Стадия: [статус]Последний контакт: N дней назад​Рекомендация: [конкретное действие]Срок: [дата]Обоснование: [краткое обоснование]Похожий кейс: [ссылка из базы знаний]
```

---

### 4\.4 Notification Agent -- Агент уведомлений

**Продукт:** Адресное уведомление нужному человеку в нужный момент через нужный канал -- без информационного шума -- как условие того, что сигналы системы реально доходят и вызывают реакцию.

| Параметр                | Содержание                                                                               |
|-------------------------|------------------------------------------------------------------------------------------|
| **Внутренний клиент**   | Менеджер / РОП / Зам. ГД -- в зависимости от типа события                                |
| **Триггер**             | Сигнал от любого агента системы                                                          |
| **Входные данные**      | Сигнал от агента + профиль получателя (предпочтительный канал)                           |
| **Выходной продукт**    | Доставленное уведомление с подтверждённой реакцией                                       |
| **Механизм доставки**   | Adapter pattern: Mattermost (основной) / Telegram (резерв), канал настраивается per-user |
| **Критерий выполнения** | Реакция в течение N часов; при отсутствии реакции -- эскалация в Orchestrator            |

**Матрица маршрутизации уведомлений:**

| Событие                                          | Получатель   | Приоритет  |
|--------------------------------------------------|--------------|------------|
| Пробел в данных по своему проекту                | Менеджер     | Нормальный |
| Просрочка реакции менеджера > SLA                | РОП          | Высокий    |
| Рекомендация по проекту                          | Менеджер     | Нормальный |
| Критическое событие (крупная сделка, риск ухода) | РОП, Зам. ГД | Высокий    |
| Сводка по команде                                | РОП          | Ежедневный |

---

### 4\.5 Orchestrator -- Оркестратор

**Продукт:** Бесперебойная работа агентной системы как единого целого -- обеспечивающая, что ни одно критическое событие не теряется и каждый сигнал доходит до нужного человека в нужное время.

| Параметр                | Содержание                                                                               |
|-------------------------|------------------------------------------------------------------------------------------|
| **Внутренний клиент**   | РОП, Зам. ГД                                                                             |
| **Триггер**             | Постоянно -- реагирует на сигналы всех агентов                                           |
| **Входные данные**      | Сигналы от всех агентов; SLA-параметры из конфига                                        |
| **Выходной продукт**    | Гарантия непрерывности потока сигналов; каждое событие имеет назначенного ответственного |
| **Критерий выполнения** | Отсутствие потерянных эскалаций; система работает без ручного вмешательства              |

---

### 4\.6 Ingest Agent -- Агент загрузки знаний

**Продукт:** Проиндексированный документ в RAGflow с корректными метаданными -- готовый к поиску Query Agent.

| Параметр                | Содержание                                                                                |
|-------------------------|-------------------------------------------------------------------------------------------|
| **Внутренний клиент**   | Query Agent, Recommendation Agent                                                         |
| **Триггер**             | Загрузка нового документа ответственным за базу знаний                                    |
| **Входные данные**      | Документ (PDF, DOCX, MD) + метаданные: отрасль, тип клиента, стадия сделки, продукт, теги |
| **Выходной продукт**    | Проиндексированная запись в RAGflow; обновлённый граф связей                              |
| **Критерий выполнения** | Документ доступен для поиска; метаданные заполнены полностью                              |

---

### 4\.7 Query Agent -- Агент поиска знаний

**Продукт:** Контекстный ответ с цитатой из источника -- для менеджера -- за ≤ 5 секунд.

| Параметр                | Содержание                                        |
|-------------------------|---------------------------------------------------|
| **Внутренний клиент**   | Менеджер, Recommendation Agent                    |
| **Триггер**             | Запрос менеджера / вызов от Recommendation Agent  |
| **Входные данные**      | Текстовый запрос + контекст проекта               |
| **Выходной продукт**    | Ответ + цитата + ссылка на источник               |
| **Критерий выполнения** | Релевантный ответ ≤ 5 сек; источник всегда указан |

---

### 4\.8 Lint Agent -- Агент аудита знаний

**Продукт:** Еженедельный отчёт о противоречиях, устаревших данных и логических разрывах в базе знаний.

| Параметр                | Содержание                                                                         |
|-------------------------|------------------------------------------------------------------------------------|
| **Внутренний клиент**   | Ответственный за базу знаний                                                       |
| **Триггер**             | Еженедельно                                                                        |
| **Входные данные**      | Все документы в RAGflow                                                            |
| **Выходной продукт**    | Отчёт: список противоречий, устаревших фактов, незаполненных разделов              |
| **Критерий выполнения** | Выявлены все документы старше 6 месяцев и документы с конфликтующими утверждениями |

---

## 5\. Технологический стек

| Слой               | Технология                                        | Роль                                  |
|--------------------|---------------------------------------------------|---------------------------------------|
| Агентный фреймворк | **Agno**                                          | Агенты, Teams, оркестрация            |
| LLM (основной)     | OpenAI GPT-4o / GPT-4o-mini                       | Рассуждение, генерация рекомендаций   |
| LLM (резерв)       | GigaChat / YandexGPT                              | Fallback при недоступности OpenAI     |
| Поисковый слой     | **OpenSearch 2.13**                               | 15 индексов CRM, аналитика            |
| База знаний        | **RAGflow**                                       | Семантический поиск, RAG, граф знаний |
| Коммуникации       | **Mattermost** (основной) + **Telegram** (резерв) | Доставка уведомлений, adapter pattern |
| Синхронизация      | CLI + Agno Agent                                  | Grace CRM API -> OpenSearch           |
| Планировщик        | Cron / systemd timer                              | Расписание синхронизации и агентов    |
| Деплой             | **Docker Compose**                                | On-premise, I-TECH инфраструктура     |

### Выбор фреймворка агентов базы знаний

Для контура Knowledge AI выбран **RAGflow** как платформа базы знаний по следующим основаниям:

| Критерий          | RAGflow                                                     |
|-------------------|-------------------------------------------------------------|
| Развёртывание     | Self-hosted, on-premise -- соответствует требованиям I-TECH |
| Поиск             | Гибридный: semantic + full-text                             |
| Граф знаний       | Поддерживается нативно                                      |
| Интеграция с Agno | Через REST API -- Agno вызывает RAGflow как tool            |
| Мультиформатность | PDF, DOCX, MD, TXT                                          |

Агенты контура Knowledge AI реализованы на **Agno** и взаимодействуют с RAGflow через его REST API как с внешним инструментом (tool call). Прямой встройки RAGflow в агентный фреймворк не требуется.

---

## 6\. Цепочка данных (основной сценарий)

```
Grace CRM (MySQL)    ↓  CLI → APISync Agent    ↓  bulk indexOpenSearch (15 индексов)    ↓  запрос агентовQuality Agent → реестр пробелов → Notification Agent → Mattermost/Telegram → МенеджерRecommendation Agent → рекомендация → Notification Agent → Mattermost/Telegram → Менеджер    ↑RAGflow (база знаний) — контекст для рекомендаций
```

---

## 7\. Что остаётся за рамками Этапа 0

| Тема                                                  | Этап   |
|-------------------------------------------------------|--------|
| Калькулятор премии (Кк)                               | Этап 1 |
| Telegram-бот (UI)                                     | Этап 2 |
| Полная интеграция RAGflow + Ingest/Query/Lint агентов | Этап 2 |
| Интеграция с 1С ЕРП                                   | Этап 3 |

---

## 8\. Программа и методика приёмо-сдаточных испытаний (ПМИ)

### 8\.1 Общие принципы

ПМИ фиксирует проверку каждого функционального блока системы на соответствие требованиям Этапа 0.

Формат тест-кейса:

-  Идентификатор

-  Описание

-  Входные данные

-  Шаги выполнения

-  Ожидаемый результат (эталон)

-  Допустимое отклонение

-  Критерий: пройдено / не пройдено

---

### 8\.2 ПМИ -- Sync Agent

**TC-SA-01 -- Инкрементальная синхронизация**

-  Вход: изменения в CRM (≥1 запись)

-  Шаги: запуск `grace-sync run --mode incremental`

-  Ожидаемо: записи появляются в OpenSearch

-  Отклонение: ≤1% записей может быть с задержкой

-  Критерий: все записи синхронизированы

**TC-SA-02 -- Полная синхронизация**

-  Вход: полный запуск

-  Ожидаемо: алиас переключён, данные консистентны

-  Критерий: расхождение с CRM = 0

---

### 8\.3 ПМИ -- Quality Agent

**TC-QA-01 -- Обнаружение пробелов**

-  Вход: проект без forecast_date

-  Ожидаемо: проект попадает в реестр

-  Критерий: найден 100% таких проектов

**TC-QA-02 -- SLA-эскалация**

-  Вход: нет реакции > SLA

-  Ожидаемо: уведомление РОП

-  Критерий: эскалация сработала

---

### 8\.4 ПМИ -- Recommendation Agent

**TC-RA-01 -- Генерация рекомендации**

-  Вход: проект без активности >14 дней

-  Ожидаемо: рекомендация сформирована ≤2 часа

-  Критерий: рекомендация содержит действие, срок, обоснование

---

### 8\.5 ПМИ -- Notification Agent

**TC-NA-01 -- Доставка уведомления**

-  Вход: событие от агента

-  Ожидаемо: сообщение доставлено

-  Критерий: получено пользователем

---

### 8\.6 ПМИ -- API

**TC-API-01 -- Получение проектов**

-  Вход: GET /projects

-  Ожидаемо: список проектов

-  Критерий: HTTP 200, корректный JSON

---

### 8\.7 ПМИ -- Knowledge AI

**TC-KB-01 -- Поиск**

-  Вход: запрос

-  Ожидаемо: ответ с источником

-  Критерий: время ≤5 сек

---

## 9\. Прототипы дашбордов OpenSearch Dashboards

### 9\.1 Общие требования

-  Фильтры: период, тип клиента

-  Экспорт: Excel / PDF

---

### 9\.2 Дашборд «Менеджер»

**Фильтры**: период, стадия, тип клиента

**Виджеты:**

-  Воронка продаж по стадиям

-  Мои проекты (таблица)

-  Просроченные действия

-  Топ «спящих» клиентов

-  Рекомендации (список)

---

### 9\.3 Дашборд «РОП»

**Фильтры**: менеджер, период, стадия, тип клиента

**Виджеты:**

-  Воронка по команде (динамика)

-  Распределение заказов и проектов по менеджерам

-  Топ-10 спящих клиентов

-  Средний Кк по отделу

   Кк = 1 - (количество проектов с ошибками / общее количество проектов)

-  Эскалации:

   -  проект

   -  менеджер

   -  время просрочки

   -  статус

---

### 9\.4 Дашборд «Зам. ГД»

**Виджеты:**

-  Created / Shipped / Backlog (динамика) -- график, показывающий изменение объёма созданных заказов (Created), фактически отгруженной выручки (Shipped) и накопленного незавершённого портфеля (Backlog) во времени; позволяет оценить баланс между продажами, отгрузками и ростом незавершёнки

-  Growth YoY (%) -- показатель год-к-году, отражающий темп роста ключевых метрик (Created, Shipped, Backlog) относительно аналогичного периода прошлого года; используется для оценки динамики бизнеса

-  Backlog vs Shipped -- сравнительный график объёма незавершённого портфеля (Backlog) и фактической отгрузки (Shipped); позволяет выявить перегрев воронки и риски накопления незавершёнки

-  Производственная нагрузка (items, hours) -- метрики загрузки производства: количество активных позиций (items) и суммарные трудозатраты (hours); позволяет оценить соответствие объёма продаж возможностям производства

-  Monthly trend -- помесячная динамика ключевых показателей (Created, Shipped); используется для выявления сезонности, пиков и провалов продаж

Дополнительно:

-  Прогноз выручки

---

## 10\. Развёртывание и инфраструктура

### 10\.1 Сервер

-  ОС: Ubuntu 24.04 LTS

-  CPU: Intel Xeon E5-2620 v4 (8 ядер, 2.1 GHz)

-  RAM: 32 GB

-  Диск: 2×240 GB SSD

---

### 10\.2 Размещение компонентов

| Компонент   | Размещение          |
|-------------|---------------------|
| OpenSearch  | Docker container    |
| RAGflow     | Docker container    |
| Agno Agents | Docker container    |
| API Layer   | Docker container    |
| Mattermost  | Внешний / контейнер |

---

### 10\.3 Требования к ресурсам

-  OpenSearch: ≥16 GB RAM

-  RAGflow: ≥8 GB RAM

-  Agents/API: ≥4 GB RAM

---

### 10\.4 Сеть и доступ

-  Внутренний контур (VPN / LAN)

-  Доступ по HTTP(S)

-  Ограничение по IP

---

### 10\.5 Запуск (базовый)

```
docker-compose up -d
```

---

### 10\.6 Резервное копирование

-  OpenSearch snapshot (ежедневно)

-  RAGflow storage backup

---

### 10\.7 Мониторинг

-  Health endpoint `/api/v1/health`

-  Логи Docker

-  Метрики OpenSearch

# Спецификация API-слоя — Grace CRM Assistant

**Версия:** 1\.0 **Дата:** 4 мая 2026

**Статус:** Этап 0 -- согласование файл 03_api\_[spec.md](http://spec.md)

---

## 1\. Назначение

API-слой Grace CRM Assistant предоставляет интерфейс для:

-  получения данных из OpenSearch внешними системами (BI, ERP, 1С)

-  получения AI-сигналов и рекомендаций

-  управления агентами (запуск синхронизации, статус системы)

-  будущей интеграции с другими сервисами экосистемы I-TECH

Все эндпоинты доступны только на внутренней сети. Публичного доступа нет.

---

## 2\. Базовые параметры

| Параметр        | Значение                                                                     |
|-----------------|------------------------------------------------------------------------------|
| Base URL        | [`http://grace-ai.i-tech.local/api/v1`](http://grace-ai.i-tech.local/api/v1) |
| Протокол        | HTTP/HTTPS (TLS 1.3 внутри периметра)                                        |
| Формат          | JSON                                                                         |
| Аутентификация  | Bearer Token (JWT)                                                           |
| Версионирование | URI (`/v1/`, `/v2/`)                                                         |

### Заголовки запроса

```
Authorization: Bearer {token}Content-Type: application/jsonAccept: application/json
```

### Стандартный формат ответа

```
{  "success": true,  "data": { ... },  "meta": {    "total": 100,    "page": 1,    "per_page": 20  }}
```

### Стандартный формат ошибки

```
{  "success": false,  "error": {    "code": "UNAUTHORIZED",    "message": "Токен недействителен или истёк"  }}
```

---

## 3\. Аутентификация и авторизация

### 3\.1 Получение токена

```
POST /api/v1/auth/tokenContent-Type: application/json​{  "client_id": "erp-system",  "client_secret": "***"}
```

**Ответ:**

```
{  "access_token": "eyJ...",  "expires_in": 3600,  "token_type": "Bearer"}
```

### 3\.2 Матрица доступа по ролям

| Группа эндпоинтов           | manager | rop | deputy_gd | admin | system |
|-----------------------------|---------|-----|-----------|-------|--------|
| `/projects` -- свои проекты | ✅       | ✅   | ✅         | ✅     | ✅      |
| `/projects` -- все проекты  | ❌       | ✅   | ✅         | ✅     | ✅      |
| `/recommendations`          | ✅       | ✅   | ❌         | ✅     | ✅      |
| `/analytics/team`           | ❌       | ✅   | ✅         | ✅     | ✅      |
| `/analytics/aggregate`      | ❌       | ❌   | ✅         | ✅     | ✅      |
| `/sync/*`                   | ❌       | ❌   | ❌         | ✅     | ✅      |
| `/admin/*`                  | ❌       | ❌   | ❌         | ✅     | ❌      |

---

## 4\. Эндпоинты -- данные CRM

### 4\.1 Проекты / Сделки

```
GET /api/v1/projects
```

**Параметры фильтрации:**

| Параметр          | Тип     | Описание                       |
|-------------------|---------|--------------------------------|
| `manager_id`      | integer | Фильтр по менеджеру            |
| `status`          | string  | Статус проекта                 |
| `probability_min` | integer | Минимальная вероятность, %     |
| `updated_since`   | ISO8601 | Изменено после даты            |
| `page`            | integer | Страница (default: 1)          |
| `per_page`        | integer | Записей на странице (max: 100) |

**Ответ:**

```
{  "success": true,  "data": [    {      "id": 15714,      "name": "ЖК Дмитровское небо",      "account_name": "КР ЭНЕРГО ООО",      "manager_name": "Пересунько Павел",      "project_status": "Отправлено КП",      "probability_percent": 65,      "amount": 91769410,      "forecast_date": "2026-06-30"    }  ],  "meta": { "total": 247, "page": 1, "per_page": 20 }}
```

```
GET /api/v1/projects/{id}
```

Возвращает полную карточку проекта включая историю комментариев и список расчётов.

---

### 4\.2 Рекомендации

```
GET /api/v1/recommendations
```

**Параметры:**

| Параметр     | Тип     | Описание                            |
|--------------|---------|-------------------------------------|
| `manager_id` | integer | Рекомендации для менеджера          |
| `project_id` | integer | Рекомендации по проекту             |
| `status`     | string  | `pending` / `acknowledged` / `done` |

**Ответ:**

```
{  "success": true,  "data": [    {      "id": "rec_001",      "project_id": 15714,      "project_name": "ЖК Дмитровское небо",      "account_name": "КР ЭНЕРГО ООО",      "action": "Позвонить клиенту и уточнить статус решения по КП",      "deadline": "2026-05-07",      "rationale": "Последний контакт 18 дней назад, КП на согласовании",      "knowledge_ref": "kb://cases/energo-jk-pattern",      "created_at": "2026-05-04T09:00:00",      "status": "pending"    }  ]}
```

```
POST /api/v1/recommendations/{id}/acknowledge
```

Менеджер подтверждает получение рекомендации.

```
POST /api/v1/recommendations/{id}/done
```

Менеджер отмечает рекомендацию выполненной.

---

### 4\.3 Аналитика

```
GET /api/v1/analytics/funnel
```

Воронка продаж с разбивкой по статусам и менеджерам.

**Параметры:** `manager_id`, `date_from`, `date_to`, `group_by` (manager / status / month)

```
GET /api/v1/analytics/data-quality
```

Коэффициент качества данных (Кк) по менеджерам и отделу.

**Ответ:**

```
{  "success": true,  "data": {    "team_kk": 0.82,    "managers": [      {        "manager_id": 12,        "manager_name": "Стегнина Мария",        "kk": 0.91,        "projects_total": 249,        "projects_with_gaps": 22      }    ]  }}
```

```
GET /api/v1/analytics/backlog
```

Сводка по backlog-позициям (незавершённые отгрузки).

---

## 5\. Эндпоинты -- управление системой

### 5\.1 Синхронизация (только role: admin, system)

```
POST /api/v1/sync/runContent-Type: application/json​{  "mode": "incremental",  "entities": ["projects", "orders"]}
```

**Ответ:**

```
{  "success": true,  "data": {    "run_id": "sync_2026_05_04_090000",    "status": "started",    "estimated_duration_sec": 25  }}
```

```
GET /api/v1/sync/status/{run_id}
```

Статус текущего или последнего запуска синхронизации.

```
GET /api/v1/sync/history
```

История запусков синхронизации (последние 30).

---

### 5\.2 Состояние системы

```
GET /api/v1/health
```

Доступен без авторизации. Возвращает статус всех компонентов.

```
{  "status": "healthy",  "components": {    "opensearch": "healthy",    "ragflow": "healthy",    "grace_api": "healthy",    "sync_agent": "healthy",    "last_sync": "2026-05-04T08:45:00"  }}
```

```
GET /api/v1/metrics
```

Метрики системы для мониторинга (только admin).

---

## 6\. Эндпоинты -- база знаний

```
GET /api/v1/knowledge/search
```

Поиск по базе знаний (через RAGflow).

**Параметры:** `q` (текст запроса), `industry`, `deal_stage`, `product_type`

**Ответ:**

```
{  "success": true,  "data": {    "answer": "По данному типу клиента рекомендуется...",    "sources": [      {        "id": "kb_case_001",        "title": "Кейс: ЦОД-проект, застройщик",        "excerpt": "...",        "relevance": 0.92      }    ]  }}
```

```
POST /api/v1/knowledge/documents
```

Загрузка нового документа в базу знаний (только role: knowledge_manager, admin).

---

## 7\. Коды ошибок

| Код                   | HTTP | Описание                             |
|-----------------------|------|--------------------------------------|
| `UNAUTHORIZED`        | 401  | Токен отсутствует или недействителен |
| `FORBIDDEN`           | 403  | Недостаточно прав для операции       |
| `NOT_FOUND`           | 404  | Ресурс не найден                     |
| `VALIDATION_ERROR`    | 422  | Ошибка валидации параметров          |
| `RATE_LIMITED`        | 429  | Превышен лимит запросов              |
| `INTERNAL_ERROR`      | 500  | Внутренняя ошибка сервера            |
| `SERVICE_UNAVAILABLE` | 503  | Компонент системы недоступен         |

---

## 8\. Лимиты

| Параметр                         | Значение                       |
|----------------------------------|--------------------------------|
| Rate limit                       | 100 запросов / минуту на токен |
| Максимум записей в ответе        | 100 (`per_page`)               |
| Максимальный размер тела запроса | 10 МБ                          |
| Таймаут                          | 30 секунд                      |

# Схема индексов OpenSearch — Grace CRM Assistant

**Версия:** 2.0 **Дата:** 22 июля 2026 (актуализация по проду)

**Источник:** OpenSearch [`http://localhost:9200`](http://localhost:9200) файл 01_opensearch\_[schema.md](http://schema.md)

**Всего индексов:** 31

---

## 1\. Назначение слоя OpenSearch

OpenSearch является поисковым и аналитическим слоем системы. Данные поступают из Grace CRM через Sync Agent и хранятся в виде денормализованных витрин, оптимизированных под сценарии работы AI-агентов.

**Ключевые принципы:**

-  OpenSearch не является источником истины -- им остаётся Grace CRM (MySQL)

-  Все изменения идут по цепочке: Grace CRM -> Sync Agent -> OpenSearch

-  При расхождении данных MySQL приоритетен

-  `company_id = 1` соответствует компании I-Tech

---

## 2\. Индексы контура Sales AI

### 2\.1 `itech_projects` -- Сделки (Opportunities)

Центральный индекс воронки продаж. Используется Quality Agent и Recommendation Agent.

| Поле                  | Тип             | Описание                                           |
|-----------------------|-----------------|----------------------------------------------------|
| `id`                  | integer         | PK                                                 |
| `number`              | keyword         | Номер сделки                                       |
| `name`                | text + .keyword | `ru_standard`                                      |
| `account_id`          | integer         | -> `itech_`[`accounts.id`](http://accounts.id)     |
| `account_name`        | text + .keyword | `ru_standard`                                      |
| `manager_id`          | integer         |                                                    |
| `manager_name`        | text + .keyword | `standard`                                         |
| `engineer_user_id`    | integer         |                                                    |
| `engineer_name`       | text + .keyword | `standard`                                         |
| `property_id`         | integer         | -> `itech_`[`properties.id`](http://properties.id) |
| `property_name`       | text + .keyword | `ru_standard`                                      |
| `project_status_id`   | integer         |                                                    |
| `project_status`      | text + .keyword | `standard`                                         |
| `probability_new`     | keyword         | Вероятность (категория)                            |
| `probability_percent` | integer         | Вероятность, %                                     |
| `amount`              | double          | Сумма сделки                                       |
| `type_of_calculation` | keyword         | Тип тендера                                        |
| `forecast_date`       | date            | Прогнозная дата закрытия                           |
| `refusal_reason`      | text            | Причина отказа, `ru_standard`                      |
| `created_at`          | date            |                                                    |
| `created_year`        | integer         |                                                    |

**Правила фильтрации для агентов:**

-  Активные проекты: исключить статусы «Отказ покупателя», «Покупатель вышел из тендера», «Отказ от участия»

-  Пробел в данных: `forecast_date IS NULL` или `probability_new IS NULL`

---

### 2\.2 `itech_accounts` -- Контрагенты

| Поле                 | Тип             | Описание                            |
|----------------------|-----------------|-------------------------------------|
| `id`                 | integer         | PK                                  |
| `name`               | text + .keyword | `ru_standard`                       |
| `inn`                | keyword         | ИНН                                 |
| `reliability`        | keyword         | red / yellow / green / black / blue |
| `manager_id`         | integer         |                                     |
| `manager_name`       | text + .keyword | `standard`                          |
| `assistant_user_id`  | integer         |                                     |
| `is_prepayment_only` | boolean         | Только предоплата                   |
| `order_count`        | integer         | Кол-во заказов                      |
| `project_count`      | integer         | Кол-во сделок                       |
| `revenue_mln`        | float           | Выручка, млн руб.                   |
| `paid_mln`           | float           | Оплачено, млн руб.                  |
| `debt_mln`           | float           | Долг, млн руб.                      |
| `last_order_at`      | date            | Дата последнего заказа              |
| `sectors`            | keyword         | Отраслевые сектора                  |
| `top_properties`     | keyword         | Топ объекты                         |
| `created_at`         | date            |                                     |

---

### 2\.3 `itech_calculations` -- КП / Расчёты

| Поле                    | Тип             | Описание                                       |
|-------------------------|-----------------|------------------------------------------------|
| `id`                    | integer         | PK                                             |
| `project_id`            | integer         | -> `itech_`[`projects.id`](http://projects.id) |
| `project_name`          | text + .keyword | `ru_standard`                                  |
| `account_id`            | integer         |                                                |
| `account_name`          | text + .keyword | `ru_standard`                                  |
| `manager_id`            | integer         |                                                |
| `manager_name`          | text + .keyword | `standard`                                     |
| `engineer_user_id`      | integer         |                                                |
| `engineer_name`         | text + .keyword | `standard`                                     |
| `calculation_status_id` | integer         |                                                |
| `calculation_status`    | text + .keyword | `standard`                                     |
| `amount`                | double          | Сумма КП                                       |
| `type`                  | keyword         | Тип расчёта                                    |
| `quality`               | keyword         | Точный / Бюджетная оценка                      |
| `is_urgent`             | boolean         | Срочный                                        |
| `due_date`              | date            | Срок выполнения                                |
| `kp_exposed_at`         | date            | Дата выставления КП                            |
| `completed_at`          | date            |                                                |
| `created_at`            | date            |                                                |

---

### 2\.4 `itech_orders` -- Заказы (шапки)

| Поле                 | Тип             | Описание                                       |
|----------------------|-----------------|------------------------------------------------|
| `id`                 | integer         | PK                                             |
| `order_number`       | keyword         | Номер заказа                                   |
| `account_id`         | integer         |                                                |
| `account_name`       | text + .keyword | `ru_standard`                                  |
| `manager_id`         | integer         |                                                |
| `manager_name`       | text + .keyword | `standard`                                     |
| `project_id`         | integer         | -> `itech_`[`projects.id`](http://projects.id) |
| `total_cost`         | double          | Итоговая стоимость                             |
| `general_purchase`   | double          | Себестоимость                                  |
| `is_shipped`         | boolean         | Отгружен                                       |
| `bill_type`          | keyword         | Тип счёта                                      |
| `run_date`           | date            | Дата запуска в производство                    |
| `shipping_date_plan` | date            | Плановая дата отгрузки                         |
| `shipping_date_fact` | date            | Фактическая дата отгрузки                      |
| `created_at`         | date            |                                                |

---

### 2\.5 `itech_order_items` -- Позиции заказов

| Поле                 | Тип             | Описание                                   |
|----------------------|-----------------|--------------------------------------------|
| `id`                 | integer         | PK                                         |
| `order_id`           | integer         | -> `itech_`[`orders.id`](http://orders.id) |
| `order_number`       | keyword         |                                            |
| `name`               | text + .keyword | `standard`                                 |
| `article`            | keyword         | Артикул                                    |
| `amount`             | double          | Сумма с НДС                                |
| `amount_wo_vat`      | double          | Сумма без НДС                              |
| `purchase_plan`      | double          | Плановая себестоимость                     |
| `profit_amount`      | double          | Прибыль                                    |
| `hours_plan`         | double          | Плановые часы                              |
| `is_shipped`         | boolean         |                                            |
| `shipping_date_plan` | date            |                                            |
| `shipping_date_fact` | date            | NULL = позиция в backlog                   |
| `created_at`         | date            |                                            |

---

### 2\.6 `itech_comments` -- Комментарии

| Поле               | Тип             | Описание                                       |
|--------------------|-----------------|------------------------------------------------|
| `id`               | long            | PK                                             |
| `commentable_type` | keyword         | Тип объекта (Project / Calculation / ...)      |
| `commentable_id`   | integer         | ID объекта                                     |
| `author_id`        | integer         |                                                |
| `author_name`      | text + .keyword | `standard`                                     |
| `project_id`       | integer         | -> `itech_`[`projects.id`](http://projects.id) |
| `project_name`     | text + .keyword | `ru_standard`                                  |
| `project_status`   | keyword         | Статус на момент комментария                   |
| `account_name`     | text + .keyword | `standard`                                     |
| `manager_name`     | text + .keyword | `standard`                                     |
| `comment`          | text + .keyword | Текст, `ru_standard`                           |
| `created_at`       | date            |                                                |

---

### 2\.7 `itech_contacts` -- Контактные лица

| Поле             | Тип             | Описание              |
|------------------|-----------------|-----------------------|
| `id`             | integer         | PK                    |
| `full_name`      | text + .keyword | `ru_standard`         |
| `job_title`      | text + .keyword | Должность             |
| `phones`         | keyword         | Массив телефонов      |
| `emails`         | keyword         | Массив email          |
| `is_priority`    | boolean         |                       |
| `accounts`       | **nested**      | Связанные контрагенты |
| └ `account_id`   | integer         |                       |
| └ `account_name` | text + .keyword |                       |
| `created_at`     | date            |                       |

<note type="quote">

⚠️ `accounts` -- nested-тип. Обязательно использовать `nested` query при фильтрации.

</note>

---

### 2\.8 `itech_properties` -- Строительные объекты

| Поле            | Тип             | Описание            |
|-----------------|-----------------|---------------------|
| `id`            | integer         | PK                  |
| `name`          | text + .keyword | `ru_standard`       |
| `address_full`  | text + .keyword | `ru_standard`       |
| `city`          | keyword         |                     |
| `region`        | keyword         |                     |
| `property_type` | keyword         | Тип объекта         |
| `sector`        | keyword         | Отрасль             |
| `account_count` | integer         | Кол-во контрагентов |
| `project_count` | integer         | Кол-во сделок       |
| `top_account`   | keyword         | Основной контрагент |
| `created_at`    | date            |                     |

---

### 2\.9 `itech_expected_payments` -- Ожидаемые платежи

| Поле                 | Тип             | Описание                                   |
|----------------------|-----------------|--------------------------------------------|
| `id`                 | text + .keyword | PK                                         |
| `order_id`           | integer         | -> `itech_`[`orders.id`](http://orders.id) |
| `order_number`       | keyword         |                                            |
| `exp_payment_status` | keyword         | Статус платежа                             |
| `pay_amount`         | double          | Ожидаемая сумма                            |
| `paid_amount`        | double          | Оплаченная сумма                           |
| `pay_date`           | date            | Ожидаемая дата                             |
| `paid_date`          | date            | Фактическая дата                           |
| `created_at`         | date            |                                            |

---

### 2\.10 `itech_users` -- Пользователи системы

| Поле         | Тип             | Описание      |
|--------------|-----------------|---------------|
| `id`         | integer         | PK            |
| `full_name`  | text + .keyword | `ru_standard` |
| `email`      | keyword         |               |
| `title`      | keyword         | Должность     |
| `department` | text + .keyword | `standard`    |
| `roles`      | keyword         | Массив ролей  |
| `is_active`  | boolean         |               |
| `created_at` | date            |               |

---

## 3\. Индексы продуктового каталога

### 3\.1 `itech_nomenclatures` -- Мастер-каталог

| Поле         | Тип             | Описание      |
|--------------|-----------------|---------------|
| `id`         | integer         | PK            |
| `name`       | text + .keyword | `ru_standard` |
| `article`    | keyword         | Артикул       |
| `brand`      | text + .keyword | Бренд         |
| `created_at` | date            |               |

### 3\.2 `itech_calc_nomenclatures` -- Расчётная номенклатура

| Поле                                        | Тип             | Описание                |
|---------------------------------------------|-----------------|-------------------------|
| `article`                                   | keyword         | PK                      |
| `name`                                      | text + .keyword | `ru_standard`           |
| `price`                                     | float           | Нормативная цена        |
| `assembly_time`                             | float           | Норма времени сборки, ч |
| `weight`                                    | float           | Масса, кг               |
| `body_type`                                 | keyword         | Тип корпуса             |
| `body_width` / `body_height` / `body_depth` | integer         | Габариты, мм            |
| `body_ip`                                   | integer         | Степень защиты IP       |
| `rated_in`                                  | float           | Номинальный ток, А      |
| `icu`                                       | float           | Ток отключения, кА      |

### 3\.3 `itech_bom_components` -- BOM-спецификации

| Поле             | Тип     | Описание                                               |
|------------------|---------|--------------------------------------------------------|
| `id`             | integer | PK                                                     |
| `calculation_id` | integer | -> `itech_`[`calculations.id`](http://calculations.id) |
| `project_id`     | integer | -> `itech_`[`projects.id`](http://projects.id)         |
| `article`        | keyword | Артикул компонента                                     |
| `quantity`       | double  | Количество                                             |
| `cost`           | double  | Стоимость                                              |
| `currency`       | keyword | Валюта                                                 |

### 3\.4 `itech_purchase_items` -- Позиции закупок

| Поле                    | Тип             | Описание                                                 |
|-------------------------|-----------------|----------------------------------------------------------|
| `id`                    | integer         | PK                                                       |
| `nomenclature_id`       | integer         | -> `itech_`[`nomenclatures.id`](http://nomenclatures.id) |
| `nomenclature_name`     | text + .keyword | `ru_standard`                                            |
| `article`               | keyword         |                                                          |
| `quantity`              | integer         | Запрошено                                                |
| `received_quantity`     | integer         | Получено                                                 |
| `desired_delivery_date` | date            |                                                          |
| `created_at`            | date            |                                                          |

### 3\.5 `itech_digital_requests` -- ИТ-задачи

| Поле                        | Тип             | Описание                 |
|-----------------------------|-----------------|--------------------------|
| `id`                        | integer         | PK                       |
| `name`                      | text + .keyword | `ru_standard`            |
| `status`                    | keyword         | Статус                   |
| `importance`                | keyword         | Важность                 |
| `department_name`           | text + .keyword | Отдел-заказчик           |
| `plan_date_end_development` | date            | Плановая дата завершения |
| `fact_date_end_development` | date            | Фактическая дата         |
| `created_at`                | date            |                          |

---

## 4\. Схема связей между индексами

```
itech_projects ──── account_id ────► itech_accountsitech_projects ──── property_id ───► itech_propertiesitech_projects ──── manager_id ────► itech_users​itech_calculations ── project_id ──► itech_projectsitech_orders ──────── project_id ──► itech_projectsitech_order_items ─── order_id ────► itech_ordersitech_expected_payments ─ order_id ► itech_orders​itech_comments ──── project_id ────► itech_projectsitech_contacts ──── accounts[] ────► itech_accounts (nested)​itech_bom_components ── calculation_id ► itech_calculationsitech_purchase_items ─── nomenclature_id ► itech_nomenclatures
```

---

## 5\. Правила использования агентами

| Агент                | Индексы                                                                                      | Операции            |
|----------------------|----------------------------------------------------------------------------------------------|---------------------|
| Sync Agent           | Все 15                                                                                       | Запись (bulk index) |
| Quality Agent        | `itech_projects`, `itech_calculations`, `itech_accounts`                                     | Чтение, агрегации   |
| Recommendation Agent | `itech_projects`, `itech_accounts`, `itech_comments`, `itech_calculations`, `itech_contacts` | Чтение, fulltext    |
| Orchestrator         | `itech_projects`, `itech_users`                                                              | Чтение              |

---

## 6. Индексы, добавленные после v1.0
_Снято с живого OpenSearch (прод, сервер 147) 22 июля 2026. Схемы полей — из фактического `_mapping` индексов. Служебные поля `_sync_source` / `_synced_at` в таблицах опущены._

### 6.1 Операционный контур — новые `itech_*` (синк из Grace)

#### `itech_contracts` — Договоры с контрагентами (шапки)  
_Документов: 1 980_

| Поле | Тип |
|---|---|
| `account_id` | integer |
| `approval_status` | keyword |
| `approval_status_id` | integer |
| `assistant_name` | keyword |
| `assistant_user_id` | integer |
| `contact_id` | integer |
| `contract_end_date` | date |
| `contract_start_date` | date |
| `deadline` | date |
| `id` | integer |
| `manager_name` | keyword |
| `manager_user_id` | integer |
| `number` | keyword |
| `project_id` | integer |
| `signing_date` | date |
| `status_id` | integer |
| `type` | keyword |

#### `itech_contract_annexes` — Приложения/спецификации к договорам  
_Документов: 2 986_

| Поле | Тип |
|---|---|
| `amount` | double |
| `approval_status` | keyword |
| `contract_id` | integer |
| `currency_code` | keyword |
| `id` | integer |
| `number` | keyword |
| `order_number` | keyword |
| `project_id` | integer |
| `signing_date` | date |
| `start_date` | date |
| `status_id` | integer |
| `type` | keyword |

#### `itech_calculation_requests` — Заявки на расчёт — входящая очередь инженерам  
_Документов: 22 745_

| Поле | Тип |
|---|---|
| `account_id` | integer |
| `calculation_complexity` | integer |
| `created_at` | date |
| `description` | text + .keyword |
| `end_desired` | date |
| `end_plan` | date |
| `engineer_name` | keyword |
| `engineer_user_id` | integer |
| `estimated_time` | float |
| `id` | integer |
| `is_priority` | integer |
| `is_question` | integer |
| `manager_id` | integer |
| `manager_name` | keyword |
| `probability_percent` | float |
| `project_id` | integer |
| `project_path` | keyword |
| `property_id` | integer |
| `start_plan` | date |
| `status_id` | integer |
| `type_of_calc_id` | integer |
| `updated_at` | date |

#### `itech_calculation_remarks` — Замечания к расчётам  
_Документов: 41_

| Поле | Тип |
|---|---|
| `author_name` | keyword |
| `author_user_id` | integer |
| `calculation_engineer_user_id` | integer |
| `calculation_id` | integer |
| `created_at` | date |
| `engineer_name` | keyword |
| `id` | integer |
| `project_id` | integer |
| `remark` | text + .keyword |

#### `itech_services_requests` — Сервисные заявки (внутренние закупки/услуги)  
_Документов: 4 503_

| Поле | Тип |
|---|---|
| `account_id` | integer |
| `approval_status_id` | integer |
| `category` | text + .keyword |
| `cost` | long |
| `created_at` | date |
| `department_id` | integer |
| `department_name` | text + .keyword |
| `executor_name` | text + .keyword |
| `expenditure_item_id` | integer |
| `id` | integer |
| `order_number` | keyword |
| `purpose` | text + .keyword |
| `recipient_name` | text + .keyword |
| `status_id` | integer |

#### `itech_object_registrations` — Регистрации объектов за контрагентом (защита проекта)  
_Документов: 467_

| Поле | Тип |
|---|---|
| `account_id` | integer |
| `contact_id` | integer |
| `controller_name` | keyword |
| `controller_user_id` | integer |
| `created_at` | date |
| `id` | integer |
| `property_id` | integer |

#### `itech_quality_managers` — Снимки коэффициента качества Кк по менеджерам (витрина Quality Agent)  
_Документов: 41_

| Поле | Тип |
|---|---|
| `clean` | integer |
| `gap_count` | integer |
| `kk` | float |
| `manager` | keyword |
| `snapshot_date` | date |
| `stale_count` | long |
| `total` | integer |
| `with_gaps` | integer |

#### `itech_activity_log` — Журнал изменений сущностей (аудит воронки)  
_Документов: 15 868_

| Поле | Тип |
|---|---|
| `account_id` | integer |
| `account_name` | text + .keyword |
| `action` | keyword |
| `amount` | double |
| `causer_name` | text + .keyword |
| `causer_user_id` | integer |
| `changed_fields` | keyword |
| `changes_text` | text |
| `created_at` | date |
| `created_year` | integer |
| `engineer_name` | text + .keyword |
| `engineer_user_id` | integer |
| `entity_id` | integer |
| `entity_type` | keyword |
| `forecast_date` | date |
| `id` | long |
| `manager_name` | text + .keyword |
| `manager_user_id` | integer |
| `probability_percent` | float |
| `project_id` | integer |
| `status_id` | integer |
| `status_name` | keyword |

#### `itech_reminders` — Напоминания менеджерам (индекс создан, данных пока нет)  
_Документов: 0_

| Поле | Тип |
|---|---|
| `by_email` | boolean |
| `by_grace` | boolean |
| `by_telegram` | boolean |
| `created_at` | date |
| `entity_id` | integer |
| `entity_type` | keyword |
| `id` | integer |
| `is_expired` | boolean |
| `manager_id` | integer |
| `manager_name` | text + .keyword |
| `pre_notifications` | keyword |
| `remind_date` | date |
| `result` | text + .keyword |
| `status` | keyword |
| `text` | text + .keyword |

### 6.2 Продуктовый каталог — `itech_vendor_price_lists`
Прайс-листы вендоров по артикулам — крупнейший индекс каталога.  
_Документов: 658 642_

| Поле | Тип |
|---|---|
| `article` | keyword |
| `brand_id` | keyword |
| `currency` | keyword |
| `effective_date` | date |
| `family` | text + .keyword |
| `name` | text |
| `price` | double |
| `price_list_id` | keyword |
| `source` | keyword |
| `unit` | keyword |
| `vendor` | keyword |

### 6.3 Аналитический слой — витрины `*_v1` (в v1.0 отсутствовал)
Считаются **у нас** (не синк из Grace): модель конверсии сделок (агент Quality) и поиск похожих проектов (агент Recommendation).

#### `deal_conversion_training_v1` — Обучающая выборка модели конверсии сделок (признаки + метка `converted`)  
_Документов: 8 648_

| Поле | Тип |
|---|---|
| `account_id` | keyword |
| `amount` | double |
| `comment_avg_gap_days` | double |
| `comment_count` | double |
| `comment_distinct_authors` | double |
| `comment_max_gap_days` | double |
| `comment_span_days` | double |
| `comments_before_forecast` | double |
| `comments_per_week` | double |
| `company_id` | keyword |
| `complexity` | double |
| `converted` | boolean |
| `created_at` | date |
| `created_year` | double |
| `days_created_to_forecast` | double |
| `days_forecast_to_first_order` | double |
| `days_since_last_comment` | double |
| `first_order_created_at` | date |
| `first_order_id` | long |
| `forecast_date` | date |
| `important` | keyword |
| `is_sales_plan` | keyword |
| `label` | integer |
| `manager_id` | keyword |
| `manager_name` | keyword |
| `probability_source` | keyword |
| `probability_value` | double |
| `project_age_days` | double |
| `project_id` | long |
| `project_name` | keyword |
| `project_status` | keyword |
| `project_status_id` | keyword |
| `property_id` | keyword |
| `sector` | keyword |
| `type_of_calculation` | keyword |

#### `deal_conversion_predictions_v1` — Предсказания вероятности конверсии (модель против оценки менеджера)  
_Документов: 1 255_

| Поле | Тип |
|---|---|
| `as_of_date` | date |
| `created_at` | date |
| `features` | object |
| `forecast_date` | date |
| `manager_id` | keyword |
| `manager_name` | keyword |
| `manager_probability` | double |
| `model_name` | keyword |
| `predicted_probability` | double |
| `probability_delta` | double |
| `project_id` | long |
| `project_name` | keyword |
| `project_status` | keyword |

#### `project_similarity_embeddings_v1` — Эмбеддинги проектов (`knn_vector`: content + structured) для поиска похожих  
_Документов: 20 371_

| Поле | Тип |
|---|---|
| `account_id` | keyword |
| `account_name` | text + .keyword |
| `amount` | double |
| `amount_log` | float |
| `comment_count` | integer |
| `comment_count_log` | float |
| `comment_span_days` | float |
| `comments_per_week` | double |
| `content_embedding` | knn_vector |
| `content_hash` | keyword |
| `content_text` | text |
| `created_at` | date |
| `created_year` | integer |
| `days_since_last_comment` | float |
| `embedding_dimensions` | integer |
| `embedding_model` | keyword |
| `embedding_provider` | keyword |
| `execution_days` | double |
| `first_order_created_at` | date |
| `first_order_id` | long |
| `forecast_date` | date |
| `forecast_horizon_days` | double |
| `has_order` | boolean |
| `has_order_value` | double |
| `manager_id` | keyword |
| `manager_name` | keyword |
| `order_item_count` | integer |
| `order_item_count_log` | float |
| `probability` | double |
| `project_age_days` | double |
| `project_id` | long |
| `project_name` | text + .keyword |
| `project_status` | keyword |
| `project_status_id` | keyword |
| `property_id` | keyword |
| `property_name` | text + .keyword |
| `sector` | keyword |
| `structured_vector` | knn_vector |
| `type_of_calculation` | keyword |

#### `project_similarity_vectors_v1` — Векторы сходства проектов (`knn_vector`)  
_Документов: 20 356_

| Поле | Тип |
|---|---|
| `account_id` | keyword |
| `account_name` | text + .keyword |
| `amount` | double |
| `amount_log` | float |
| `comment_count` | integer |
| `comment_count_log` | float |
| `comment_span_days` | float |
| `comments_per_week` | double |
| `content_hash` | keyword |
| `content_text` | text |
| `content_vector` | knn_vector |
| `created_at` | date |
| `created_year` | integer |
| `days_since_last_comment` | float |
| `execution_days` | double |
| `first_order_created_at` | date |
| `first_order_id` | long |
| `forecast_date` | date |
| `forecast_horizon_days` | double |
| `has_order` | boolean |
| `has_order_value` | double |
| `manager_id` | keyword |
| `manager_name` | keyword |
| `order_item_count` | integer |
| `order_item_count_log` | float |
| `probability` | double |
| `project_age_days` | double |
| `project_id` | long |
| `project_name` | text + .keyword |
| `project_status` | keyword |
| `project_status_id` | keyword |
| `property_id` | keyword |
| `property_name` | text + .keyword |
| `sector` | keyword |
| `structured_vector` | knn_vector |
| `type_of_calculation` | keyword |

#### `project_similarity_cards_v1` — Карточки проектов для выдачи похожих (токенизированные)  
_Документов: 20 353_

| Поле | Тип |
|---|---|
| `account_id` | keyword |
| `account_name` | text + .keyword |
| `amount` | double |
| `amount_log` | double |
| `created_at` | date |
| `created_year` | integer |
| `execution_days` | double |
| `first_order_created_at` | date |
| `first_order_id` | long |
| `forecast_date` | date |
| `forecast_horizon_days` | double |
| `has_order` | boolean |
| `manager_id` | keyword |
| `manager_name` | keyword |
| `order_item_count` | integer |
| `probability` | double |
| `project_age_days` | double |
| `project_id` | long |
| `project_name` | text + .keyword |
| `project_status` | keyword |
| `project_status_id` | keyword |
| `property_id` | keyword |
| `property_name` | text + .keyword |
| `sector` | keyword |
| `token_text` | text |
| `tokens` | keyword |
| `type_of_calculation` | keyword |

#### `project_similarity_comment_drafts_v1` — Черновики рекомендательных комментариев (`nested` similar_projects)  
_Документов: 426_

| Поле | Тип |
|---|---|
| `comment_text` | text |
| `created_at` | date |
| `draft_id` | keyword |
| `send_result` | object |
| `sent_at` | date |
| `similar_projects` | nested |
| `source` | keyword |
| `status` | keyword |
| `target_project_id` | long |
| `target_project_name` | keyword |

# Схема интеграции Grace CRM → OpenSearch

**Версия:** 1\.0 **Дата:** 4 мая 2026

**Статус:** Этап 0 -- согласование файл 02_integration\_[schema.md](http://schema.md)

---

## 1\. Архитектура интеграции

Grace CRM (MySQL) не подключается к OpenSearch напрямую. Синхронизация осуществляется через Sync Agent -- Agno-агент, запускаемый по расписанию или вручную.

```
Grace CRM (MySQL)    │    │  REST API (GET-запросы)    ▼CLI-команда → Sync Agent (Agno)    │    │  Трансформация данных    │  (нормализация, денормализация, обогащение)    ▼OpenSearch (bulk index)    │    ├── itech_projects    ├── itech_accounts    ├── itech_calculations    ├── itech_orders    ├── itech_order_items    ├── itech_comments    ├── itech_contacts    ├── itech_properties    ├── itech_expected_payments    └── ... (15 индексов)
```

**Важно:** прямого доступа к MySQL Grace CRM у Sync Agent нет. Все данные получаются только через REST API Grace CRM.

---

## 2\. Механизм запуска

### 2\.1 CLI-команда

```
# Инкрементальная синхронизация (основной режим)grace-sync run --mode incremental​# Полная синхронизация (ночная / восстановление)grace-sync run --mode full​# Синхронизация конкретной сущностиgrace-sync run --entity projects --mode incremental​# Ручной запуск с указанием временного окнаgrace-sync run --mode incremental --since 2026-05-01T00:00:00
```

### 2\.2 Расписание (cron)

| Режим           | Расписание                   | Описание                       |
|-----------------|------------------------------|--------------------------------|
| Инкрементальный | Каждые 15 минут              | Основной рабочий режим         |
| Полный          | Ежедневно в 02:00            | Восстановление консистентности |
| Ручной          | По требованию администратора | После миграций, исправлений    |

---

## 3\. Сущности и endpoints API

| Сущность        | Endpoint                                    | Индекс OpenSearch         | Частота    |
|-----------------|---------------------------------------------|---------------------------|------------|
| Сделки          | `GET /api/projects?updated_since=`          | `itech_projects`          | 15 мин     |
| Контрагенты     | `GET /api/clients?updated_since=`           | `itech_accounts`          | 15 мин     |
| Расчёты (КП)    | `GET /api/calculations?updated_since=`      | `itech_calculations`      | 15 мин     |
| Заказы          | `GET /api/orders?updated_since=`            | `itech_orders`            | 15 мин     |
| Позиции заказов | `GET /api/order_items?updated_since=`       | `itech_order_items`       | 15 мин     |
| Активности      | `GET /api/activities?updated_since=`        | `itech_comments`          | 15 мин     |
| Задачи          | `GET /api/tasks?updated_since=`             | (в `itech_projects`)      | 15 мин     |
| Контактные лица | `GET /api/contacts?updated_since=`          | `itech_contacts`          | 1 час      |
| Объекты         | `GET /api/objects?updated_since=`           | `itech_properties`        | 1 час      |
| Платежи         | `GET /api/expected_payments?updated_since=` | `itech_expected_payments` | 1 час      |
| Пользователи    | `GET /api/users`                            | `itech_users`             | 1 раз/день |

---

## 4\. Режимы синхронизации

### 4\.1 Инкрементальный режим

**Принцип:** запрашиваются только записи, изменённые с момента последней синхронизации.

```
1. Читаем last_sync_timestamp из хранилища состояния2. GET /api/{entity}?updated_since={last_sync_timestamp}3. Трансформируем полученные записи4. Bulk upsert в OpenSearch (upsert по id)5. Обновляем last_sync_timestamp = текущее время
```

**Хранение состояния:** файл `sync_state.json` или переменная окружения. Формат:

```
{  "projects": "2026-05-04T08:45:00",  "clients": "2026-05-04T08:45:00",  "orders": "2026-05-04T08:45:00"}
```

### 4\.2 Полный режим

**Принцип:** полная выгрузка всех сущностей с пагинацией, полная пересборка индексов.

```
1. Создаём новый индекс с суффиксом _tmp2. Загружаем все данные через API с пагинацией (batch по 500 записей)3. После успешной загрузки — переключаем алиас4. Удаляем старый индекс
```

**Применяется при:** первоначальном развёртывании, восстановлении после сбоя, изменении маппинга.

---

## 5\. Трансформация данных

### 5\.1 Денормализация

При индексации данные обогащаются связанными сущностями во избежание JOIN-запросов в OpenSearch:

```
projects → добавляем account_name, manager_name, property_name, project_status (название)orders   → добавляем account_name, manager_name, company_namecomments → добавляем project_name, project_status, account_name, manager_name
```

### 5\.2 Вычисляемые поля

| Поле          | Индекс                              | Формула                                                           |
|---------------|-------------------------------------|-------------------------------------------------------------------|
| `is_shipped`  | `itech_orders`, `itech_order_items` | `shipping_date_fact IS NOT NULL`                                  |
| `revenue_mln` | `itech_accounts`                    | `SUM(order_items.amount) / 1 000 000`                             |
| `debt_mln`    | `itech_accounts`                    | `SUM(expected_payments где paid_amount < pay_amount) / 1 000 000` |
| `order_count` | `itech_accounts`                    | `COUNT(`[`orders.id`](http://orders.id)`)`                        |
| `top_account` | `itech_properties`                  | Контрагент с наибольшим числом проектов на объекте                |

### 5\.3 Нормализация данных

-  Имена менеджеров: нормализация пробелов, удаление неразрывных пробелов (`\xa0`)

-  Даты: приведение к формату `yyyy-MM-dd HH:mm:ss`

-  Суммы: `NULL` -> `0.0`

-  Булевы поля: `0/1` -> `false/true`

---

## 6\. Обработка конфликтов и ошибок

### 6\.1 Стратегия при конфликте версий

**Правило:** последнее изменение по `updated_at` побеждает.

```
# При upsert в OpenSearch{  "doc": { ...новые поля... },  "doc_as_upsert": True}
```

Если `updated_at` в новой записи меньше, чем в существующей -- запись не обновляется (idempotent операция).

### 6\.2 Обработка ошибок API

| Ситуация                  | Поведение                                 |
|---------------------------|-------------------------------------------|
| HTTP 429 (rate limit)     | Пауза 60 сек, повтор                      |
| HTTP 5xx (ошибка сервера) | Retry 3 раза с экспоненциальной задержкой |
| HTTP 404 (запись удалена) | Удаление из OpenSearch                    |
| Таймаут соединения        | Retry 3 раза, затем запись в лог ошибок   |
| Частичный сбой батча      | Повтор только ошибочных записей           |

### 6\.3 Логирование

Каждый запуск синхронизации фиксирует:

```
{  "run_id": "uuid",  "mode": "incremental",  "started_at": "2026-05-04T09:00:00",  "finished_at": "2026-05-04T09:00:23",  "entities": {    "projects": { "fetched": 42, "indexed": 42, "errors": 0 },    "orders": { "fetched": 7, "indexed": 7, "errors": 0 }  },  "status": "success"}
```

---

## 7\. Мониторинг и алерты

| Метрика                       | Пороговое значение     | Действие                    |
|-------------------------------|------------------------|-----------------------------|
| Время последней синхронизации | \> 30 минут назад      | Алерт администратору        |
| Количество ошибок за запуск   | \> 5% от batch         | Алерт + запись в лог        |
| Расхождение счётчиков         | Индекс \< 90% от MySQL | Запуск полной синхронизации |
| Недоступность API Grace       | \> 3 неудачных попытки | Алерт + пауза 10 минут      |

---

## 8\. Требования к API Grace CRM

Для корректной работы интеграции API Grace CRM должен поддерживать:

| Требование                   | Параметр                 | Обязательно                 |
|------------------------------|--------------------------|-----------------------------|
| Фильтрация по дате изменения | `?updated_since=ISO8601` | Да                          |
| Пагинация                    | `?page=N&per_page=500`   | Да                          |
| Получение записи по ID       | `GET /{entity}/{id}`     | Да                          |
| Аутентификация               | API-ключ в заголовке     | Да                          |
| Rate limit                   | Информация о лимитах     | Да (для настройки задержек) |

<note type="quote">

**Открытый вопрос:** наличие webhooks в API Grace CRM уточняется на Этапе 0. При наличии webhooks -- добавить режим event-driven синхронизации в дополнение к cron-polling.

</note>

# Ролевая модель (RBAC) — Grace CRM Assistant

**Версия:** 1\.0 **Дата:** 4 мая 2026

**Статус:** Этап 0 -- согласование файл 04\_[rbac.md](http://rbac.md)

---

## 1\. Принципы ролевой модели

-  **Минимальные права:** каждая роль получает только те права, которые необходимы для выполнения её функции

-  **Изоляция данных:** менеджер видит только свои проекты и клиентов

-  **Конфиденциальность премий:** данные о расчёте премии (Кк) видны только самому менеджеру и его непосредственному руководителю (РОП)

-  **Наследование:** роли не наследуются, каждая назначается явно

-  **Аудит:** все действия фиксируются в audit log с timestamp и user_id

---

## 2\. Роли системы

### 2\.1 Контур Sales AI

| Роль                       | ID          | Назначение                                            |
|----------------------------|-------------|-------------------------------------------------------|
| Менеджер по продажам       | `manager`   | Работа со своими проектами, рекомендации, уведомления |
| Руководитель отдела продаж | `rop`       | Мониторинг команды, эскалации, аналитика по отделу    |
| Заместитель ГД             | `deputy_gd` | Стратегическая аналитика, агрегированные данные       |
| Администратор системы      | `admin`     | Управление системой, конфиг, синхронизация            |

### 2\.2 Контур Knowledge AI

| Роль                         | ID                  | Назначение                                   |
|------------------------------|---------------------|----------------------------------------------|
| Ответственный за базу знаний | `knowledge_manager` | Загрузка документов, управление базой знаний |
| Читатель базы знаний         | `knowledge_reader`  | Поиск и просмотр документов                  |

### 2\.3 Системные роли

| Роль                 | ID       | Назначение                               |
|----------------------|----------|------------------------------------------|
| Системный интегратор | `system` | Межсистемное взаимодействие (API-to-API) |

---

## 3\. Матрица прав доступа

### 3\.1 Данные CRM

| Объект                          | manager | rop | deputy_gd | admin |
|---------------------------------|---------|-----|-----------|-------|
| Свои проекты (просмотр)         | ✅       | ✅   | ✅         | ✅     |
| Все проекты команды (просмотр)  | ❌       | ✅   | ✅         | ✅     |
| Все проекты компании (просмотр) | ❌       | ❌   | ✅         | ✅     |
| Свои клиенты (просмотр)         | ✅       | ✅   | ✅         | ✅     |
| Все клиенты (просмотр)          | ❌       | ✅   | ✅         | ✅     |
| Комментарии по своим проектам   | ✅       | ✅   | ✅         | ✅     |
| Комментарии по всем проектам    | ❌       | ✅   | ✅         | ✅     |

### 3\.2 Рекомендации

| Действие                                | manager | rop | deputy_gd | admin |
|-----------------------------------------|---------|-----|-----------|-------|
| Получать рекомендации по своим проектам | ✅       | ✅   | ❌         | ✅     |
| Просматривать рекомендации по команде   | ❌       | ✅   | ❌         | ✅     |
| Подтверждать выполнение рекомендации    | ✅       | ✅   | ❌         | ✅     |
| Запрашивать рекомендацию вручную        | ✅       | ✅   | ❌         | ✅     |

### 3\.3 Аналитика

| Объект                            | manager | rop | deputy_gd | admin |
|-----------------------------------|---------|-----|-----------|-------|
| Своя воронка продаж               | ✅       | ✅   | ✅         | ✅     |
| Воронка по команде                | ❌       | ✅   | ✅         | ✅     |
| Агрегированная аналитика компании | ❌       | ❌   | ✅         | ✅     |
| Свой коэффициент качества (Кк)    | ✅       | ✅   | ❌         | ✅     |
| Кк по команде                     | ❌       | ✅   | ❌         | ✅     |
| Кк агрегированно по отделу        | ❌       | ❌   | ✅         | ✅     |
| Свой прогноз премии               | ✅       | ✅   | ❌         | ✅     |
| Прогноз премии по команде         | ❌       | ✅   | ❌         | ✅     |
| Прогноз премии по всему отделу    | ❌       | ❌   | ❌         | ✅     |

<note type="quote">

**Примечание:** Зам. ГД видит только агрегированные данные по отделу, без персональных показателей менеджеров.

</note>

### 3\.4 База знаний

| Действие                  | manager | rop | deputy_gd | knowledge_manager | admin |
|---------------------------|---------|-----|-----------|-------------------|-------|
| Поиск по базе знаний      | ✅       | ✅   | ✅         | ✅                 | ✅     |
| Просмотр документов       | ✅       | ✅   | ✅         | ✅                 | ✅     |
| Загрузка документов       | ❌       | ❌   | ❌         | ✅                 | ✅     |
| Редактирование документов | ❌       | ❌   | ❌         | ✅                 | ✅     |
| Удаление документов       | ❌       | ❌   | ❌         | ✅                 | ✅     |
| Запуск Lint Agent (аудит) | ❌       | ❌   | ❌         | ✅                 | ✅     |

### 3\.5 Управление системой

| Действие                                | manager | rop | deputy_gd | knowledge_manager | admin |
|-----------------------------------------|---------|-----|-----------|-------------------|-------|
| Запуск синхронизации                    | ❌       | ❌   | ❌         | ❌                 | ✅     |
| Просмотр статуса синхронизации          | ❌       | ❌   | ❌         | ❌                 | ✅     |
| Изменение правил проверки Quality Agent | ❌       | ❌   | ❌         | ❌                 | ✅     |
| Изменение SLA-параметров                | ❌       | ❌   | ❌         | ❌                 | ✅     |
| Просмотр audit log                      | ❌       | ❌   | ❌         | ❌                 | ✅     |
| Управление пользователями и ролями      | ❌       | ❌   | ❌         | ❌                 | ✅     |

### 3\.6 Уведомления

| Действие                                                 | manager | rop | deputy_gd | admin |
|----------------------------------------------------------|---------|-----|-----------|-------|
| Получать уведомления о своих проектах                    | ✅       | ✅   | ❌         | ✅     |
| Получать сводку по команде                               | ❌       | ✅   | ✅         | ✅     |
| Получать эскалации                                       | ❌       | ✅   | ✅         | ✅     |
| Настраивать предпочтительный канал (Mattermost/Telegram) | ✅       | ✅   | ✅         | ✅     |

---

## 4\. Изоляция данных: правила фильтрации

### Менеджер (role: manager)

```
projects WHERE manager_id = {current_user_id}
accounts WHERE manager_id = {current_user_id}
  OR assistant_user_id = {current_user_id}
recommendations WHERE manager_id = {current_user_id}
kk_score WHERE manager_id = {current_user_id}
bonus_forecast WHERE manager_id = {current_user_id}
```

### РОП (role: rop)

```
projects WHERE manager_id IN (
  SELECT id FROM users WHERE department_id = {rop_department_id}
)
-- или конфигурируемый список подчинённых менеджеров
```

### Зам. ГД (role: deputy_gd)

```
-- Только агрегированные данные, без персональных показателей
SELECT COUNT(*), SUM(amount), AVG(probability_percent)
FROM projects
-- без разбивки по конкретным менеджерам в разделе премий
```

---

## 5\. Назначение ролей

### 5\.1 Текущее назначение (I-TECH)

| Пользователь                 | Роль в Grace CRM                 | Роль в AI-системе   |
|------------------------------|----------------------------------|---------------------|
| Менеджеры отдела продаж      | Продажи                          | `manager`           |
| Руководитель отдела продаж   | РОП                              | `rop`               |
| Заместитель ГД по развитию   | Зам. ГД                          | `deputy_gd`         |
| Дмитрий Калдарбеков          | Руководитель отдела цифровизации | `admin`             |
| Ответственный за базу знаний | --                               | `knowledge_manager` |

### 5\.2 Правила назначения

-  Роль назначается администратором системы

-  Один пользователь может иметь несколько ролей (например, `rop` + `knowledge_reader`)

-  Назначение ролей фиксируется в audit log

-  Роли синхронизируются с учётными записями Grace CRM (при наличии SSO/LDAP)

---

## 6\. Аутентификация

### 6\.1 Режимы

| Режим               | Применение                             |
|---------------------|----------------------------------------|
| SSO через Grace CRM | Основной режим для сотрудников I-TECH  |
| JWT Bearer Token    | Межсистемные интеграции (1С, BI, ERP)  |
| API Key             | Системные интеграторы (`role: system`) |

### 6\.2 Параметры JWT

| Параметр      | Значение                                     |
|---------------|----------------------------------------------|
| Алгоритм      | RS256                                        |
| Срок действия | 8 часов (рабочая смена)                      |
| Refresh token | 30 дней                                      |
| Payload       | `user_id`, `roles[]`, `department_id`, `exp` |

---

## 7\. Audit Log

Все действия пользователей фиксируются со следующими полями:

| Поле            | Описание                                                |
|-----------------|---------------------------------------------------------|
| `timestamp`     | Дата и время события                                    |
| `user_id`       | ID пользователя                                         |
| `user_role`     | Роль на момент действия                                 |
| `action`        | Тип действия (READ / WRITE / DELETE / SYNC / LOGIN)     |
| `resource_type` | Тип объекта (project / recommendation / document / ...) |
| `resource_id`   | ID объекта                                              |
| `ip_address`    | IP-адрес запроса                                        |
| `result`        | success / forbidden / error                             |

**Обязательно логируются:**

-  Просмотр данных о премиях и Кк

-  Загрузка и удаление документов из базы знаний

-  Запуск синхронизации

-  Изменение конфигурации

-  Назначение и изменение ролей

-  Все неудачные попытки авторизации

**Хранение:** audit log хранится 12 месяцев, доступен только `admin`.

# Реестр критических данных и правила контроля качества

файл 05_critical\_[data.md](http://data.md)

## 1\. Назначение

Данный документ определяет перечень критических данных в Grace CRM, подлежащих обязательной проверке Quality Agent, а также правила контроля качества:

-  допустимые форматы

-  условия полноты

-  логика выявления пробелов

Цель: обеспечить достоверность аналитики и корректную работу Recommendation Agent.

---

## 2\. Принципы контроля качества

-  Проверяются только активные проекты

-  Каждое правило имеет уровень критичности (Critical / Warning)

-  Нарушение Critical -> обязательная эскалация

-  Нарушение Warning -> уведомление без эскалации

---

## 3\. Реестр объектов и полей

### 3\.1 Проекты (itech_projects)

| Поле                | Тип     | Обязательность | Формат     | Правило проверки | Критичность |
|---------------------|---------|----------------|------------|------------------|-------------|
| account_id          | integer | Обязательно    | \>0        | Не NULL          | Critical    |
| project_status_id   | integer | Обязательно    | \>0        | Не NULL          | Critical    |
| probability_percent | integer | Обязательно    | 0–100      | Не NULL          | Critical    |
| forecast_date       | date    | Обязательно    | YYYY-MM-DD | Не NULL, ≥ today | Critical    |
| next_action         | text    | Обязательно    | строка     | Не пусто         | Critical    |
| next_action_date    | date    | Обязательно    | YYYY-MM-DD | ≥ today          | Critical    |
| last_activity_at    | date    | Обязательно    | дата       | ≤ 30 дней        | Warning     |

---

### 3\.2 Контрагенты (itech_accounts)

| Поле        | Тип     | Обязательность | Формат     | Правило проверки | Критичность |
|-------------|---------|----------------|------------|------------------|-------------|
| name        | text    | Обязательно    | строка     | Не пусто         | Critical    |
| inn         | keyword | Обязательно    | 10/12 цифр | regex            | Critical    |
| manager_id  | integer | Обязательно    | \>0        | Не NULL          | Critical    |
| reliability | keyword | Желательно     | enum       | red/yellow/green | Warning     |

---

### 3\.3 Активности / комментарии (itech_comments)

| Поле       | Тип  | Обязательность | Формат | Правило проверки | Критичность |
|------------|------|----------------|--------|------------------|-------------|
| comment    | text | Обязательно    | строка | длина > 10       | Warning     |
| created_at | date | Обязательно    | дата   | не NULL          | Critical    |

---

### 3\.4 Расчёты (itech_calculations)

| Поле               | Тип     | Обязательность | Формат | Правило проверки | Критичность |
|--------------------|---------|----------------|--------|------------------|-------------|
| project_id         | integer | Обязательно    | \>0    | Не NULL          | Critical    |
| calculation_status | keyword | Обязательно    | enum   | Не NULL          | Critical    |
| amount             | double  | Обязательно    | \>0    | \>0              | Warning     |

---

## 4\. Логика выявления пробелов

### 4\.1 Отсутствие обязательных полей

```
IF field IS NULL → ошибка
```

---

### 4\.2 Нарушение бизнес-логики

Примеры:

-  Статус "КП отправлено" -> должен существовать расчёт

-  Есть проект -> должен быть следующий шаг

```
IF status = "КП отправлено" AND calculations = 0 → ошибка
```

---

### 4\.3 Просроченные действия

```
IF next_action_date < today → ошибка
```

---

### 4\.4 Отсутствие активности

```
IF last_activity_at > 30 дней → warning
```

---

## 5\. Расчёт Кк (коэффициента качества данных)

```
Кк=1−(проектысошибками/общееколичествопроектов)
```

Где:

-  ошибка = любое нарушение Critical

---

## 6\. Выход Quality Agent

Формируется реестр:

<table header="row">
<tr>
<td>

Проект

</td>
<td>

Поле

</td>
<td>

Ошибка

</td>
<td>

Ответственный

</td>
<td>

Срок

</td>
</tr>
</table>

---

## 7\. Эскалации

| Условие           | Действие              |
|-------------------|-----------------------|
| Ошибка Critical   | уведомление менеджеру |
| Нет реакции > SLA | эскалация РОП         |
| Повторная ошибка  | эскалация Зам. ГД     |

---

## 8\. Расширение реестра

-  Новые правила добавляются через конфиг

-  Без изменения кода агентов

---

# Карточки агентов — продуктовый подход

#### Приложение 6. Карточки агентов -- продуктовый подход

#### к Акту сдачи-приёмки работ по Этапу 0

**Проект:** Grace CRM Assistant **Договор:** №04-002 от 24.04.2026 **Исполнитель:** ООО «Экобанкинг» **Заказчик:** ООО «АйТек»

---

## О методе описания

Каждый агент описан через продуктовую формулу:

<note type="quote">

**Продукт** -- что конкретно производит агент **Внутренний клиент** -- кто получает этот продукт (роль или другой агент) **Триггер** -- при каком условии агент запускается **Критерий выполнения** -- как проверить, что агент выполнил свою функцию

</note>

Такой подход позволяет однозначно определить границы каждого агента, порядок их взаимодействия и критерии приёмки на каждом этапе разработки.

---

## Контур 1 -- Sales AI (Grace CRM Assistant)

---

### Агент 1. Sync Agent -- Агент синхронизации

**Продукт:**

<note type="quote">

Актуальный поисковый образ данных Grace CRM в OpenSearch -- гарантирующий, что любой запрос от downstream-агентов отражает реальное состояние CRM на момент последнего запуска.

</note>

| Элемент                 | Содержание                                                                                            |
|-------------------------|-------------------------------------------------------------------------------------------------------|
| **Внутренний клиент**   | Quality Agent, Recommendation Agent                                                                   |
| **Механизм**            | CLI -> API Grace CRM -> трансформация -> bulk index в OpenSearch                                      |
| **Триггер**             | Cron по расписанию + ручной запуск администратором                                                    |
| **Входные данные**      | API Grace CRM: projects, activities, clients, tasks, comments, calculations, orders, users, objects   |
| **Выходной продукт**    | Обновлённые индексы OpenSearch (15 индексов)                                                          |
| **Критерий выполнения** | Все индексы обновлены без ошибок; расхождение Grace CRM / OpenSearch = 0 по завершении синхронизации  |
| **Красный флаг**        | Ошибка синхронизации -> downstream-агенты работают на устаревших данных -> все рекомендации невалидны |

**Режимы работы:**

| Режим           | Триггер                           | Что синхронизируется                             |
|-----------------|-----------------------------------|--------------------------------------------------|
| Инкрементальный | Cron каждые 15 минут              | Изменения с последнего запуска (`updated_since`) |
| Полный          | Ежедневно в 02:00 / ручной запуск | Все сущности, полная пересборка индексов         |

**Цепочка ответственности:**

```
Grace CRM (source of truth)    ↓ APISync Agent    ↓ bulk indexOpenSearch (15 индексов) → Quality Agent, Recommendation Agent
```

---

### Агент 2. Quality Agent -- Агент контроля качества данных

**Продукт:**

<note type="quote">

Ежедневный реестр проектов с критическими пробелами данных -- для менеджеров и РОПа -- с указанием конкретного поля, ответственного и срока устранения.

</note>

| Элемент                 | Содержание                                                                                            |
|-------------------------|-------------------------------------------------------------------------------------------------------|
| **Внутренний клиент 1** | Менеджер -- получает задачу на заполнение по своим проектам                                           |
| **Внутренний клиент 2** | РОП -- получает сводку по команде и эскалацию при просрочке                                           |
| **Триггер**             | Ежедневно в 09:00 + при изменении статуса проекта                                                     |
| **Входные данные**      | OpenSearch: `itech_projects`, `itech_calculations`; правила проверки из конфига                       |
| **Выходной продукт**    | Структурированный реестр: проект -> пробел -> ответственный -> срок; сигнал в Notification Agent      |
| **Критерий выполнения** | Доля проектов с полными данными ≥ 85% (вектор роста); каждый пробел имеет назначенного ответственного |

**Правила проверки (настраиваются в конфиге без релиза):**

| Проверка          | Поле                                                                                 | Условие нарушения                                 |
|-------------------|--------------------------------------------------------------------------------------|---------------------------------------------------|
| Обязательные поля | `account_id`, `property_id`, `project_status_id`, `probability_new`, `forecast_date` | Пусто                                             |
| Следующий шаг     | `next_action_date`                                                                   | Пусто или дата в прошлом                          |
| Логика статусов   | `calculation_status`                                                                 | При статусе «КП выставлено» -- расчёт отсутствует |
| Активность        | `last_activity_at`                                                                   | Более 30 дней назад для активного проекта         |

---

### Агент 3. Recommendation Agent -- Агент рекомендаций

**Продукт:**

<note type="quote">

Конкретный следующий шаг по каждому активному проекту -- для менеджера -- сформулированный на основе истории CRM и базы знаний RAGflow, доставляемый не позднее 2 часов после изменения статуса или по запросу.

</note>

| Элемент                 | Содержание                                                                                                       |
|-------------------------|------------------------------------------------------------------------------------------------------------------|
| **Внутренний клиент**   | Менеджер (первично); РОП (при просрочке реакции менеджера)                                                       |
| **Триггер**             | Изменение статуса проекта / запрос менеджера / просрочка контакта                                                |
| **Входные данные**      | OpenSearch: история проекта, активности, комментарии; RAGflow: кейсы, скрипты, возражения                        |
| **Выходной продукт**    | Рекомендация: действие + срок + обоснование + ссылка на кейс из базы знаний                                      |
| **Критерий выполнения** | Менеджер знает следующий шаг по каждому активному проекту; нет проектов без зафиксированного следующего действия |
| **Вектор роста**        | Снижение доли проектов без следующего шага; рост конверсии КП -> заказ                                           |

**Формат рекомендации:**

```
Проект: [название] | Клиент: [название] | Стадия: [статус]
Последний контакт: N дней назад

Рекомендация: [конкретное действие]
Срок: [дата]
Обоснование: [краткое обоснование на основе истории]
Похожий кейс: [ссылка из базы знаний RAGflow]
```

---

### Агент 4. Notification Agent -- Агент уведомлений

**Продукт:**

<note type="quote">

Адресное уведомление нужному человеку в нужный момент через нужный канал -- без информационного шума -- как условие того, что сигналы системы реально доходят и вызывают реакцию.

</note>

| Элемент                 | Содержание                                                                                                 |
|-------------------------|------------------------------------------------------------------------------------------------------------|
| **Внутренний клиент**   | Менеджер / РОП / Зам. ГД -- в зависимости от типа события                                                  |
| **Триггер**             | Сигнал от любого агента системы                                                                            |
| **Входные данные**      | Сигнал от агента + профиль получателя (предпочтительный канал)                                             |
| **Выходной продукт**    | Доставленное уведомление с подтверждённой реакцией                                                         |
| **Механизм доставки**   | Adapter pattern: Mattermost (основной) / Telegram (резерв), канал настраивается per-user                   |
| **Критерий выполнения** | Реакция (действие или подтверждение) в течение N часов; при отсутствии реакции -- эскалация в Orchestrator |
| **Красный флаг**        | Уведомление без реакции сверх SLA -> передаётся Orchestrator для эскалации                                 |

**Матрица маршрутизации:**

| Событие                                                  | Получатель   | Приоритет  |
|----------------------------------------------------------|--------------|------------|
| Пробел в данных по своему проекту                        | Менеджер     | Нормальный |
| Рекомендация по проекту                                  | Менеджер     | Нормальный |
| Просрочка реакции менеджера > SLA                        | РОП          | Высокий    |
| Критическое событие (крупная сделка, риск ухода клиента) | РОП, Зам. ГД | Высокий    |
| Ежедневная сводка по команде                             | РОП          | Плановый   |

---

### Агент 5. Orchestrator -- Оркестратор

**Продукт:**

<note type="quote">

Бесперебойная работа агентной системы как единого целого -- для РОПа и Зам. ГД -- обеспечивающая, что ни одно критическое событие не теряется и каждый сигнал доходит до нужного человека в нужное время.

</note>

| Элемент                 | Содержание                                                                                           |
|-------------------------|------------------------------------------------------------------------------------------------------|
| **Внутренний клиент**   | РОП, Зам. ГД                                                                                         |
| **Триггер**             | Постоянно -- реагирует на сигналы всех агентов                                                       |
| **Входные данные**      | Сигналы от всех агентов; SLA-параметры из конфига                                                    |
| **Выходной продукт**    | Гарантия непрерывности потока сигналов и эскалаций; каждое событие имеет назначенного ответственного |
| **Критерий выполнения** | Отсутствие потерянных эскалаций; система работает без ручного вмешательства                          |

**Примечание:** Orchestrator не имеет одного артефактного продукта -- его продукт это состояние системы. Это принципиальное отличие от остальных агентов.

---

## Контур 2 -- Knowledge AI (база знаний)

---

### Агент 6. Ingest Agent -- Агент загрузки знаний

**Продукт:**

<note type="quote">

Проиндексированный документ в RAGflow с корректными метаданными -- готовый к поиску Query Agent и использованию Recommendation Agent.

</note>

| Элемент                 | Содержание                                                                                |
|-------------------------|-------------------------------------------------------------------------------------------|
| **Внутренний клиент**   | Query Agent, Recommendation Agent                                                         |
| **Триггер**             | Загрузка нового документа ответственным за базу знаний                                    |
| **Входные данные**      | Документ (PDF, DOCX, MD) + метаданные: отрасль, тип клиента, стадия сделки, продукт, теги |
| **Выходной продукт**    | Проиндексированная запись в RAGflow; обновлённый граф связей                              |
| **Критерий выполнения** | Документ доступен для поиска Query Agent; все метаданные заполнены                        |

**Обязательные метаданные документа:**

| Поле          | Описание        | Пример                              |
|---------------|-----------------|-------------------------------------|
| `industry`    | Отрасль клиента | Энергетика, Строительство           |
| `client_type` | Тип клиента     | Генподрядчик, Интегратор            |
| `deal_stage`  | Стадия сделки   | Расчёт КП, Переговоры               |
| `product`     | Продукт         | НКУ, ВРУ, БКТП                      |
| `doc_type`    | Тип документа   | Кейс, Скрипт, Возражение, Регламент |
| `tags`        | Теги            | конкуренция, срок, цена             |

---

### Агент 7. Query Agent -- Агент поиска знаний

**Продукт:**

<note type="quote">

Контекстный ответ с цитатой и ссылкой на источник -- для менеджера или Recommendation Agent -- за ≤ 5 секунд.

</note>

| Элемент                 | Содержание                                                              |
|-------------------------|-------------------------------------------------------------------------|
| **Внутренний клиент**   | Менеджер (прямой запрос); Recommendation Agent (инструментальный вызов) |
| **Триггер**             | Текстовый запрос менеджера / вызов от Recommendation Agent              |
| **Входные данные**      | Текстовый запрос + контекст проекта (отрасль, стадия, тип клиента)      |
| **Выходной продукт**    | Ответ + цитата из источника + ссылка на документ                        |
| **Критерий выполнения** | Релевантный ответ ≤ 5 секунд; источник указан всегда                    |

---

### Агент 8. Lint Agent -- Агент аудита знаний

**Продукт:**

<note type="quote">

Еженедельный отчёт о противоречиях, устаревших данных и логических разрывах в базе знаний -- для ответственного за базу знаний.

</note>

| Элемент                 | Содержание                                                                         |
|-------------------------|------------------------------------------------------------------------------------|
| **Внутренний клиент**   | Ответственный за базу знаний (роль `knowledge_manager`)                            |
| **Триггер**             | Еженедельно                                                                        |
| **Входные данные**      | Все документы в RAGflow                                                            |
| **Выходной продукт**    | Отчёт: противоречия, документы старше 6 месяцев, незаполненные разделы             |
| **Критерий выполнения** | Выявлены все документы старше 6 месяцев и документы с конфликтующими утверждениями |

---

## Схема взаимодействия агентов

```
Grace CRM
    ↓ API
[1] Sync Agent ──────────────────────────────────────────────►  OpenSearch
                                                                     │
                                     ┌───────────────────────────────┘
                                     │
                              [5] Orchestrator
                             (управление, SLA)
                                     │
                    ┌────────────────┴────────────────┐
                    ▼                                 ▼
             [2] Quality Agent              [3] Recommendation Agent
             (пробелы в данных)             (следующий шаг) ◄── RAGflow
                    │                                 │        [6] Ingest Agent
                    └────────────────┬────────────────┘        [7] Query Agent
                                     ▼                         [8] Lint Agent
                             [4] Notification Agent
                              (Mattermost / Telegram)
                                     │
                    ┌────────────────┼────────────────┐
                    ▼                ▼                 ▼
                Менеджер            РОП            Зам. ГД
```

---

##