A working reply classifier, and the measurements behind it

Sorting cold email replies automatically, and knowing whether it is right

Pulling replies out of an inbox and labelling them is the easy half. The half that decides whether you can actually stop reading the inbox is whether you can prove the labels are right, and know what it costs you when they are not.

This page is a classifier that runs, on 54 replies, scored against labels set in advance. It shows the accuracy per class, the confusion matrix, every call it made, and the ones it got wrong. It also shows two things that came out of building it that were not obvious going in.

What it does, on this sample

53 / 54
correct, scored against labels written before the model saw anything
98.2%
overall accuracy on the realistic set
54 / 54
identical labels across 5 full reruns
1.46s
median time per reply, one API call each
$1.073
per 1,000 replies at list token prices

Seven classes, because five was not enough to route on. The split that matters most is between a reply that is declining and a reply that is deferring, and between a reply that is declining and a reply that is asking to be removed. Those three land in different places and one of them has a legal edge.

ClassWhere a correct call sends itWhat a wrong call costs
InterestedNotify (Slack) and flag for review. Nothing auto-sends.A missed one is a lost deal. This is the expensive direction.
Not nowCRM: set a follow-up date from the reply, drop from the live sequence.Cheap if it lands in review. Expensive if it is filed as a hard no.
Not interestedCRM: closed, suppressed from future sends.Cheap. Worst case someone reads a dead reply.
ReferralNotify, with the named person pulled out for a new contact record.High. A referral is a warm intro that expires quietly.
Out of officePause the sequence until the stated return date. No notification.Low, unless it is filed as a hard no and the person never gets a follow-up.
UnsubscribeSuppress immediately, write to the compliance log. No notification.The only class with a legal edge. A miss here is worse than a miss anywhere else.
BounceSuppress, increment the domain-health counter for that domain.Low individually. Ignored in bulk, it is how a sending domain dies.

Nothing in any branch sends anything to a prospect. Positives are flagged and notified so they can be looked at first.

The first version of this test was wrong

The first corpus was 44 clean, one line replies. The classifier scored 44 of 44 on it. That looked like a good result until the control arm ran: a plain list of keyword rules, no model at all, scored 42 of 44 on the same set.

If a regular expression scores 95.5%, a model scoring 100.0% has not been shown to be good. It has been shown that the test was too easy to tell the two apart. A test where every arm sits at the ceiling cannot report a difference, so its result means nothing in either direction.

The reason the clean set was easy is that real replies do not look like that. They arrive with the original outbound quoted underneath, a signature, a mobile footer, and the actual answer top posted in a line or two. So the corpus was rebuilt: same replies, same labels, wrapped in that furniture, plus 10 more replies where the correct label is genuinely arguable rather than obvious.

The quoted outbound is the interesting part. It is sales copy, so it is full of exactly the words a rules pass keys on. On the rebuilt set the rules drop to 44 of 54 (81.5%), and the gap opens up:

ArmCorpus CorrectAccuracy
Keyword rules, no modelclean, one line replies 42 / 44 95.5%
Modelclean, one line replies 44 / 44 100.0%
Keyword rules, no modelrealistic, quoted threads and signatures 44 / 54 81.5%
Modelrealistic, quoted threads and signatures 53 / 54 98.2%

The rules do not fail evenly, which is the part that matters for routing. Their worst class is referrals, at 0.5 recall: they miss half of them. A referral is a warm introduction with a named person in it, and it expires quietly if nobody sees it. The cheap failure mode and the expensive one are not the same failure mode.

Accuracy, per class

Overall accuracy is the least useful number here. What decides whether this is usable is whether it is accurate on the classes where being wrong is expensive.

ClassRepliesPrecisionRecallF1False posFalse neg
Interested91.01.01.000
Not now80.8891.00.94110
Not interested81.01.01.000
Referral81.00.8750.93301
Out of office71.01.01.000
Unsubscribe71.01.01.000
Bounce71.01.01.000

Confusion matrix

Rows are the true label, columns are what the classifier called it.

Actual \ PredictedInterestedNot nowNot interestedReferralOut of officeUnsubscribeBounce
Interested9000000
Not now0800000
Not interested0080000
Referral0107000
Out of office0000700
Unsubscribe0000070
Bounce0000007

Every reply it got wrong

H-46 called it Not now, the label says Referral, confidence 0.72 label arguable

I have forwarded this internally. If it is of interest to anyone here they will get in touch.

Forwarded to an unnamed person with no commitment. Arguably not_interested with a courtesy, arguably a referral with no name attached.

Both models were wrong only on replies from the arguable group, and never on a reply whose label is clear cut. That is the good version of this result, but it is also a small number: one error in one arm and two in the other is nowhere near enough to state an error rate. It shows where the errors live, not how often they happen.

Every call, all 54 replies
IdReply (first line)Called itConfQuoted evidence
H-01
Re: cutting your dock idle time Yes, this is a live problem for us right now. Can you send over what a rollout would look like? I have half an hour Thursday or Friday afternoon.
Interested0.98Yes, this is a live problem for us right now. Can you send over what a rollout would look correct
H-02
Re: quick question about your intake process send it
Interested0.95send itcorrect
H-03
Re: reducing your quote turnaround What does pricing look like for a site with about 40 people? We would need it to sit alongside the ERP we already run, not replace it.
Interested0.95What does pricing look like for a site with about 40 people? We would need it to sit alongcorrect
H-04
Re: the reconciliation thing Happy to talk. Fair warning, we looked at two other tools last year and neither survived contact with our actual data, so I will be blunt about what w
Interested0.95Happy to talk. Fair warning, we looked at two other tools last year and neither survived ccorrect
H-05
Re: following up Timing is good actually. Who else in our space are you working with?
Interested0.95Timing is good actually. Who else in our space are you working with?correct
H-06
Re: intake triage I am interested, but I am not the one who signs off. Send me something I can forward to our managing partner and I will push it.
Interested0.95I am interested, but I am not the one who signs off. Send me something I can forward to oucorrect
H-07
Re: your inbound routing Yes please. Calendar link?
Interested0.99Yes please. Calendar link?correct
H-08
Re: worth a look? Not right now, we are mid migration and nobody has the bandwidth. Ask me again after the new year and I will genuinely take the meeting.
Not now0.95Ask me again after the new year and I will genuinely take the meeting.correct
H-09
Re: quick one We just renewed with our current provider for twelve months. Circle back in Q1 and I will look properly.
Not now0.95Circle back in Q1 and I will look properly.correct
H-10
Re: reply triage Interesting but the budget for this year is spent. Keep me on your list.
Not now0.95the budget for this year is spent. Keep me on your list.correct
H-11
Re: patient intake Can you check back in about six weeks? We are onboarding two new locations and I would be wasting your time before that.
Not now0.95Can you check back in about six weeks? We are onboarding two new locations and I would be correct
H-12
Re: automating the boring part Park this for now. Not a no.
Not now0.95Park this for now. Not a no.correct
H-13
Re: your quoting workflow Our fiscal year starts in April and nothing gets approved before then. If you want to send material now I will file it.
Not now0.92Our fiscal year starts in April and nothing gets approved before then. If you want to sendcorrect
H-14
Re: dock scheduling Thanks but we are all set.
Not interested0.95Thanks but we are all set.correct
H-15
Re: intake automation We built this internally two years ago and it works fine. Appreciate the note.
Not interested0.95We built this internally two years ago and it works fine.correct
H-16
Re: quick question Bold of you to assume I read cold emails.
Not interested0.92Bold of you to assume I read cold emails.correct
H-17
Re: worth 15 minutes? No thank you.
Not interested0.95No thank you.correct
H-18
Re: partnership Not looking for this, but funnily enough we sell into the same buyers. If you ever want to swap referrals let me know.
Not interested0.85Not looking for thiscorrect
H-19
Re: following up This is not a fit for how we operate. Please do not take it personally.
Not interested0.95This is not a fit for how we operate.correct
H-20
Re: intake We are a two person shop. There is nothing here to automate.
Not interested0.95There is nothing here to automate.correct
H-21
Re: dock idle time Wrong person for this. Priya runs operations and would be the one to ask. I have copied her.
Referral0.95Wrong person for this. Priya runs operations and would be the one to ask. I have copied hecorrect
H-22
Re: your reply handling Not my area. Try Dominic, he owns anything touching the CRM.
Referral0.95Try Dominic, he owns anything touching the CRM.correct
H-23
Re: patient scheduling I moved off that team in March. Kwame has it now and I think he would actually want to see this.
Referral0.95I moved off that team in March. Kwame has it now and I think he would actually want to seecorrect
H-24
Re: quoting I am not the right contact, though I will say we are happy with what we use. If you want to try anyway, Nina handles vendor evaluations.
Referral0.95If you want to try anyway, Nina handles vendor evaluations.correct
H-25
Automatic reply: Bertrand Ashgrove is no longer with Hensleigh Group Bertrand Ashgrove has left the company. For anything relating to operations please contact Rosalind Vance, who has taken over the role.
Referral0.95For anything relating to operations please contact Rosalind Vance, who has taken over the correct
H-26
Re: intake triage Forwarding this to our COO. Do not chase me, chase him.
Referral0.95Forwarding this to our COO. Do not chase me, chase him.correct
H-27
Out of office: Auto Reply I am out of the office until the 19th with limited access to email. I will respond when I am back.
Out of office0.95I am out of the office until the 19th with limited access to email. I will respond when I correct
H-28
Automatic reply: Annual leave On annual leave until Monday. For anything urgent please contact the operations desk, who are covering while I am away.
Out of office0.95On annual leave until Monday. For anything urgent please contact the operations desk, who correct
H-29
Automatic reply Thank you for your message. Our office is closed for the public holiday and reopens on Tuesday.
Out of office0.95Our office is closed for the public holiday and reopens on Tuesday.correct
H-30
Ticket #48213 received Your message has been received and assigned reference 48213. A member of the team will respond within two business days. Please do not reply to this a
Out of office0.95Your message has been received and assigned reference 48213. A member of the team will rescorrect
H-31
Out of Office Re: intake I am on parental leave until the autumn. Messages to this address are not being monitored.
Out of office0.95I am on parental leave until the autumn. Messages to this address are not being monitored.correct
H-32
AutoReply: Away Away from desk, back Thursday.
Out of office0.95Away from desk, back Thursday.correct
H-33
Re: quick question Please remove me from your list.
Unsubscribe0.99Please remove me from your list.correct
H-34
Re: following up Where did you get my details? Delete them and do not contact me again.
Unsubscribe0.99Delete them and do not contact me again.correct
H-35
Re: intake automation Unsubscribe.
Unsubscribe0.99Unsubscribe.correct
H-36
Re: dock scheduling Stop emailing me. If this continues I will report it as spam.
Unsubscribe0.99Stop emailing me. If this continues I will report it as spam.correct
H-37
Re: worth a look? Take me off whatever list this came from, thanks.
Unsubscribe0.99Take me off whatever list this came from, thanks.correct
H-38
Re: patient intake I did not opt in to this and I want my data removed under GDPR.
Unsubscribe0.99I did not opt in to this and I want my data removed under GDPR.correct
H-39
Undeliverable: quick question about your intake process Your message could not be delivered. The recipient address does not exist at this domain. Status code 5.1.1, permanent failure.
Bounce0.99Your message could not be delivered. The recipient address does not exist at this domain. correct
H-40
Delivery Status Notification (Failure) The account you tried to reach is over quota and cannot accept new messages at this time. Status code 4.2.2.
Bounce0.95The account you tried to reach is over quota and cannot accept new messages at this time. correct
H-41
Undeliverable: following up Recipient rejected. The mailbox has been disabled and is no longer in use. 5.2.1.
Bounce0.99The mailbox has been disabled and is no longer in use. 5.2.1.correct
H-42
Message blocked Your message was rejected by the recipient server policy. Sending IP is listed on a blocklist used by this domain.
Bounce0.95Your message was rejected by the recipient server policy. Sending IP is listed on a blocklcorrect
H-43
Undeliverable: dock scheduling Delivery to the following recipient failed permanently. The domain could not be found. Status code 5.4.4.
Bounce0.99Delivery to the following recipient failed permanently. The domain could not be found. Stacorrect
H-44
Automatic reply: address retired This mailbox has been retired and is not monitored. Messages sent here are not forwarded.
Bounce0.95This mailbox has been retired and is not monitored. Messages sent here are not forwarded.correct
H-45
Re: worth fifteen minutes? Leave it with me.
Not now label arguable0.85Leave it with me.correct
H-46
Re: inbound routing I have forwarded this internally. If it is of interest to anyone here they will get in touch.
Not now (should be Referral) label arguable0.72I have forwarded this internally. If it is of interest to anyone here they will get in touwrong
H-47
Re: quick question What is this actually costing me and who else runs it in freight? Not committing to anything.
Interested label arguable0.85What is this actually costing me and who else runs it in freight?correct
H-48
Automatic reply: Re: worth fifteen minutes? Thanks for your email. I am currently travelling and will pick this up when I am back at my desk. If it is about a supplier enquiry please send it to
Out of office label arguable0.95I am currently travelling and will pick this up when I am back at my desk.correct
H-49
Re: inbound routing We already do this.
Not interested label arguable0.92We already do this.correct
H-50
Re: quick question You said you would stop chasing. Please do that.
Unsubscribe label arguable0.95You said you would stop chasing. Please do that.correct
H-51
Re: patient intake Not before the audit. After that, maybe.
Not now label arguable0.92Not before the audit. After that, maybe.correct
H-52
Re: worth fifteen minutes? Send the write up rather than the call.
Interested label arguable0.85Send the write up rather than the call.correct
H-53
Re: inbound routing Not me. Ask the person who owns your account here, whoever that is.
Referral label arguable0.95Ask the person who owns your account here, whoever that is.correct
H-54
Warning: message delayed Your message has not yet been delivered. Delivery attempts will continue for 24 hours. You do not need to resend the message.
Bounce label arguable0.95Your message has not yet been delivered. Delivery attempts will continue for 24 hours.correct

Two things that came out of measuring it

1. Stripping the quoted thread is a cost saving, not an accuracy saving

Cutting the quoted original and the signature before the classifier reads the body is the obvious first optimisation. It was worth checking what it actually buys, so the same corpus ran twice, once raw and once stripped, changing nothing else.

Accuracy Input tokensCost per 1,000
Raw, quoted thread left in98.2% 47,098 $1.073
Quoted thread stripped98.2% 38,793 $0.912

Identical accuracy, 17.6% fewer input tokens. So it is worth doing, and it is worth knowing that it is a billing decision rather than a quality one. If it had been sold as the thing that makes the classifier accurate, that would have been wrong in a way nobody would have caught.

2. The confidence score is a weak review trigger. Disagreement is a better one.

A review lane for the uncertain cases is the standard answer, and the standard trigger is the model's own confidence score. On this run that score is badly bunched: most replies come back at the same high value, so a threshold either catches almost nothing or holds back a sixth of the volume.

Hold back if confidence below Share of replies heldErrors caught Errors that got routed anyway
0.60 0.0% 0 / 1 1
0.70 0.0% 0 / 1 1
0.75 1.8% 1 / 1 0
0.80 1.8% 1 / 1 0
0.90 9.3% 1 / 1 0
0.95 16.7% 1 / 1 0

Running a second, stronger model over the same replies works better. The two models disagreed on 2 of 54 replies, and those 2 were exactly the replies either model got wrong. Disagreement found every error on this set, at 3.7% of the volume.

Paying for two models on everything is wasteful though, so the built version only asks for the second opinion where the first one is unsure, and holds the reply back only when the two disagree. On this sample that is 9.3% of replies getting a second call, 2 replies reaching a human, and no error reaching a destination unreviewed. About $1.748 per 1,000 replies all in.

The cheaper model was the more accurate one here. The small fast model scored 53 of 54. The large expensive one scored 52 of 54, at 6.8 times the price. Do not read too much into that: the difference is a single reply and it is one of the arguable ones. The useful conclusion is not that one model wins, it is that this decision is cheap to test and worth testing rather than assuming.

What this does not prove

The replies are invented, and I wrote both the replies and the instructions the classifier follows. That is the single biggest caveat on this page. When the same person writes the exam and the answer sheet, a high score is partly just internal consistency. It is why the keyword control arm is on here at all, and why the honest headline is the shape of the errors rather than the percentage.

Does it give the same answer twice

The whole corpus ran 5 times at temperature zero. 54 of 54 replies came back with an identical label every time. Per run accuracy: 98.2%, 98.2%, 98.2%, 98.2%, 98.2%.

The label is also constrained by a schema with a fixed list of allowed values, so the classifier cannot return a class that does not exist. If a reply comes back unparseable, the workflow sends it to review rather than picking a default. A reply quietly filed as not interested is a reply nobody reads again, which makes defaulting the most expensive thing the pipeline could do.

The workflow

Built as an n8n workflow: 17 nodes, imported into a running n8n instance rather than drawn. The export is on this page, so it can be read node by node or imported directly.

The reply triage workflow on the n8n canvas, from the
Gmail trigger through stripping, classification, the confidence gate, adjudication and the routing
switch, out to eight destinations.
The workflow as n8n renders it. Gmail trigger, strip the quoted thread, classify, and only where the first pass is unsure, ask a second model and hold the reply back if they disagree.

Download the workflow JSON and the full measurement output, including every prediction, the confusion matrix and the per class scores.