Blog

How I stopped missing positive replies in a GTM workflow

A lead replied to one of my client’s LinkedIn campaigns, and the reply never reached the Google Sheet it was supposed to land in. That sheet is the client’s list of leads who said yes. Their average contract is worth over a hundred thousand dollars a year, so a positive reply that nobody follows up on can cost them a contract that size. This time the client caught it, because OutFlo also posts every campaign reply to their Slack.

The workflow is for a GTM client that runs cold email through Instantly and LinkedIn outreach through OutFlo. Both tools send replies to the same n8n workflow through webhooks. Each source has its own step to clean up the data, and after that they share one path: match the reply to a known lead, decide whether it’s positive, and queue it if it is. A scheduled job then writes the queued replies to the sheet with the lead’s name, the campaign name, the source, the email address or LinkedIn URL, and the reply itself.

Deciding what counts as positive is the hard part. My first version used regex, and that wasn’t good. So I switched to an LLM, GPT-6 Luna, and it still missed replies.

The replies it missed were short. The campaign’s message ends by offering to send a one-page plan, so a lone 👍, a “sure” or a “happy to see it” all mean yes. Read without the question they answer, none of those looks like a lead saying yes, and that’s how both the regex and the model saw them.

Around then Typesafe AI released Jev, which I think is one of the best classification models out there. I tested it against Luna on 36 replies, each with a hand-checked label: 13 real OutFlo replies, 11 real Instantly emails and 12 made-up edge cases. Jev got all 36 labels right and Luna got 34. Both caught all 20 positive replies, and neither marked any of the other 16 as positive. Luna’s two misses were a factual correction it called negative and a lead questioning who the sender was, which it called uncertain; both were neutral. Jev was also faster in that run, about 0.7 seconds per batch against 2 to 2.5 for Luna, and it cost slightly less.

Most of the fix was in the prompt, though. Jev’s own early misses came from a prompt that didn’t say what the campaign had asked. The new prompt includes the campaign’s offer and says a short yes accepts it. It also separates a person mentioning they’re on leave from an automatic out-of-office reply, and counts a request to follow up at a specific later time as positive. The same prompt made Luna better too.

I kept Jev in the live workflow. Only a positive label moves a reply forward. If Jev returns a missing or malformed label, the workflow throws an error instead of assuming the reply is positive, and the call to Jev retries up to three times when it fails. Instantly’s flag for machine-generated responses still keeps auto-replies out before they reach the model.

Thirty-six replies can’t prove it will never miss one, so the next step is to label new real replies, especially negatives and out-of-office notices, and rerun the comparison on them before I change the live prompt again.

The Jev version has been live for two weeks, every positive reply in that time has landed in the sheet, and the client is happy. Their team no longer has to hope someone spots a yes in Slack, and with contracts that size, one yes left to go cold can be a whole year of revenue lost.