Projects
What I've actually built, not a skills list.
Why I built this
Anyone can list "n8n" and "Salesforce" on a resume. I wanted a page that shows the work instead of describing it, so I gave myself a real n8n instance, a real Salesforce org, and a fictional company to build for — then committed to one new automation a day. Nothing here is staged after the fact: every workflow below ran end-to-end against live data, and the screenshots are from the actual runs.
Turning Buying Signals Into Outreach
~3 min read
A rep drops a buying signal in Slack; Claude drafts two ready-to-send outbound sequences in seconds, then turns an approval into real Gmail drafts.
Turning Buying Signals Into Outreach
~3 min readA rep drops a buying signal in Slack; Claude drafts two ready-to-send outbound sequences in seconds, then turns an approval into real Gmail drafts.
The problem
Reps see buying signals constantly — a funding round, an acquisition, a leadership change, a security incident at a target account — but turning a signal into a genuinely differentiated outbound sequence takes more time than most reps have in the moment. So the signal gets a LinkedIn like instead of a sequence, and the window passes.
The build
An AI agent lives in a Slack channel. A rep @mentions it with a plain-language signal — "Paramount just bought Warner Bros." — and Claude classifies the signal type, then drafts two complete, genuinely different 3-touch outbound email sequences: Angle A leads with risk/urgency framing, Angle B leads with a consultative/relationship framing. Both post back into the Slack thread within seconds, grounded in a real company context (below) so the copy references actual products and competitive positioning instead of generic filler.
From there it's an actual review loop, not a one-shot generation. The rep can reply in-thread with a plain instruction — "make angle B shorter" — and the agent edits just that angle using per-thread conversation memory, then reposts only what changed instead of re-flooding the thread with both angles again. When a rep reacts with ✅ on the angle they want, the workflow logs the approval, confirms it in-thread, and splits that angle's three touches into three separate Gmail drafts — each with its own real subject line and no leftover Slack instructions — ready to review and send. Every draft, edit, and approval is logged to an n8n Data Table for an audit trail, and a shared error-handling workflow alerts Slack and logs any node failure automatically.
Company context
Every draft is grounded in a fictional company I built specifically for this project — Fortavault, Inc., a data protection and security platform — so the agent has real products, industries, and competitors to reason about instead of writing in a vacuum.
Products
- Fortavault Backup Cloud — cloud backup & disaster recovery
- Fortavault Shield — ransomware detection, isolation, one-click rollback
- Fortavault Access — zero-trust endpoint access control
- Fortavault Insights — compliance & audit reporting (HIPAA, SOC 2, GLBA)
Industries served
Competitors & how Fortavault wins
- Veyron Data (backup/DR) — faster to recover, simpler SaaS-data setup
- Ashcombe Systems (ransomware detection point solution) — Fortavault pairs detection with backup for one-click recovery
- Cyphertide (zero-trust access) — better suited for regulated industries needing audit-ready logs
- Northgate Cloud Security (broad platform incumbent) — more focused roadmap, faster implementation
- Ridgeline Compliance (compliance reporting point tool) — Fortavault Insights is natively integrated with backup/security data
Live run
Impact (measured from live runs)
Bringing Dead Deals Back to Life
~3 min read
A daily scan flags old lost deals worth a second shot, drafts the re-engagement pitch, and waits for a rep's Slack approval before reopening anything.
Bringing Dead Deals Back to Life
~3 min readA daily scan flags old lost deals worth a second shot, drafts the re-engagement pitch, and waits for a rep's Slack approval before reopening anything.
The problem
Closed Lost opportunities pile up in Salesforce and get forgotten — even the ones that were lost for reasons that don't hold up six months later. A budget freeze thaws. A champion who left gets replaced by someone inheriting the exact same problem. Nobody has time to manually comb through the Closed Lost list and guess which dead deals are actually worth a second look, so they just stay dead.
The build
A daily scheduled scan queries Salesforce for every Closed Lost opportunity. Claude reviews each one against its stated loss reason and how much time has passed, deciding whether it's worth re-engaging — deliberately instructed to be selective, since most closed-lost deals shouldn't be resurrected. For anything flagged worth resurrecting, Claude drafts a short re-engagement angle grounded in real Fortavault products and competitive positioning, then the workflow sends an interactive Slack approval message for that one deal — reopen it, or skip it.
On approval, the opportunity is reopened in Salesforce (moved back to Qualification, close date pushed out 90 days), a high-priority follow-up task is created with the drafted angle as the task description, and every decision — approved, declined, or skipped — is logged to an n8n Data Table for a full audit trail. When a run flags more than one deal at once, each gets its own independent Slack approval cycle in sequence rather than being bundled into a single wait — a real bug I hit and fixed mid-build, after the first multi-deal run silently dropped the second approval.
Assessor system prompt
Same Fortavault context as above, with a different job: be skeptical by default, and only surface deals with a genuine, time-sensitive reason to revisit.
Live run
Impact (measured from live runs)
Support Triage That Knows Who's Asking
~3 min read
An inbound support email gets read by Claude, matched to the right Salesforce account, and either escalated, routed, or quietly queued depending on who sent it and how urgent it actually is.
Support Triage That Knows Who's Asking
~3 min readAn inbound support email gets read by Claude, matched to the right Salesforce account, and either escalated, routed, or quietly queued depending on who sent it and how urgent it actually is.
The problem
Most support triage treats every inbound ticket the same way: same queue, same SLA clock, same Slack noise, regardless of whether it's a trivial question from a small account or a fleet-wide outage at an enterprise customer mid-renewal. That flattening cuts both ways — teams either over-alert on things that don't matter, or bury a genuinely urgent ticket from a top account in the same pile as a "how do I export this" question.
The build
There's no live customer support inbox connected for this sprint, so the trigger is a scoped Gmail watch that only fires on test emails carrying a demo subject tag — a stand-in for a real support alias. Everything after that runs live: a real Salesforce lookup, a real Claude call, a real Case, a real Slack message. When a matching email lands, a Code node parses out the sender's stated email and the message body, then Salesforce is queried for a matching Contact. If one exists, the linked Account's AnnualRevenue determines a customer tier — Enterprise, Mid-Market, or SMB — computed from real seeded Salesforce data, not a hardcoded label.
Claude reads the email and classifies it on two axes: category (Security
Incident, Technical Issue, Billing/Account, or Feature Request/General)
and priority (Urgent/High/Normal/Low), grounded in Fortavault's product
line so it can tell a real outage report from a feature ask. A routing
step then combines category, tier, and Claude's priority into the
routing decision: a Security Incident always escalates immediately regardless of
tier; an Enterprise account with an urgent issue gets a 1-hour SLA and an
@here Slack ping; a low-priority ticket from a small account
gets a 2-business-day SLA and no Slack ping at all — it's logged and
queued, not dropped. Every ticket gets a real Salesforce Case created
either way, and every decision is logged to a Data Table for an audit
trail of what got escalated, what got queued, and why.
Routing logic
Category, tier, and priority don't just stack — they interact:
Live run