Корпоративный AI-агент в Норникеле: путь от Open WebUI-пилота к агентной платформе
Корпоративный AI-агент в Норникеле
Подробный конспект доклада Александра Козлова на Data Fest 2026 о переходе от быстрого пилота на Open WebUI к расширяемой внутренней платформе AI-агентов. Источник — автоматическая расшифровка, поэтому редкие названия и отдельные численные формулировки требуют сверки со слайдами.
Коротко
Норникель не стал развивать Open WebUI как собственный монолит. Команда сохранила его как привычный ChatGPT-подобный интерфейс и RAG-слой, а доменную логику вынесла в отдельный LangGraph-оркестратор и независимые MCP-агенты. Доступ к локальным и внешним моделям унифицирован через LiteLLM; выполнение сгенерированного кода изолировано в Firecracker microVM; состояние и артефакты привязаны к chat ID; новые возможности поставляются в виде сервисов и Markdown-скиллов без пересборки UI.
Главный инженерный вывод: качество сложного агента повышается не только выбором LLM, а сочетанием детерминированных узлов, constrained generation, явного планирования, коротких исследовательских циклов, верификации и безопасной среды исполнения.
Зачем понадобилось своё решение
Типовые задачи сотрудников крупной корпорации — работа с документами, аналитика, транскрибация, summary и презентации — уже решаются публичными LLM-ассистентами. Но корпоративные документы нельзя выносить из внутреннего контура, а доступ сотрудников ограничен требованиями ИБ. Поэтому команда выбрала внутреннюю разработку и on-premise-развёртывание.
Этап 1. Быстрый пилот
Для пилотирования выбрали Open WebUI: готовый знакомый интерфейс, базовая серверная часть и простой RAG.
По расшифровке в пилот вошли:
- Open WebUI;
- SQLite;
- ChromaDB;
- локальная доменная модель MetalGPT;
- Qwen (конкретная версия из ASR неразборчива);
- отдельный API/RAG-сервис;
- S3;
- Docling;
- VictoriaMetrics и Grafana.
Что подтвердил пилот
- ChatGPT-подобный интерфейс не требует обучения пользователей.
- Базовые сценарии работают «из коробки».
- UI и backend Open WebUI достаточно стабильны для пилота.
- Простой RAG выдерживал базы с сотнями документов и удовлетворял большинство текущих запросов.
Что не устроило
1. Слабая агентность. Встроенный агентный механизм спикер характеризует как простой цикл инструментальных вызовов. 2. Недостаточная аналитика Excel. Пользователям нужны большие книги, объединение листов, сводные таблицы, инфографика и HTML-артефакты. 3. Производительность. Даже при мощном сервере примерно 1 000 пользователей и всплески параллельных запросов заметно нагружали систему. 4. Монолит. UI, backend и AI-часть связаны в одном проекте. 5. Цена форка. Собственные изменения трудно отделять от upstream, а частые обновления усложняют сопровождение. 6. Растущий backlog агентов. Подразделения постоянно запрашивали новые сценарии, для которых требовалась расширяемая архитектура.
Этап 2. Целевая платформенная архитектура
Принцип разделения
Open WebUI оставили почти без изменений как UI/backend. Собственная агентная система подключается к нему как обычная OpenAI-compatible «модель» через административную панель. Для пользователя всё остаётся единым чатом; HTTP-запрос поступает в оркестратор, а тот вызывает специализированные сервисы через MCP.
Основные компоненты
| Слой | Решение | Роль |
|---|---|---|
| Пользовательский интерфейс | Open WebUI | чат, существующий RAG и знакомый UX |
| Оркестрация | отдельный LangGraph-агент, ReAct-подход | маршрутизация, память, вызов MCP, workflow, проверка результата |
| Интеграция агентов | MCP | единый способ подключать новые независимые сервисы |
| Специализированные агенты | data analyst, web search, presentation, будущие HR-агенты | доменные workflow |
| LLM gateway | LiteLLM | единый каталог моделей, OpenAI-compatible API, retries, budgets, fallback chains, routing |
| Модели | локальные vLLM-модели + Яндекс через private endpoint | гибрид локального и внешнего inference в допустимом контуре |
| Память | Mem0 | память чата и долгосрочная пользовательская память |
| Данные | PostgreSQL, Milvus, S3 | транзакционные данные, векторы и артефакты |
| Балансировка | Traefik | маршрутизация и балансировка реплик |
| Изоляция кода | Firecracker microVM | безопасное исполнение аналитического кода и Linux-инструментов |
| Наблюдаемость | VictoriaMetrics, Grafana | CPU/GPU и сервисные метрики |
Модель расширения
Новый кейс больше не требует форка Open WebUI. Команда создаёт отдельный агентный сервис, регистрирует его в оркестраторе/MCP и делает доступным в общем чате. Это отделяет частоту развития агентов от цикла обновлений пользовательского интерфейса.
UX длительных операций
В UI добавили четыре собственных типа SSE-чанков, чтобы показывать прогресс анализа. Пользователь видит, что агент выполняет шаги, а не завис. Это небольшая, но важная граница между технически работающим workflow и приемлемым корпоративным UX.
Оркестратор
Оркестратор — центральный LangGraph/ReAct-агент:
1. принимает запрос из Open WebUI; 2. извлекает релевантный контекст из Mem0; 3. выбирает MCP-инструмент или специализированного агента; 4. запускает workflow; 5. получает и верифицирует результат; 6. сохраняет результат и обновляет память.
Встроенная память Open WebUI — последние N сообщений — была признана слишком примитивной. Платформа разделяет как минимум:
- память текущей сессии/чата;
- долгосрочную память конкретного пользователя.
Агент анализа данных
Именно этот агент заменил недостаточный встроенный анализ Open WebUI. Верхнеуровневый workflow:
1. профилирование файла; 2. маршрутизация и выбор файла; 3. планирование; 4. генерация и выполнение кода; 5. верификация; 6. retry при ошибке; 7. summary и упаковка артефактов; 8. сохранение в S3 и выдача пользователю.
1. Детерминированное профилирование вместо «пусть LLM разберётся»
Когда модели сразу давали Excel и просили написать код, она выдумывала поля, неверно понимала типы, ошибалась в коде и попадала в длинные retry-циклы. Вместо этого команда написала обычный Python-узел, который анализирует:
- листы и заголовки;
- merged headers;
- колонки и типы;
- перцентили и статистические характеристики.
LLM получает компактный JSON-профиль структуры файла. По словам спикера, один этот шаг повысил success rate первых итераций примерно на 20–25% и снизил лишние токены/циклы.
Обобщение: всё, что можно надёжно вычислить обычным кодом, не следует поручать вероятностной модели.
2. Constrained generation для решений со строгой схемой
Для роутинга, выбора файлов и других структурированных решений применяется constrained generation: JSON schema/parser ограничивает допустимые токены через logits masking. Спикер описывает схему ответа с промежуточными полями: анализ доступных файлов и запроса, оценки файлов, reasoning, затем финальный выбор.
Поскольку модель авторегрессионна, финальное решение уже обусловлено ранее сгенерированным анализом. Это снижает риск режима «сначала выбрать, затем задним числом оправдать выбор», который команда наблюдала у reasoning-моделей.
3. Иерархическое планирование и малые исследовательские шаги
Планировщик разбивает запрос на шаги, а кодогенератор может дополнительно декомпозировать каждый шаг. Если информации недостаточно, модель в цикле:
- задаёт вопрос среде;
- выполняет небольшой исследовательский код;
- получает результат sandbox;
- добавляет наблюдение в prompt;
- продолжает, пока не снимет флаг
continue.
Такой внутренний цикл позволяет разбирать большие и нестандартные Excel-книги постепенно, а не пытаться сгенерировать весь анализ одним проходом.
4. Верификация и ограниченные retry
После исполнения результат проверяется отдельным verifier-узлом. Успех ведёт к summary и формированию артефактов; неуспех — к повторной итерации. Важное отличие от наивного retry: повторение получает фактические наблюдения из среды и структурированный контекст.
Безопасное выполнение кода
Почему Firecracker, а не обычный Docker
Сгенерированный код нельзя безопасно запускать на основном хосте. Docker разделяет kernel хоста, поэтому уязвимость kernel потенциально даёт путь к host escape. Firecracker поднимает отдельную microVM с собственным гостевым kernel и дополнительным слоем изоляции. Поэтому команда выбрала более безопасную, хотя и более тяжёлую модель исполнения.
Жизненный цикл sandbox
Первоначально microVM создавали на каждый запрос. Затем перешли к привязке VM к chat ID:
- sandbox manager ищет существующую VM для текущей сессии;
- повторно использует её;
- сохраняет внутри промежуточные файлы и артефакты;
- удаляет после периода бездействия.
На момент доклада TTL ещё подбирался — примерно 10–20 минут. Такой session-scoped sandbox уменьшает стоимость запуска и делает многошаговую работу с файлами естественной.
Среда как полноценный Linux-workbench
Внутри VM доступен не только Python, но и Linux-инструменты: упомянуты LibreOffice, Pandoc, средства графики/диаграмм и другие пакеты. Агент получает tools для bash, чтения директорий и создания файлов. Это позволяет выпускать не только текст ответа, но документы, таблицы, графики и преобразованные файлы.
Skills как слой процедурного знания
В оркестраторе есть skill registry. Он индексирует Markdown-файлы с названием, описанием и инструкцией решения конкретной задачи. В нужный момент оркестратор выбирает skill и передаёт его агенту. В VM также попадают корпоративные шаблоны, включая брендбук Норникеля.
Отдельный meta-skill skill creator может создать новый Markdown-skill и положить его в папку; пересборка системы не требуется. Пока это эксперимент: открытая проблема — namespaces, права и предотвращение накопления тысяч пользовательских скиллов.
Это совпадает с подходом формализации бизнеса и агентов: повторяемая процедура становится версионируемым машинно-читаемым артефактом, а не частью закрытого prompt-кода.
Маршрутизация моделей и эксплуатация
LiteLLM используется как единая точка доступа к моделям:
- единый OpenAI-compatible интерфейс;
- каталог локальных и внешних моделей;
- retries и budgets;
- fallback на Яндекс при отказе локальной модели;
- tiered routing между быстрыми, средними и сложными моделями;
- выбор модели самим агентом или жёсткая привязка в workflow.
Простой запрос не должен уходить на тяжёлую модель уровня Qwen 235B. Это превращает выбор модели в эксплуатационную политику, а не в решение интерфейса.
В Q&A спикер сообщил, что на сервере было четыре GPU (автораспознавание не позволяет уверенно определить модель карты). Нагрузка была разделена между embeddings, MetalGPT и Qwen. Замер порядка 150–170 токенов/с прозвучал как приблизительный единичный результат, а не как формальный benchmark.
По словам спикера, LiteLLM не демонстрировал утечек памяти: команда следила за CPU/GPU и сервисными метриками. Проблемы наблюдались у других сервисов, в частности Docling.
RAG: что сделано, а что только планируется
На агентный или graph RAG команда ещё не перешла. Оркестратор использует существующий RAG Open WebUI, и для нынешних сценариев этого достаточно. Agentic RAG и graph RAG рассматриваются как будущее направление для кейсов с тысячами документов и более сложными данными.
Возможные будущие шаги:
- query rewriting;
- решение, нужен ли поиск вообще;
- выбор специализированного способа поиска;
- дополнительные узлы очистки и проверки;
- graph retrieval.
Важно не приписывать докладу уже реализованный agentic RAG: это перспективная гипотеза.
Организационные и продуктовые выводы
1. Пилот должен проверять спрос, а не сразу становиться платформой. Open WebUI быстро подтвердил востребованность и раскрыл реальные кейсы. 2. Не форкать UI без необходимости. Стабильный внешний продукт можно оставить shell-слоем, а ценную логику вынести за API. 3. Agent capability = отдельный сервис. Это упрощает ownership, масштабирование и независимый release cycle. 4. Инженерия важнее магии модели. Детерминированный parser дал измеримый прирост, которого не гарантирует простая замена LLM. 5. Длительные workflow требуют прозрачности. Streaming progress — часть продукта, а не косметика. 6. Sandbox должен сохранять контекст сессии. Иначе стоимость запуска и передача артефактов ухудшают UX. 7. Skills требуют governance. Нужны namespaces, владельцы, ACL, review, версии, дедупликация и lifecycle. 8. Гибридный inference практически полезен. Локальные модели дают контроль, private endpoint и fallback — устойчивость. 9. ИБ — постоянный процесс. Детали кейсов безопасности не раскрыты; спикер подтвердил участие команд ИБ и DevOps и соблюдение корпоративных правил.
Что переносимо в наши проекты
Для агентской среды «Гелиос» особенно применимы:
- UI как заменяемый adapter, а не место бизнес-логики;
- отдельный orchestrator/control plane;
- MCP-сервисы как исполнимые capability;
- skill registry как процедурный слой;
- tiered model routing через gateway;
- session-scoped sandbox с TTL;
- deterministic preprocessing до LLM;
- verifier после выполнения;
- артефакты и прогресс как first-class outputs.
Для Everything as Code доклад даёт практическую форму: процедура хранится в Markdown-skill, корпоративный шаблон — как версионируемый asset, агент — как сервис, модельная политика — как gateway configuration, а выполнение — как наблюдаемый workflow.
Риски и открытые вопросы
- Не раскрыты SLA, latency percentile, DAU/MAU и реальная concurrency.
- Нет формального benchmark качества data analyst; есть только прирост success rate от profiling node.
- Неясны ACL и tenant isolation в Mem0, S3, Milvus и session VM.
- Не раскрыты защита от prompt injection, egress policy, supply-chain контроль образов и secrets management sandbox.
- Неясны аудит MCP-tools и подтверждение опасных действий.
- Skill creator без governance способен создать неуправляемый каталог процедур.
- Примерно 1 000 пользователей — не то же самое, что 1 000 одновременных запросов.
- Часть названий и характеристик восстановлена из автоматических субтитров и нуждается в сверке со слайдами.
Таймкоды
| Время | Тема |
|---|---|
| [00:00](https://www.youtube.com/watch?v=2yjcPd2rYFc&t=0s) | задача и ограничения корпоративного контура |
| [01:40](https://www.youtube.com/watch?v=2yjcPd2rYFc&t=100s) | пилот на Open WebUI и его стек |
| [02:43](https://www.youtube.com/watch?v=2yjcPd2rYFc&t=163s) | обратная связь пользователей и ограничения пилота |
| [04:44](https://www.youtube.com/watch?v=2yjcPd2rYFc&t=284s) | переход к Open WebUI + orchestrator + MCP |
| [05:48](https://www.youtube.com/watch?v=2yjcPd2rYFc&t=348s) | LiteLLM, tiered routing и инфраструктура |
| [07:12](https://www.youtube.com/watch?v=2yjcPd2rYFc&t=432s) | SSE-прогресс и UX |
| [07:52](https://www.youtube.com/watch?v=2yjcPd2rYFc&t=472s) | LangGraph-оркестратор и Mem0 |
| [08:55](https://www.youtube.com/watch?v=2yjcPd2rYFc&t=535s) | workflow data analyst |
| [09:42](https://www.youtube.com/watch?v=2yjcPd2rYFc&t=582s) | детерминированное профилирование Excel |
| [10:31](https://www.youtube.com/watch?v=2yjcPd2rYFc&t=631s) | constrained generation |
| [12:43](https://www.youtube.com/watch?v=2yjcPd2rYFc&t=763s) | вложенные циклы планирования и code execution |
| [14:12](https://www.youtube.com/watch?v=2yjcPd2rYFc&t=852s) | Firecracker против Docker |
| [15:10](https://www.youtube.com/watch?v=2yjcPd2rYFc&t=910s) | session-scoped microVM и TTL |
| [16:25](https://www.youtube.com/watch?v=2yjcPd2rYFc&t=985s) | skill registry и Linux-tools |
| [18:40](https://www.youtube.com/watch?v=2yjcPd2rYFc&t=1120s) | Q&A: GPU throughput и LiteLLM |
| [20:09](https://www.youtube.com/watch?v=2yjcPd2rYFc&t=1209s) | Q&A: классический и agentic RAG |
| [21:44](https://www.youtube.com/watch?v=2yjcPd2rYFc&t=1304s) | Q&A: безопасность |
Источник
- Автоматическая расшифровка видео с таймкодами
- [YouTube](https://www.youtube.com/watch?v=2yjcPd2rYFc)