17 Guide

Automating a CRM with AI

I run eight AI-backed functions in a CRM that real people use daily. Two more got built and switched off. The ones that survived have something in common.

AI belongs on CRM work that is repetitive, judgement-light, and currently skipped because nobody has time. It does not belong writing to a system of record without a deterministic check between the model and the database. The features that survive remove a step; the ones that get turned off add one.

The test that predicts survival

Does this remove work, or add a step?

Every AI feature that stuck removes something a person was doing or skipping. Every one that got switched off added a screen, a suggestion, or a summary that had to be read and evaluated — which is work, dressed as help.

A summary nobody reads is worse than no summary, because it cost latency and now sits there implying it should be read. If the feature does not remove work, adoption will not save it.

What works

FeatureRemovesWhy it survives
Summarise a long threadReading 40 messagesGenuine compression of real work
Draft a follow-upThe blank pageEditing beats writing
Classify an inbound enquiryManual triageConsistent, and checkable against a fixed list
Flag quiet dealsNoticing nothing happenedAbsence is what humans miss
Extract next steps from a callWriting up notesThe task everyone skips

The strongest of these is flagging what has gone quiet. Humans are good at reacting to things that happen and terrible at noticing things that stopped happening. That asymmetry is where automation has the biggest edge, and it needs no cleverness at all.

The two I turned off

An AI-written summary on every record. Generated on view, rendered above the record. It worked, and nobody read it — the actual record was right there and more trustworthy. It cost latency on the most-used screen in the product to display something people scrolled past. The lesson: a summary is only valuable when the underlying thing is too long to read. On a short record it is noise with a delay attached.

Automatic lead scoring, in its first form. The scores were plausible and completely unactionable, because nobody could tell why a lead was a 72. A number with no explanation is not information, it is an assertion. It came back later as a short reason string instead of a score, and that version gets used.

Both failures were the same shape: the feature performed fine and produced nothing anyone could act on.

The rule that protects the data

Model proposes, code validates, system records.

Never let a probabilistic step write directly into pipeline data. Put a deterministic check in between:

  • Model classifies an enquiry → code checks the category is one of the allowed values.
  • Model extracts a date → code checks it parses and is in a sensible range.
  • Model picks a record to update → code confirms the record exists and belongs to the right account.
  • Model drafts a message → a human approves it, at least until the pattern is proven.

These checks are trivial to write. They get skipped because the AI step usually works, which is exactly what makes the eventual failure expensive: bad data enters the system with no error, and every report built on it is quietly wrong.

Permissions are the part to get right

An AI feature acting on a record must respect exactly the same access rules as the user who triggered it.

The tempting shortcut is running AI functions with elevated privileges because it was easier to build that way. In a multi-tenant CRM that is how one customer’s data ends up summarised into another customer’s screen, and it will not announce itself.

Put authorisation in the database rather than the application, so a new AI endpoint is protected whether or not somebody remembered. The full argument is here, along with the specific mistakes I have made doing it.

And log which identity each function ran as. When something goes wrong, “it ran as the wrong thing” is a common cause and invisible unless you recorded it.

Architecture notes

Things that cost me time on a production build:

  • Put AI functions next to the database, not the frontend. They need privileged access and they are triggered by data events rather than page loads.
  • Never await a model call inside a request. It will exceed the timeout and frequently surface as a generic error, so it reads as a bug in your own logic. Queue it and poll.
  • Separate platform email from customer email. If they share a quota system, a tenant who exhausts their sending cap also stops receiving “your payment failed.”
  • Deploy functions one at a time once you have many. Batch deploys fail in ways that leave you unsure what actually updated.
  • Keep shared concerns in shared modules. When the email provider changed, that was one module rather than a search across every function.

Where to start

  1. Find the task everyone skips. Not the annoying one — the skipped one. That is where the value is.
  2. Build it as a suggestion first, with a human accepting or rejecting. The acceptance rate tells you whether to automate it.
  3. Add the validation before the write.
  4. Check permissions as an anonymous user and as a user from another tenant.
  5. Measure whether it removed work. If usage decays, it added a step. Turn it off rather than defending it.

FAQ

What should AI do in a CRM?

Repetitive, judgement-light work that is currently skipped: summarising long threads, drafting follow-ups, classifying enquiries, flagging quiet deals.

What should it never do?

Write to a system of record without a deterministic check. Model proposes, code validates, system records.

Why do AI CRM features get turned off?

Because they add a step instead of removing one. A summary nobody reads is friction with latency attached.

Does AI need its own permissions model?

It must respect the same row-level rules as the triggering user. Running with elevated privileges because it was easier is how tenants see each other’s data.

Related: custom CRM vs GoHighLevel, row-level security vs app-layer auth, and custom CRM development.