KW Knowledge base

Helpdesk rules

The rules engine automates ticket workflows. A rule has three parts:

Mitch Wigham
Updated 24 June 2026 · 6 views

32 · Helpdesk rules

The rules engine automates ticket workflows. A rule has three parts:

Part What it is
Trigger When the rule is evaluated
Conditions Filters that must all match (AND)
Actions What happens when conditions are true

Rules are tenant-scoped, ordered, and toggleable. Build them at /admin/helpdesk/rules.

Triggers

Trigger Fires
Ticket created Once per new ticket. Routing, auto-assign, welcome reply.
Ticket updated Whenever any field changes. changedFrom / changedTo available in the rule context.
Comment added On each comment. commentIsInternal lets you branch on internal vs public.
Schedule (every 5 min) Walks every open ticket every 5 minutes. The path for "remind after N days" / "auto-close N hours after resolved" — no event needed, just time elapsed.

Conditions

The condition picker exposes these fields:

  • Status / Priority / Source — enum, with operators is / is not / is one of (comma-separated). Status options are OPEN / IN_PROGRESS / RESOLVED / CLOSED; Source options are EMAIL / PORTAL / AGENT.
  • Assignee ID / Customer ID / Contact email / Ticket type ID / Title / Description / Has tag (id) — string, with operators is / is not / contains / is set.
  • Is unassigned / Is merged dupe / SLA breached / Comment is internal — boolean.
  • Time since created / updated / resolved / customer reply / any reply — duration, with operators is more than / is at least / is less than / is at most. Entered as days + hours + minutes; stored internally as minutes.

The builder UI exposes the fields above. The engine additionally understands changedFrom / changedTo references on the TICKET_UPDATED trigger, though there is no dedicated picker row for them.

Conditions combine with AND. Leave empty to fire unconditionally on the trigger.

Actions

  • Set status / Set priority / Set assignee / Set ticket type — direct field writes
  • Add tag / Remove tag — auto-creates the tag if missing
  • Add comment — internal or public, supports {{ticket.title}} / {{ticket.id}} / {{ticket.contactEmail}} placeholders
  • Send email — via SMTP, recipient = customer / assignee / a literal address; subject + body templated
  • Stop further rules — halts the chain (Outlook-style)

Actions run in order. A SET_STATUS = RESOLVED followed by SET_PRIORITY = LOW reads the new status when the priority action runs.

Quick-start templates

/admin/helpdesk/rules opens a 📋 Quick-start templates drawer with:

Template What it does
📧 Remind customer after 3 days of silence Sends a templated email when minutesSinceLastCustomerReply > 4320.
🔒 Auto-close 48 hours after RESOLVED Flips RESOLVED tickets to CLOSED once minutesSinceResolved > 2880.
🚨 Tag URGENT-priority tickets on creation Adds an urgent tag for queue filtering.
⚠️ Internal note when ticket sits unassigned > 2 hours Adds a triage-delay note.

Click a template to open the form pre-filled — edit before saving.

Builder UI

The form has three sections:

  1. Name & description — what to call the rule.
  2. Trigger picker — one of the four triggers above. The hint under the dropdown describes the trigger semantics.
  3. Conditions builder — repeat-add typed rows. Each row has a field dropdown, operator dropdown (filtered to operators the field's kind supports), and a value input that adapts to the field type (enum dropdown, days+hours+minutes spinner, etc.).
  4. Actions builder — repeat-add typed rows. Each action shows only the params it actually accepts (e.g. Set status shows just a status dropdown; Send email shows recipient + subject + body).

📷 Screenshot placeholder: screenshots/admin-helpdesk-rules.png

Run history

Every rule evaluation is recorded in a per-rule run log (the helpdesk_rule_runs table). The rule card also shows a lifetime fired N times counter and the last-run timestamp. Click ▾ Recent runs on a rule to see the last 100 entries:

Column Meaning
When Timestamp of evaluation
Status MATCHED (conditions true, actions ran) / SKIPPED (conditions false) / ERROR
Ticket Link to the ticket the rule fired on
Notes JSON of which actions ran or which condition failed

Engine internals

  • Conditions and actions are stored as JSON-as-TEXT on the helpdesk_rules row. Adding a new comparator or action type means appending to the engine's FIELD_META / action switch — no schema change.
  • The scheduled tick runs every 5 minutes from helpdesk-service (HELPDESK_RULES_TICK_MS env override available).
  • Event triggers (CREATED / UPDATED / COMMENT_ADDED) are fired non-blocking from tickets.service.ts — a misconfigured rule can't fail a ticket write.
  • Cycle protection isn't currently needed: the engine doesn't automatically re-trigger UPDATED on its own writes (Prisma write doesn't loop back through the helpdesk service's mutators).

⚠️ Caution. Send email recipient customer resolves to ticket.contactEmail, falling back to ticket.contact.email. If both are null the action errors and is logged — no silent drops.

Permissions

Action Role
View rules + run history any helpdesk user
Create / edit / delete admin

See also

Still need help?

Log a support ticket and the team will pick it up from this page.