Автораспределение входящих обращений: mini-CRM с весами компетентности операторов
Сервис распределяет входящие обращения между операторами по весам компетентности и текущей загрузке — без ручного назначения. Исходный код открыт, покрыт тестами.
- Масштаб
- Асинхронный REST API
- Этап
- Открытый код
- Сдан
- ноябрь 2025
TL;DR. Входящие обращения обычно назначают операторам вручную или по кругу. Сервис делает это сам: у каждого оператора настраиваемые веса компетентности по источникам обращений и лимит одновременной нагрузки, распределение — взвешенное случайное среди доступных. Асинхронный REST API на FastAPI, код открыт.
Ситуация: назначение обращений вручную
Входящие обращения приходят из разных источников — форма на сайте, мессенджер, телефон, партнёрский канал. Операторы разбираются в них неодинаково: один сильнее в технических вопросах, другой — в биллинге.
Ручное назначение требует диспетчера. Распределение по кругу диспетчера не требует, но игнорирует и компетентность, и текущую загрузку: обращение уходит человеку, у которого уже пять открытых диалогов, при свободном коллеге рядом.
Задача
- Распределять обращения автоматически, без диспетчера.
- Учитывать, кто в каком типе обращений сильнее.
- Не перегружать оператора сверх заданного лимита одновременных обращений.
- Собрать это как сервис с REST API, а не как скрипт внутри монолита.
Что сделали
Асинхронный сервис на FastAPI. Модель данных описывает операторов, источники обращений и веса: для каждой пары «оператор — источник» задаётся вес компетентности, отражающий, насколько этот человек подходит под такой тип обращения.
При поступлении нового обращения сервис отбирает операторов, у которых не исчерпан лимит одновременной нагрузки, и выбирает исполнителя взвешенным случайным образом по весам компетентности для этого источника. Случайность здесь намеренная: детерминированный выбор максимума отдавал бы все обращения одному сильнейшему оператору, пока тот не упрётся в лимит.
Работа с базой — через асинхронный SQLAlchemy. Проект покрыт тестами, исходный код опубликован на github.com/pimenoffd.
Результат
- Рабочий сервис с REST API: обращение приходит, исполнитель назначается без участия человека.
- Компетентность и загрузка учитываются одновременно, а не по очереди.
- Тестовое покрытие на pytest.
- Открытый исходный код — архитектуру можно посмотреть до разговора о задаче.
Ключевые технические решения
- Взвешенное случайное распределение вместо выбора максимума. Всегда отдавать обращение самому компетентному — значит создать очередь к одному человеку и простой у остальных. Вес влияет на вероятность, а не назначает исполнителя жёстко.
- Лимит нагрузки как фильтр до распределения. Оператор с исчерпанным лимитом исключается из выборки перед взвешиванием, а не получает штраф к весу. Так лимит остаётся гарантией, а не пожеланием.
- Веса по паре «оператор — источник». Компетентность не абстрактна: человек может быть сильным в обращениях из одного канала и слабым в другом. Один общий рейтинг оператора эту разницу теряет.
- Асинхронный стек целиком. FastAPI и SQLAlchemy в async-режиме: распределение — операция на каждом входящем обращении, блокирующий доступ к базе упирается в потолок при росте потока.
Частые вопросы
Это готовая CRM?
Нет, это сервис распределения — одна задача, решённая целиком. Он показывает архитектуру автоматического назначения обращений и подключается к существующей CRM, а не заменяет её.
Почему распределение случайное, а не по лучшему оператору?
Детерминированный выбор лучшего создаёт очередь к одному человеку при свободных коллегах. Взвешенная случайность сохраняет приоритет компетентных операторов и распределяет поток.
Можно ли использовать код в своём проекте?
Код открыт на GitHub. Под конкретный процесс потребуется настройка модели весов и интеграция с источниками обращений.
Что было бы дальше
Естественное продолжение — приоритеты обращений и SLA по времени ответа, перераспределение зависших диалогов, подстройка весов по фактическим результатам операторов вместо ручной настройки.
Если входящие обращения распределяются вручную или по кругу — обсудим за 30 минут.
Стек
- Python
- FastAPI
- SQLAlchemy (async)
- SQLite
- pytest