A self-hosted support desk that triages itself
A support desk is three moving parts: something that receives mail, something that turns it into a conversation, and something that decides whether to wake you up.
The shape
Inbound mail arrives at a provider that can deliver it to a webhook rather than a mailbox. That webhook lands in an automation workflow. The workflow finds or creates the contact, finds or creates the conversation, and posts the message. Then a second stage classifies it and decides whether to alert.
Keeping receipt and triage separate matters. If classification fails, the ticket still exists. Combine them and a bad model response loses the customer's message.
Threading is the hard part
Getting the first message in is easy. Keeping a reply attached to the original conversation is where implementations fall down.
Match on more than one signal: the sender address, the normalised subject with reply prefixes and any ticket reference stripped, and the message identifier headers where present. Store the identifier you sent so the reply can be tied back deterministically rather than guessed.
Deduplicate explicitly
Webhooks get retried. Without a guard, one email becomes three tickets. Keep a short list of processed message identifiers and drop anything already seen. This costs almost nothing and prevents an embarrassing class of failure.
Triage is a classifier, not an author
Use the model to categorise and prioritise, not to reply unsupervised. Ask for a small fixed set of categories and a priority, and make it return structured output you can act on. A free text summary is pleasant and unusable.
Then act on the classification mechanically: label the conversation, set priority, and alert only on the urgent ones. The value is not the intelligence, it is that everything arrives sorted.
Alert on exceptions only
If every ticket pushes a notification, you stop reading notifications and the system is worse than nothing. Alert on urgent classifications, on bounces, and on failures of the pipeline itself. Everything else waits for you to look.
The traps
- Machine mail. Notification senders, delivery reports and your own outbound copies will all open tickets unless explicitly excluded. See our separate note, because the naive filter misses most of them.
- Auto reply loops. If your acknowledgement triggers their acknowledgement, you have built a mail loop. Never acknowledge anything that looks automated.
- Sending identity. Replies must come from an address that accepts replies and is verified for sending. It is easy to end up sending from a domain that cannot receive.
Need help with any of this?
These notes are free and always will be. If you would rather someone just set it up, or you are stuck on something similar, get in touch at hello@opsira.io.