Designed, built and operated by one engineer. It scans job boards, scores every prospect against a strict ideal-client profile, writes each email from the company’s verified tech stack — and follows up on its own.
A pipeline is a graph of steps assembled from a node registry — discovery, guards, enrichment, branching, actions — each one configured rather than written. The flow below is a real one: a new audience means a new graph, not a new codebase. It mixes autonomous tool-using agents where judgment is needed with deterministic steps where consistency and auditability matter more.
Materialises a batch of leads. The only node type that runs once per run instead of once per lead.
Runs before the per-lead phase and stamps every row it creates with the pipeline id, so throughput and send caps stay attributable. Skipped entirely when the trigger already supplied lead ids.
{ "leadIds": ["8f2c…", "b104…"],
"source": "apify_google",
"inserted": 42, "deduped": 7 }Cross-pipeline 30-day cooldown, plus a hard unsubscribe stop.
Resolves the lead to an identity — email address, optionally company domain — across every lead row, not just this one. Two pipelines sharing an ICP will otherwise both email the same person imported twice under two ids. Placed first because a lead that must not be contacted should never have been researched either.
{ "dedupe": { "passed": false,
"reason": "cooldown",
"matched_on": "domain",
"last_contacted_at": "2026-08-14" } }Waterfall lookup, then tool-using agents that read the prospect’s own site.
The deep-diver is a real multi-turn loop: it fetches a page, decides what to read next, and repeats under a page budget. It is confined to the lead’s own hostname — an agent free to follow outbound links will quietly start auditing somebody else’s site on your token budget.
{ "enrichment": { "email_risk": "low" },
"audit_points": [
{ "area": "capture", "severity": "high",
"finding": "No enquiry form on /services" } ] }Folds the run’s findings onto the lead profile so they outlive the run.
Context exists only for the duration of one run. This node merges it under a namespace inside raw_data — never replacing the original import payload — and writes mapped values onto real columns through a whitelist, so a config edited in the builder can never reach unsubscribed or pipeline_id.
{ "crm_write": {
"fields_written": ["company", "website"],
"context_keys": ["research", "audit_points"] } }Qualification agent scores 0–10; the branch reads the score and splits.
Branches are generic field / operator / value tests against the accumulated context, evaluated top to bottom with first match winning. Nothing about scoring is special-cased — any numeric or boolean a step writes can route a lead with no schema change.
{ "qualification": { "score": 8,
"passed": true,
"reasons": ["WordPress 5.4, unpatched",
"hiring 2 sales roles"] } }Writes the email from what the audit actually found.
Takes the angle from step config rather than a hardcoded campaign switch, which is what lets one registry node serve a web-dev pipeline and a logistics pipeline without a fork.
{ "personalization": {
"subject": "the /services form on …",
"opening_line": "Noticed your quote form …" } }Resend, under this pipeline’s own daily cap.
The cap is fail-closed: if the count query errors it reports the day as full. An unknown send count read as “nothing sent yet” is how a whole batch escapes on an already-full day.
{ "sent": true, "message_id": "re_9f…",
"cap_remaining": 11 }Parks the lead in the database, not in memory.
Holding a lead in process memory for three days assumes a process that lives three days; this one sleeps on a free tier. The lead is parked with resume_at and the step it should resume at, and a sweep re-enters the pipeline for it once the time passes.
{ "wait": { "resume_at": "2026-09-04T09:00Z",
"delay_minutes": 4320 } }A second touch by email, or a human task card if the channel is LinkedIn.
Where the channel cannot be automated, the pipeline stops being an autopilot and becomes a queue: a Slack card with the drafted note, under its own daily cap, because silently flooding human work is the expensive failure here.
{ "sentiment": { "category": "interested",
"confidence": 0.82 } }The lead stops here, and the run records why.
An explicit early exit, kept distinct from a failure in the step contract. A correctly-rejected lead is the pipeline working; routing it down the failure path would misreport the run and bury real errors.
{ "status": "stopped",
"stop_reason": "score 4 below threshold 7" }The portal shows the full funnel — who was found, why they scored what they scored, what was written, when it was opened. Rejection is a feature: leads that don’t fit the profile are disqualified with a stated reason and never emailed.
→ real interface · live data · details redacted
I design and ship AI agent systems, custom WordPress / WooCommerce engineering, and modern web platforms — end to end, as one engineer.