Data pipelines, LLM integration, and n8n workflows with real error handling. I take a messy internal process and turn it into something that runs every day without you watching it.
An anonymized production system I built and still maintain. It turns a raw list of target companies into personalized, verified outreach, and keeps running on its own.
The system ingests target companies, then enriches each contact through a cascade of enrichment providers (Prospeo, Apify) so it always has the best available email before spending a cent on the model. Every contact runs through an LLM personalization step with strict schema validation, so nothing hallucinated ever reaches a real prospect.
Failed lookups are caught and retried instead of silently dropping. The whole flow is orchestrated in n8n over a Postgres backend on Railway, feeding clean records into the sending layer. It was engineered to run at 1,500 leads a day on a lean, predictable tooling budget.
Retrieval grounded in your own data, tool calling, and schema validation on every output. The model answers from what it retrieved, so it stays factual instead of confident and wrong.
Ingestion, webhooks, retries, and error branches wired into flows you can actually read. I clean up brittle workflows and make them recover on their own.
Python and Node services, Postgres, and third-party API integration with queueing and retry logic. The plumbing that holds when traffic and edge cases show up.
Shipping to Railway or Vercel, environment config, logging, and staying on after launch. Systems drift, so I keep them running instead of handing off and vanishing.
Fail loud, then recover. If something can break silently, it eventually will. I make failures visible and give the system a way back.
Validate before you trust. No LLM output moves downstream until it passes a schema check. That is what keeps hallucinations out of real operations.
Documentation you can read. You get a short, clear explanation of what runs, why, and how to change it. Not just a repo you cannot touch.
I stay after launch. APIs change, data shifts, edge cases appear. I keep the system alive instead of disappearing at handoff.