#2193: Автоматическое распределение тикетов: правила автоназначения и ребалансировщик
Отредактирована: вчераSwarmica умеет распределять тикеты по агентам и группам без диспетчера. Это делают два механизма, и оба используют один и тот же упорядоченный список правил автоназначения (AutoAssign):
| Механизм | Когда запускается | Какие тикеты обрабатывает |
|---|---|---|
| Автоназначение при создании тикета | Один раз, сразу после создания тикета | Новый тикет, созданный без исполнителя и без группы |
| Ребалансировщик (Rebalancer) | Периодически, по расписанию CRON | Тикеты в статусе Новый или Открыт, у которых нет исполнителя или исполнитель в статусе Офлайн, а тикет не заблокирован |
Каждое изменение записывается в историю тикета событием «Применено правило автоназначения», автор события — системный пользователь Swarmica.
1. Правила автоназначения
Правила проверяются сверху вниз, в заданном порядке. Побеждает первое правило, которое дало результат; остальные для этого тикета уже не проверяются.
1.1 Опции правила
| Опция (API) | Значения | Что делает |
|---|---|---|
Название (name), описание (description) | локализованный текст | Только для администраторов, на распределение не влияет. |
Включено (enabled) / Порядок (order) | — | В работе участвуют только включённые правила. Эти параметры настраиваются через визуальный редактор в разделе Настройка > Автоматизация > Автоназначение заявок. |
Условия заявки (ticket_conditions) | фильтр тикетов (Query Language) | К каким тикетам применяется правило. Те же условия, что в фильтрах тикетов (статус, приоритет, канал, продукт, навыки, кастомные поля, SLA и т. д.). Пусто — любой тикет. Настраивается через визуальный редактор. |
Условия пользователя (user_conditions) | фильтр пользователей (Query Language) | Каких агентов может выбрать правило (например, по роли, навыкам, сегменту, кастомным полям). Пусто — любой агент. Настраивается через визуальный редактор. |
Группа (group) | группа или пусто | Задана: агент выбирается среди участников этой группы, а тикет переводится в эту группу. Пусто: агент выбирается среди всех агентов, группа тикета не меняется. |
Искать исполнителя внутри текущей группы заявки (within_ticket_group) | да / нет | Агент выбирается среди участников текущей группы тикета (любой агент, если у тикета нет группы). Группа тикета никогда не меняется. Нельзя сочетать с group и с do_not_assign. |
Назначение по навыкам (skill_match) | пусто / ANY / FULL | Как навыки тикета ограничивают пул агентов. Пусто: навыки не учитываются. ANY: у агента должен быть хотя бы один из навыков тикета. FULL: у агента должны быть все навыки тикета. Тикет без навыков не ограничивает пул. |
Не назначать никого (do_not_assign) | да / нет | Правило никогда не назначает агента. Вместе с group оно только переводит тикет в группу (маршрутизация в очередь). Без группы правило ничего не делает, и проверка переходит к следующему правилу. |
Не обрабатывать другие правила (skip_other_rules) | да / нет | Стоп-правило: если тикет под него подходит, тикет остаётся как есть (без агента и без смены группы), и следующие правила не проверяются. Используйте, чтобы исключить тикеты из автоматического распределения (VIP, определённый канал и т. п.). |
Удаление правила архивирует его (оно пропадает из списка и выключается). При удалении навыка он убирается из условий всех правил; если в условии не осталось навыков, условие удаляется.
1.2 Как выбирается агент
Из агентов, попавших в пул правила (user_conditions, группа, навыки), рассматриваются только доступные:
- статус агента — Онлайн или В сессии (агенты в статусах Занят, Завершение работы, Отошёл и Офлайн не выбираются никогда);
- агент не достиг личного лимита назначений (
autoassign_limitв профиле агента;0— без лимита; значение по умолчанию для новых агентов берётся из переменной окруженияDEFAULT_AUTOASSIGN_LIMIT). Нагрузка — это число тикетов агента в статусах Новый и Открыт.
Затем доступные агенты ранжируются, и выбирается первый:
- Статус: Онлайн раньше, чем В сессии.
- Нагрузка: сначала те, у кого меньше тикетов Новый/Открыт.
- Время ожидания: первым идёт агент, который дольше всех не получал тикет (из любого источника — вручную, правилом, триггером); агент, которому тикеты ещё ни разу не назначались, идёт самым первым.
- При равенстве — по ID агента.
Нагрузка пересчитывается для каждого тикета, поэтому за один запуск ребалансировщика тикеты распределяются по кругу между наименее загруженными агентами.
1.3 Сочетания опций
| Поместить тикет в группу | Искать исполнителя в текущей группе | Не назначать никого | Не обрабатывать другие правила | Результат для подходящего тикета |
|---|---|---|---|---|
| — | — | — | ✔ | Тикет не меняется; следующие правила не проверяются. (Остальные опции стоп-правила игнорируются.) |
| пусто | нет | нет | нет | Агент из всех агентов; группа тикета не меняется. Если доступного агента нет — следующее правило. |
| Группа A | нет | нет | нет | Агент из группы A; тикет переводится в A и назначается. Если в A нет доступного агента — следующее правило (тикет не переводится). |
| Группа A | нет | ✔ | нет | Тикет переводится в A без агента. Срабатывает всегда — доступность агентов не важна. |
| пусто | нет | ✔ | нет | Не действует: правило пропускается, проверяется следующее. (Такой настройки лучше избегать.) |
| пусто | ✔ | нет | нет | Агент из собственной группы тикета (любой агент, если у тикета нет группы); группа не меняется. Если агента нет — следующее правило. |
| Группа A | ✔ | любое | — | Запрещено (ошибка валидации). |
| пусто | ✔ | ✔ | — | Запрещено (ошибка валидации). |
skill_match и user_conditions можно добавить к любой назначающей строке — они только сужают пул агентов.
Типовые настройки
- Сначала маршрутизация в очередь, потом назначение: правило «Тикеты по биллингу → группа Биллинг,
do_not_assign» стоит выше назначающего правила сwithin_ticket_group. Первое правило маршрутизирует, а ребалансировщик (в режиме GROUP) затем назначает агента внутри группы. - Цепочка с запасными вариантами: «Агенты L2 с навыками (
skill_match = FULL)» → «Любой агент L2» → «Любой агент L1». Если в первом пуле никто не доступен, пробуется следующее правило. - Исключение: правило со
skip_other_rulesв самом верху для тикетов, которые нужно распределять вручную.
2. Автоназначение при создании тикета
Настройка: enable_autoassign в настройках ребалансировщика (по умолчанию включена).
- Запускается один раз, в фоне, сразу после создания тикета.
- Запускается только если тикет создан без исполнителя и без группы (тикет, созданный сразу в группе — например, каналом или триггером, — остаётся ребалансировщику).
- Не зависит от режима ребалансировщика — работает и при выключенном ребалансировщике.
- Проверяются все включённые правила (ограничение режима GROUP не действует — у тикета всё равно нет группы).
- Если ни одно правило не дало результата, тикет остаётся неназначенным; позже его может подхватить ребалансировщик.
flowchart TD
A([Тикет создан]) --> B{Есть исполнитель<br/>или группа?}
B -- да --> Z1([Пропуск: оставить как создан])
B -- нет --> C{enable_autoassign<br/>включён?}
C -- нет --> Z2([Пропуск])
C -- да --> D[Фоновая задача:<br/>включённые правила по порядку]
D --> E{Следующее правило?}
E -- правил не осталось --> Z3([Без изменений:<br/>тикет не назначен])
E -- правило --> F{Тикет подходит под<br/>ticket_conditions?}
F -- нет --> E
F -- да --> G{skip_other_rules?}
G -- да --> Z4([Стоп: тикет не меняется])
G -- нет --> H{do_not_assign?}
H -- да --> I{У правила есть группа?}
I -- нет --> E
I -- да --> J[Перевести тикет в группу<br/>правила, без агента]
H -- нет --> K[Собрать пул агентов:<br/>user_conditions + skill_match<br/>+ группа правила / группа тикета / все]
K --> L[Оставить агентов Онлайн / В сессии<br/>ниже их autoassign_limit]
L --> M{Есть агент?}
M -- нет --> E
M -- да --> N[Выбрать лучшего агента:<br/>статус → нагрузка → дольше ждёт → id]
N --> O[Назначить агента;<br/>перевести в группу правила, если задана<br/>и нет within_ticket_group]
J --> P([Сохранить тикет + событие<br/>«Применено правило автоназначения»<br/>от Swarmica])
O --> P
3. Ребалансировщик
Ребалансировщик — одна глобальная настройка.
3.1 Опции ребалансировщика
| Опция (API) | Значения | Что делает |
|---|---|---|
mode | NONE / GROUP / ALL | NONE: периодическая ребалансировка выключена. GROUP: тикеты остаются в своей группе (см. ниже). ALL: каждое включённое правило применяется к каждому тикету, тикеты могут переводиться между группами. |
cron_schedule | выражение CRON, по умолчанию */30 * * * * | Как часто запускается ребалансировщик (по умолчанию каждые 30 минут). |
enable_autoassign | да / нет, по умолчанию да | Включает или выключает автоназначение при создании тикета (раздел 2). Не зависит от mode. |
Переменная окружения: REBALANCER_LOCK_TIMEOUT (в секундах, по умолчанию 1800) — максимальное время, на которое один запуск удерживает блокировку.
3.2 Какие тикеты ребалансируются
Тикет ребалансируется, если выполнены все условия:
- статус Новый или Открыт (тикеты в статусах Ожидание, Решён, Закрыт и т. д. не трогаются никогда);
- у тикета нет исполнителя, или его исполнитель в статусе Офлайн, а тикет не заблокирован (заблокированный тикет остаётся за офлайн-исполнителем).
Тикеты обрабатываются начиная с самых срочных — по индексу нарушения SLA, по убыванию; тикеты без SLA идут последними.
3.3 Режимы GROUP и ALL
Режим определяет, какие правила может использовать тикет:
| Тикет | Режим ALL | Режим GROUP |
|---|---|---|
| Без группы | все включённые правила | все включённые правила |
| В группе X | все включённые правила (тикет может быть переведён в другую группу) | только правила с group = X и правила с within_ticket_group; правила с другой группой и правила без группы пропускаются |
Таким образом, в режиме GROUP тикет, уже находящийся в группе, никогда её не покидает и назначается только участникам этой группы. Тикет в группе, для которой нет подходящих правил, не меняется.
3.4 Алгоритм запуска
flowchart TD
S([Срабатывание CRON]) --> L{Блокировка свободна?<br/>другой запуск не идёт}
L -- нет --> X0([Пропустить запуск])
L -- да --> M{mode = NONE?}
M -- да --> X1([Стоп])
M -- нет --> R{Есть включённое<br/>правило?}
R -- нет --> X2([Стоп])
R -- да --> T[Выбрать тикеты: статус Новый/Открыт<br/>и нет исполнителя, или исполнитель Офлайн<br/>и тикет не заблокирован]
T --> T2{Есть тикеты?}
T2 -- нет --> X3([Стоп])
T2 -- да --> A{Есть агент Онлайн / В сессии<br/>ниже лимита ИЛИ правило do_not_assign<br/>с группой?}
A -- нет --> X4([Стоп])
A -- да --> O[Отсортировать тикеты по индексу<br/>нарушения SLA, самые срочные первыми]
O --> NT{Следующий тикет?}
NT -- не осталось --> DONE([Снять блокировку, завершить])
NT -- тикет --> P[Подобрать правило и агента<br/>тем же алгоритмом, что при создании,<br/>с фильтром правил режима GROUP]
P --> Q{Правило дало агента<br/>или группу?}
Q -- нет --> NT
Q -- да --> C{Изменится исполнитель<br/>или группа?}
C -- нет --> NT
C -- да --> RE[Перечитать тикет]
RE --> V{Всё ещё Новый/Открыт, правило применимо,<br/>группа не менялась для правила within_ticket_group,<br/>изменение всё ещё есть?}
V -- нет --> NT
V -- да --> W[Сохранить исполнителя / группу<br/>+ событие «Применено правило автоназначения»<br/>от Swarmica]
W --> NT
Шаг подбора правила (P) — тот же, что в разделе 2, с одной дополнительной проверкой в начале каждого правила: в режиме GROUP правило, не подходящее к группе тикета (раздел 3.3), пропускается.
flowchart TD
E{Следующее правило?} -- не осталось --> N0([Правила нет: тикет не меняется])
E -- правило --> G{Режим GROUP и тикет в группе X:<br/>группа правила = X или within_ticket_group?}
G -- нет --> E
G -- да / режим ALL / тикет без группы --> F{Тикет подходит под<br/>ticket_conditions?}
F -- нет --> E
F -- да --> SK{skip_other_rules?}
SK -- да --> N1([Стоп: тикет не меняется])
SK -- нет --> DN{do_not_assign?}
DN -- да, с группой --> RG([Перевести в группу правила, без агента])
DN -- да, без группы --> E
DN -- нет --> AG{Есть доступный агент в пуле?}
AG -- нет --> E
AG -- да --> OK([Назначить лучшего агента;<br/>перевести в группу правила, если задана])
3.5 Важные детали
- Один запуск за раз. Если запуск ещё идёт, когда наступает следующее срабатывание CRON, новый запуск пропускается. Запуск, простоявший в очереди дольше кратчайшего интервала расписания, тоже отбрасывается — следующий уже в очереди.
- Ранние выходы. Запуск ничего не делает (и почти ничего не стоит), если режим NONE, нет включённых правил, нет тикетов для ребалансировки, или никто не доступен и нет правила, которое маршрутизирует без агента.
- Изменения, сделанные во время запуска, важнее. Перед записью ребалансировщик перечитывает тикет. Если агент за это время перевёл его в Ожидание, назначил или перенёс в другую группу, тикет пропускается.
- Агент, вышедший в онлайн во время запуска, будет учтён в следующем запуске.
- Офлайн-исполнитель + правило
do_not_assign. Такое правило меняет только группу: тикет переводится в группу правила, но остаётся за офлайн-исполнителем. - Переназначение тикета офлайн-агента не затрагивает другие настройки агента; чтобы тикет остался за офлайн-владельцем, заблокируйте тикет.
4. Сочетание автоназначения при создании и ребалансировщика
enable_autoassign | mode | Поведение |
|---|---|---|
| вкл | NONE | Новые тикеты (без группы и исполнителя) назначаются один раз при создании. Если доступного агента не было, повторной попытки не будет, а тикеты офлайн-агентов остаются за ними. |
| вкл | GROUP | Назначение при создании плюс периодическая доводка: неназначенные тикеты и тикеты офлайн-агентов переназначаются внутри своей группы. Рекомендуется для команд, организованных по группам. |
| вкл | ALL | Назначение при создании плюс периодическая доводка по всему хелпдеску; правила могут переводить тикеты между группами. |
| выкл | GROUP / ALL | При создании ничего не происходит; тикеты распределяются только по расписанию ребалансировщика (задержка — до одного интервала CRON). Удобно, когда группу сначала проставляют каналы или триггеры. |
| выкл | NONE | Автоматическое распределение полностью выключено. |
Примечания:
- Тикеты, созданные с группой (каналом, формой, триггером или агентом), при создании никогда не обрабатываются — назначить их может только ребалансировщик. Для этого используйте режим GROUP с правилом
within_ticket_group. - Оба механизма используют одни и те же правила в одном и том же порядке, поэтому правило ведёт себя в них одинаково, за исключением фильтра режима GROUP, который применяет только ребалансировщик.