Business rules are GLPI's native automation engine: with no code at all, they classify, assign and apply SLAs to every ticket. What the documentation rarely explains - and what generates the most support tickets when you maintain client GLPI estates - is not how to create a rule, but the evaluation model that decides which rule wins when two of them overlap. This guide starts where most tutorials stop: order, trigger condition and chaining.
The evaluation model almost nobody reads before their first rule
Every ticket business rule has the subtype RuleTicket and lives in the glpi_rules table. Three columns drive the behaviour:
ranking- the evaluation order. The engine reads in ascending order, from lowest to highest. The screen shows them top to bottom, but the number is what rules.condition- when the rule fires:1on creation,2on update,3on both. A rule created for1only never re-evaluates when the ticket is edited later.match- the logic between criteria:AND(all must match) orOR(any of them).
The detail that trips up most people: ticket rules do not stop at the first match. Unlike mail collector rules and inventory import rules, the RuleTicket engine walks through ALL active rules in ranking order and feeds the output of one as the input of the next. In other words, a generic rule with a higher ranking (evaluated later) can overwrite the assignment made by a specific rule that had already matched earlier.
The real anatomy: criteria, actions and operators
Every rule has three blocks. Criteria live in glpi_rulecriterias, actions in glpi_ruleactions:
- Criterion =
criteria(the field) +condition(the operator, numeric) +pattern(the expected value). - Action =
action_type(assign, regex_result, append, fromuser, fromitem) +field(the field to change) +value.
The operator is a numeric code, not text - and picking the wrong one is the most common silent failure. The values in GLPI 11:
0 = is (exact match)
1 = is not
2 = contains
3 = does not contain
4 = begins with
5 = ends with
6 = regular expression (regex)
7 = regex does not match
8 = exists
9 = does not exist
11 = under (entity/category tree)
12 = not under
Real fields you use most often in actions: _groups_id_assign (technician group), _users_id_assign (technician), slas_id_ttr (resolution SLA), itilcategories_id (category) and urgency. In criteria, _mailgate identifies a ticket that came in through a specific mail collector, and _x-priority reads the email priority header.
Checklist: a rule that fires on the first try
- Define the trigger. Reclassifying on creation? Use ONADD (condition 1). Need to react to a category change made afterwards? Also mark update (condition 3).
- Choose the right operator. "Is" (0) requires an identical title; to match a substring use "contains" (2) or regex (6). Most title rules that "don't catch" used "is" where they needed "contains".
- Position the ranking. Specific first, generic later - but remember the later generic one overwrites. If the generic rule should not touch what was already decided, narrow its criteria.
- Check the entity. A rule created in a child entity without the "recursive" flag only applies to that entity's tickets - and disappears for the rest of the estate.
- Test in staging before enabling in production.
- Validate with Rule Inspector inside a real ticket: it shows which rules were evaluated, which criteria passed and which failed.
Diagnostic SQL: what we run when "the rule doesn't work"
Before touching the interface, NexTool dumps the entire set of ticket rules in evaluation order. Within seconds the ranking tells the story - it is almost always order or condition, not a wrong criterion. Run it on a read replica or carefully on the production database:
SELECT r.ranking,
r.name,
IF(r.is_active, 'active', 'INACTIVE') AS state,
r.match AS logic,
CASE r.condition WHEN 1 THEN 'on_create'
WHEN 2 THEN 'on_update'
WHEN 3 THEN 'create+update'
END AS fires_when,
(SELECT GROUP_CONCAT(
CONCAT(c.criteria, ' [op ', c.condition, '] ', c.pattern)
ORDER BY c.id SEPARATOR ' | ')
FROM glpi_rulecriterias c WHERE c.rules_id = r.id) AS criteria,
(SELECT GROUP_CONCAT(
CONCAT(a.action_type, ':', a.field, '=', a.value)
ORDER BY a.id SEPARATOR ' | ')
FROM glpi_ruleactions a WHERE a.rules_id = r.id) AS actions
FROM glpi_rules r
WHERE r.sub_type = 'RuleTicket'
ORDER BY r.ranking;
Read top to bottom: two rows writing _groups_id_assign mean the one with the higher ranking wins. A row with state = INACTIVE explains the "vanishing" rule. fires_when = on_create explains why editing the ticket does not reroute it.
Decision matrix: which rule collection to use
GLPI has several rule collections, and each behaves differently. Confusing one for another is the root of many "why does this rule run twice?":
| Collection | Stops at 1st match? | Chains the output? | Typical use |
|---|---|---|---|
| Ticket business rules (RuleTicket) | No | Yes | Classify, assign group/technician, apply SLA |
| Mail collector rules (RuleMailCollector) | Yes | No | Route or reject the email during collection, before the ticket exists |
| Inventory import (RuleImportAsset) | Yes | No | Link a detected asset to an existing one |
| Entity import (RuleImportEntity) | Yes | No | Set entity and location on inventory intake |
| Dictionaries (software, manufacturer) | Yes | No | Normalise messy inventory names |
For a ticket that arrives by email, note that two engines run in sequence: first the collector (stops at the first match), then the business engine on the already-created ticket (runs them all).
The common field mistake
In day-to-day maintenance, the ticket we get most about rules is always the same: "I created the rule and it doesn't catch." In the vast majority it is not the criterion - it is the evaluation model. Case number one: two rules write _groups_id_assign, the specific one with a lower ranking matches first, and a generic rule with a higher ranking, created months later "just to guarantee a default group", overwrites everything because the engine chains the output. Case two: the rule was created with condition = 1 only (on creation), so when the agent changes the category later, nothing reroutes. That is why we made it an operating standard to always run the audit SQL above BEFORE touching the interface: the ranking column reveals the conflict in seconds, while clicking rule by rule on screen hides the real execution order. It is the kind of thing that only becomes obvious once you run dozens of environments and see the same pattern repeat.
Need a GLPI whose automation behaves predictably, with no rules stepping on each other? NexTool maintenance audits and reorganises your rule set, and the Rule Inspector plugin shows, inside each ticket, exactly which rule decided what.
Reviewed by the NexTool Solutions team.