Sharing something I built to kill manual lead hunting - an n8n setup (3 workflows) that runs the whole top of funnel with the Anthropic Claude API.
01 - Scrape + AI-qualify
Google Places (Text Search) pulls businesses for a niche + city
An HTTP Request node sends each to Claude, which scores it 1-10 as a prospect with a one-line reason
The trick that made it reliable: prompt Claude to reply ONLY as JSON like {“score”: 8, “reason”: “…”} so a Filter node can branch on it cleanly - no fragile text parsing
Qualified leads get appended to a Google Sheet
02 - Personalized cold email
Reads the sheet, has Claude write a personalized email per lead, sends on a daily cap, marks each so nobody is emailed twice
03 - Inbound router
A webhook for your contact form: Claude scores + summarizes each submission and pings you in Slack on the hot ones
Runs on Claude Haiku so it is about $0.001 per lead - basically free to run.
Happy to share the core scraper + qualifier template - just reply and I will drop the JSON. I also packaged the full 3-workflow version with a setup guide here if it saves anyone the wiring: Your First Qualified Lead in 15 Minutes - Without Hiring a VA
The JSON-mode prompt trick for the scorer is the right call - forcing a structured response like {"score": 8, "reason": "..."} and then branching on it with a Filter node is much more robust than parsing free-text output, especially at scale. One small addition worth considering: add a fallback branch in your Filter node for cases where Claude returns malformed JSON (it’s rare with Haiku but happens under token pressure), so those leads get flagged rather than silently dropped.
Nice setup, and forcing the scorer into JSON is the right instinct. One upgrade worth knowing about is that instead of prompting Claude to “reply ONLY as JSON,” you can have the API guarantee the shape for you. Anthropic shipped Structured Outputs, where you pass an output_format with a JSON schema and the response is constrained to match it during decoding, so malformed JSON stops being something you have to catch (Structured outputs - Claude API Docs). Check model support before wiring it in, since it landed on the larger models first and you’re running Haiku. The fallback that works broadly is to define the score as a tool’s input_schema and force it with tool_choice, which gets you the same schema guarantee through tool use. Either route lets you drop the “please return JSON” line and the malformed-output branch the other reply raised.
The other thing I’d look at is the “marks each so nobody is emailed twice” step, specifically the order of the send and the mark. Send first and write the marker after, and a failure in between re-emails that lead next run. Mark first and the send fails, and you skip them with no trace. Neither is wrong, but it’s worth deciding which way you want it to fail. For outbound I lean toward marking only after a confirmed send and storing the provider message id as the marker, so the record proves the email actually went out rather than just that the workflow reached that node.
Runs great otherwise, and Haiku at that price for the scoring pass is a smart call!