If you use AI to read client replies, the clear yes and the clear no are easy. The reply that causes trouble is the mixed one: “Looks good, but can you change the logo?” A lot of classifiers call that approved. The task moves to done and the logo change gets lost.
Two checks fix most of this, and you can add them to any workflow:
- Ask the model for the exact sentence it based its decision on, not only a label, and ask it to say whether the approval has any conditions.
- In a Code node, confirm that sentence really appears in the email. Accept an approval only when the quote is found and there are no conditions. Everything else goes to a person.
A minimal version of the quote check (Code node, Run Once for Each Item). Change emailText and quote to your own field names:
const clean = (t) => (t || '').toLowerCase().replace(/\s+/g, ' ').trim();
const email = clean($json.emailText);
const quote = clean($json.quote);
return { json: { ...$json, quoteFound: quote.length > 0 && email.includes(quote) } };
My full version does this for ClickUp: it emails the client when a task reaches review, reads the reply, moves the task to approved or revisions, and turns requested changes into a checklist. You can find it in the n8n template library under my name.
Would your workflow count “Looks good, but can you change the logo?” as approved, send it to a person, or have you never tested it? And what is the most confusing reply a client has sent you to a review request? Leave the names out and post it here.
إعجاب واحد (1)
One thing worth adding to the quote check: strip the quoted history from the reply before you run it. Most clients reply on top of your original review email, so emailText often still contains your own message underneath (“Please reply with approved or tell us what to change”). The model can then quote a sentence that came from you, and the includes() check passes because that sentence really is in the email.
Cutting the body at the first “On … wrote:” line or the first line starting with “>” before both the AI step and the Code node fixes most of it. Outlook replies use a “From:” / “Sent:” block instead, so it’s worth checking for that too.
The other reply that trips classifiers here is the short one with a late addition: “Approved!” in the first line, then “oh and the date on page 2 is wrong” three lines later. Asking for conditions like you do catches it, as long as the model sees the whole reply and not just a preview snippet.
Yes, you are right, the snippet in the post does not do that. I kept it short for the post, but anyone copying it should cut the quoted part first.
The template itself cuts the old emails and my own review email before anything reads the reply. And for the “Approved! oh and the date on page 2 is wrong” kind of reply, it does not just trust Claude. If Claude says approved but also lists a change, it comes to me to check.
Have you dealt with clients who answer inline, inside the quoted email? That one still bothers me, because cutting at the first quoted line would lose half their answer.