AI-агент
Источники требований
Модуль текстового чат-помощника в админке франшизы. Пользователь пишет запрос на русском («создай заказ на маргариту и колу на вынос»), агент сам решает какие методы ERP-API вызвать, формирует результат и стримит ход рассуждений. Авторизация — от имени юзера, никаких суперправ.
Не путать с POS-агентом
AI-агент в админке — это инструмент владельца франшизы / партнёра / администратора ТТ, не кассира. Голосовой POS-агент с computer-use отменён (ADR-022). Кассир пользуется обычным POS UI.
Сущность «Сессия чата» (agent_conversation)
| Поле | Обязательность | Описание |
|---|---|---|
| ID сессии | Авто | UUID |
| Владелец | Обязательно | user_id создателя |
| Франшиза | Обязательно | franchise_id из JWT — мультитенантная изоляция |
| Заголовок | Авто | Первые 60 символов первого сообщения |
| Статус | Авто | active (открыт) / closed (закрыт юзером) |
| Создано / обновлено | Авто | TIMESTAMPTZ |
Сущность «Сообщение» (agent_message)
| Поле | Обязательность | Описание |
|---|---|---|
| ID сообщения | Авто | UUID, порядок задаётся created_at |
| Сессия | Обязательно | FK на agent_conversation |
| Роль | Обязательно | user / assistant / tool |
| Контент | Опционально | Текст. Для tool-сообщений — JSON с результатом вызова |
| Tool calls | Опционально | Массив [{tool_name, arguments_json}] (для assistant если решил вызвать tool) |
| Tool call ID | Опционально | Для роли tool — ID вызова, на который отвечает |
| Длительность LLM | Опционально | мс (для аналитики) |
| Eval tokens | Опционально | Кол-во сгенерированных токенов |
| Создано | Авто | TIMESTAMPTZ |
Бизнес-правила
- Per-user сессии — сессия привязана к юзеру, шеринг между юзерами не допускается. Другой админ не видит чужие сессии.
- Лимит сессии — ≤ 20 ходов (пар user→assistant). После — UI показывает «Начни новый чат» и блокирует input. Цель — ограничить контекст LLM (модель влезает в 32K, но качество ReAct падает на длинных).
- Лимит сообщения — текст user ≤ 2000 символов. Если больше — UI обрезает с уведомлением.
- Авто-чистка — сессии старше 30 дней (
closed) удаляются ночным cron. Активные не трогаются. - Авторизация tool — каждый tool_call идёт с JWT юзера. Если у юзера нет permission на эндпоинт — tool вернёт
403и агент сформулирует это юзеру. - Маскирование секретов — если в результате tool пришли поля типа
pin_hash,password,salary_amount,legal_inn— OpenClaw Agent маскирует их перед передачей в модель (защита от prompt leak через ответы). Раньше эту функцию выполнял самописныйerp-llm-gateway— отказан 2026-05-13. - Rate limit — ≤ 30 запросов / минуту на юзера. На франшизу — ≤ 100 / минуту (защита LLM-хоста).
- Безопасность системного промпта — фиксированный, не редактируется пользователем. Содержит правила: «не выдумывай ID», «всегда ищи перед действием», «отказывайся от запросов вне 5 базовых tools».
Базовые инструменты (MVP)
| Tool (внутреннее имя) | Назначение | Кто может использовать |
|---|---|---|
find_products | Поиск товаров каталога по строке | Все с agent.use |
create_order | Создание заказа | Все с agent.use (и orders.write downstream) |
get_stoplist | Список товаров в стоп-листе | Все с agent.use |
add_to_stoplist | Добавить товар в стоп-лист | Все с agent.use (и catalog.stoplist.write downstream) |
get_sales_summary | Сводка продаж за период | Все с agent.use (и orders.read downstream) |
Системный промпт ссылается только на эти 5 функций. Если юзер просит что-то вне — модель отвечает «Этого я ещё не умею, попроси Алексея». Каталог расширяется отдельным BR при добавлении новых tools.
Ролевая матрица
| Permission | Системная «Администратор» | Менеджер ТТ | Кассир |
|---|---|---|---|
agent.use — открывать чат, посылать сообщения | ✅ | ⚙️ опционально | ❌ |
agent.config — включать/выключать агента для франшизы, смотреть логи всех юзеров | ✅ | ❌ | ❌ |
Логика: agent.use в системной роли «Администратор» — у владельцев франшизы / партнёра агент работает из коробки. Менеджерам ТТ владелец может выдать вручную через permission-роли (если хочет дать им возможность создавать заказы через чат — но кассир по-прежнему работает через POS UI).
Кассир и AI-агент
Кассир НЕ использует AI-агент. POS-канал — отдельный, ручной. AI-агент в админке — это инструмент быстрого ввода заказа для владельца ТТ (например, по телефону позвонил гость с большим заказом, владелец быстро ввёл голосом-в-чат).
Что НЕ входит в MVP
| Out of scope | Когда | Почему |
|---|---|---|
| Голосовой ввод (STT) | Phase 2 | Whisper в WSL2 жрёт VRAM, конкурирует с LLM |
| Голосовой ответ (TTS) | Phase 3 | UX не приоритет на демо |
| Кастомный системный промпт | Не планируется | Защита от prompt-injection |
| Multi-tenant изоляция модели | Phase 2 | На MVP одна модель на всех (per-user разделение через JWT) |
| Память между сессиями (long-term memory) | Phase 2 | Усложняет UX, требует векторной БД |
| Векторная БД / RAG по документации | Phase 2 | Отдельный продукт |
| Кастомные tools от франшизы | Phase 3 | Сначала стабилизируем базовые 5 |
| OAuth для tool на сторонние API | Не планируется | Все tools — внутрь ERP |
| Защита от prompt-injection через данные ERP (товар с подозрительным названием) | Phase 2 | Митигация — маскирование секретов перед LLM (см. правила выше) |
Поведение в UI (см. фронт-спеку)
Подробности — AI-агент — Чат.
| Состояние | Что видит юзер |
|---|---|
| Закрыт | Floating button «✨ AI» bottom-right |
| Открыт | Окно 380×600, шапка «AI-помощник», история сообщений, input снизу, кнопка «Очистить» в шапке |
| Стрим | Пузырь ассистента наполняется по мере генерации, под ним блоки 🔍 ищу товары…, ✓ нашёл 2, 📝 создаю заказ… |
| Ошибка | Красный alert «AI временно недоступен» с кнопкой «Повторить» |
| Без прав | Кнопка скрыта (agent.use отсутствует) |
Связи с другими модулями
- Роли — добавляются permissions
agent.use,agent.config - Заказы — агент создаёт через тот же endpoint что и UI
- Стоп-листы — агент читает / пишет в стоп-лист
- Каталог — агент использует поиск по товарам
Метрики (для пост-демо аналитики)
| Метрика | Источник |
|---|---|
| Кол-во активных юзеров AI-агента / неделя | agent_conversation GROUP BY user_id |
| Среднее число ходов в сессии | agent_message COUNT / conversations |
| Распределение tools по частоте | agent_message.tool_calls UNNEST |
| Среднее время ответа (LLM + tools) | agent_message.llm_duration_ms |
| Success rate (нет ошибок ни в одном tool за сессию) | По tool-сообщениям |