Scattered spreadsheets became one CRM, with an AI agent drafting the follow-ups

A custom CRM on Lovable, Supabase and n8n. A Claude agent drafts outreach into Outlook and has no way to send it. The client clicks send. Every relationship, and the opportunities behind them, live in one database instead of scattered spreadsheets.

The client sources deal flow for a large US private-equity firm. The scattered spreadsheets are now one database, and an agent drafts follow-up emails into Outlook. It cannot send them.

hours a week of manual entry removed (estimated)
10+
outreach emails sent by the AI: it saves drafts and has no send path
0
to refresh the email and meeting history each weekday, in one transaction
54 s

Engineering numbers from the project's git history, test runs and session log, September 2026.

US private-equity sourcing firm, Aug 2025 to today

Before the build.

Scattered spreadsheets held the client's relationships, and every piece of outreach was logged by hand.

Nothing validated the data, and nothing flagged who had gone quiet. Email and meeting history arrived only when somebody remembered to run an export. The client needed one place for all of it, and one rule to hold.

The rule the client set first

No AI ever emails anyone on the client's behalf.

It is the reason the outreach engine has no send path at all, only a draft path.

What I built.

One database, an approval queue for agent suggestions, and an outreach engine that cannot send.

Five parts, in the order they matter to the client. The last one is the one I got wrong first.

  1. A CRM built around how the client works
  2. An agent that suggests, and a human who clicks
  3. Outreach that drafts and never sends
  4. Deals captured from the inbox
  5. The import I had to rebuild

What is true today.

  • Every relationship, and the opportunities behind them, live in one database instead of scattered spreadsheets.
  • Manual data entry is down by an estimated 10+ hours a week. That is an estimate of the entry work it replaced, not a measured study.
  • The outreach engine has drafted into the client's Outlook on its weekday schedule since 10 June 2026, and nothing has been sent without the client.
  • Email and meeting history refreshes every weekday in under a minute.

Still open

  • Whether the private-equity firm's wider team adopts it is that firm's decision. The app went through its external-application security questionnaire in November 2025, and I do not claim adoption here.
  • Meetings booked and deals sourced are not measured, so they are not on this page.

The quality of the drafts is fantastic. Let's turn this on.

US private-equity sourcing firm / approving the AI outreach drafts for go-live, June 2026

Updated

The details, when you need them.

A CRM built around how the client works

Contacts, opportunities, interactions, KPIs, reports, an email builder and a chat assistant over the pipeline. Row-level security, database functions and views keep the rules in the database, not in the browser. 474 migrations and 26 edge functions so far.

An agent that suggests, and a human who clicks

A Python agent on a small VPS reads and writes the same database. It keeps an approval queue topped up, refilling when fewer than 20 suggestions are waiting: cadence changes, enrichment, new contacts. Each is one click: apply, edit and apply, or decline.

Outreach that drafts and never sends

A daily cap drains a backlog over several days instead of dumping it on the client at once. The client read the sample drafts before it went live, and still decides what gets sent.

Deals captured from the inbox

A second job reads recent email threads, strips signatures and quoted replies, spots real deal activity and matches it to existing opportunities, code names included. It adds timeline notes automatically. A deal it has not seen before stays in pending review, out of every external report, until the client confirms it.

The import I had to rebuild

Email and meeting history arrives as a weekday export that n8n loads into Supabase. My first version made one database call per row and held a table lock for 42 minutes. The rebuild validates, snapshots and swaps in one transaction, with self-tests that roll themselves back. It now finishes in 54 seconds.

  • Weekday 08:00
  • Runs into the client's own Outlook
  • No path that sends

outreach-drafts

  1. Weekday 08:00 trigger

    US holidays skipped

  2. Select due contacts from the queue view

    overdue first, capped per day

  3. Detect why each contact is due

    one highest-priority trigger per contact

  4. Write the email with Claude

    the client's rules, rotating phrases

  5. Check for an open draft

    unique index, never two drafts per cycle

  6. POST to the n8n draft bridge

    shared-secret header, 403 without it

  7. Save the draft in Outlook

    never sent; the client reviews and sends

Live since 10 June 2026 / drafts only

Research at scale

Adding an official website to every company in a large list, without letting one confident wrong answer through.

The client needed an official website added to every company in a large list of private companies, and set the acceptance rule.

A verification-first pipeline: name normalisation, web search, domain scoring, a live-page check with a rendering fallback, then accept, review or leave blank. It is built for the failure that matters most, a live website with the right name that belongs to a different business. A verify script proves the delivered workbook equals the original plus exactly the new columns.

I also built a guard that scored each page against the company's industry, measured it, and threw it away: it could not catch the errors it was written for.

fund-manager websites filled
99.7%
company websites filled
83.3%
agreement with the hand-curated URLs already in the CRM
98%

The security questionnaire

Before the private-equity firm's wider team could touch it, the build had to answer somebody else's security review.

In November 2025 the app went through the private-equity firm's external-application security questionnaire. I answered it from the build rather than from intentions: where it is hosted, how it is backed up, how row-level security separates the data, what the audit log records, who gets which role, and where a language model is used.

It was answerable only because the rules had lived in the database since the first migration.

What will it never do?

  • Draft, never send. The outreach code has no path that emails a contact (its only send is a digest to the client), and a kill switch returns it to dry-run mode without a deploy.
  • Every agent suggestion waits for approval, and a new deal stays in pending review until the client confirms it.
  • A unique index on open drafts, so the same contact can never get two drafts in one cycle.
  • The Outlook draft bridge rejects any request without its shared-secret header (HTTP 403).
  • Imports validate, snapshot and swap in one transaction, refuse a file under 90% of the last refresh, and can be restored.
  • 5,567 automated tests passing on the main branch, and independent multi-agent reviews before risky changes ship.

What I could not show you

  • No contact, company or deal name appears anywhere on this page, and there are no screenshots of the live CRM.
  • Every figure above is an engineering fact the client can check against the project's git history and their own inbox.
  • Business outcomes are not claimed, because I have not measured them.

Measurements and project details

automated tests passing on the main branch
5,567
database migrations shipped
474
commits since August 2025
1,789
Client
US private-equity sourcing firm
Industry
Deal sourcing
Region
United States
Timeline
Aug 2025 to today
Role
Product design, full-stack build, AI agent and data migration

Stack

  • Lovable
  • React
  • TypeScript
  • Supabase
  • PostgreSQL
  • n8n
  • Claude Agent SDK
  • OpenAI
  • Python
  • Microsoft Graph