AI Adoption GuideSupportInvestigate
Root-cause clustering across tickets
Embedding clustering groups tickets that share an underlying defect so support can batch analysis, updates, and escalation.
Support processIntakeTriageAssignInvestigateResolveConfirmClose
By Don, DoneThat’s AI coach · updated
Decide what gets embedded before anything gets grouped
Clustering quality is mostly an input problem. Raw ticket text is full of greetings, signatures, quoted replies, and macro language that every ticket shares. Left in, that boilerplate pulls unrelated tickets together because they all end with the same closing line. Strip it first, and keep the parts that carry the failure: the customer's description, extracted error strings, and product surface.
Structured fields belong in the grouping as well as the text. Product version. Region. Plan. Device or integration type. Time of first report. These fields are often what separates two clusters that read identically. A grouping built on prose alone will merge a defect on one firmware release with the same symptom on another.
Set the thresholds and the minimum cluster size in advance. Two tickets are a coincidence in most queues. Decide what count makes a group worth a human look, and what similarity score qualifies a ticket for membership. When a ticket sits below the bar, it stays ungrouped rather than joining the nearest cluster. An ungrouped ticket is honest. A forced membership corrupts the count that people will act on.
A cluster earns its cause label from one confirmed member
Groups form on similarity, which is a statement about wording and fields. Cause is a statement about the product. Getting from one to the other takes work that the clustering does not do. Someone picks a representative ticket and investigates it properly, using logs, billing, and status systems or a reproduction attempt.
Once one member has a confirmed cause, the cluster gets a provisional label and a membership test. The test is the useful artifact. It names the observable condition that makes a ticket part of this group: a specific error code, a version range, a configuration value. Tickets that meet the test belong. Tickets that only look similar do not, and they should be moved out.
Track the shape of the group over time. A cluster that grew for three days and stopped behaves differently from one adding tickets every hour. First-seen and last-seen timestamps, plotted against release dates, often point at the change that caused it. Longer-run patterns across the whole corpus are a separate reporting job, closer to contact-driver reporting on closed tickets.
Group 47 missing-production reports at a solar monitoring vendor
The following situation is fictional. A company sells monitoring hardware and an app for residential solar installations. Homeowners and installers file tickets when the app shows no energy production for a site that is clearly working. These reports arrive constantly, and most are ordinary connectivity problems.
Clustering over the last two weeks produces one group of 47 tickets. The members share a phrase pattern about production data stopping overnight, plus three structured fields: gateway firmware 4.2.1, a cellular data plan rather than home wifi, and installation dates inside a six-week window. Ninety other missing-production tickets from the same period stay outside the group.
An engineer investigates one member. The gateway is online and reporting, but its uploads carry timestamps in the wrong timezone after a scheduled reboot. The server drops readings dated in the future. That is a confirmed cause for one site. The cluster label becomes provisional, and the membership test is written down: firmware 4.2.1, cellular connection, and at least one upload rejected for a future timestamp.
Applying the test moves four tickets out and pulls in six that clustering had missed. The group is now 49 tickets with a stated condition, one confirmed instance, and a list of affected sites. That package is what goes to engineering. Filing it is the structured handoff at the end of the workflow, with the confirmed member linked as evidence.
What makes clusters look real when they are not
Boilerplate builds phantom groups. When agents use the same macro on many tickets, the reply text dominates the embedding and the group forms around the macro. Cluster on the customer's words and the extracted fields, not on the whole conversation.
One large account can look like an outbreak. A single enterprise customer filing thirty tickets about one internal rollout will form a tight cluster that affects nobody else. Report distinct accounts next to ticket count, and treat a group of thirty tickets from one account differently from thirty accounts with one each.
Clusters merge as they grow. Two defects with similar symptoms often start apart and drift together once the group is large. Re-check the membership test whenever a cluster doubles in size. If the test no longer separates the members cleanly, split the group and pick a new representative for each half.
Old clusters never die. A group formed six months ago keeps collecting tickets after the fix shipped, because the wording still matches. Close clusters explicitly when the defect is resolved, and let new reports form a new group. Stale clusters make the queue look worse than it is and hide the fresh signal underneath.
Real-time duplicates are a different mechanism. Matching a brand new ticket to an active incident happens at the moment it arrives, through incident-wave detection at intake. Clustering across the corpus runs on a slower cycle and answers a broader question.
Naming a cluster and acting on it stay with a person
A support lead names every cluster and owns its label. The system proposes the group; the human writes what it is called and what the membership test says. Auto-generated cluster names drift into vague phrases that nobody can act on, and two teams end up meaning different things by the same title.
Escalation is a decision with a cost. Filing a defect commits engineering time, so it needs a person weighing size, revenue exposure, and how solid the confirmed member is. A cluster of eighty tickets with no explained instance is a research request. One with a reproduction attached is a bug report, and a probe against a test account is often what closes that gap.
Customer messaging is the last thing to automate here. Telling 49 sites that their problem is a known firmware issue is a commitment about cause and timing. It should come from a named owner who has read the confirmed evidence, not from cluster membership alone. Being wrong in a broadcast costs more trust than being slow in one reply.
Is this worth automating for you?
Whether this pays back depends on how much time it takes your team today. Most teams estimate that from memory, and the estimate is usually wrong in one direction or the other. This one is rated high effort to implement, so the baseline matters more than usual.
DoneThat reconstructs where the time actually went, with no timers to forget, so you can measure the baseline before committing to a project and check the gain afterward.
Measure the baseline first