Building an AI CRM from scratch
What it actually takes to go from 'AI should read my inbox' to a multi-tenant SaaS with auth, billing, and a human-in-the-loop approval flow.
When people hear "AI CRM," they picture the model reading an inbox while records appear on their own. That turned out to be the easy part. Calling a language model and getting structured output back is a few hours of work. Almost everything that made Agentic CRM hard lived around the model, not inside it.
I built it to find out what production actually costs. Not a demo with one user and a hardcoded workspace, but a multi-tenant app with real authentication, email ingestion, background workers, and an AI pipeline that never writes to the database without a human signing off. Here is what that work really was.
The model is the last 10%
The flow a user sees is simple. An email arrives, the system proposes "create company Acme, add contact Jane, open a deal," and you approve it. Underneath, that one sentence touches a dozen systems. The email has to be fetched over OAuth, normalized, and stored. The proposal has to come back as structured, reviewable data instead of free text. The approval has to be recorded. Only then can anything be written, in the right order, inside the right tenant boundary.
Starting from the model would have produced a clever toy. Starting from the system meant the model dropped into a place that already knew how to be safe.
What the surrounding system is
- A FastAPI backend of 120+ routes, organized by domain: auth, workspaces, CRM entities, email, AI actions, and billing, with clear lines between request handling, business logic, and persistence.
- PostgreSQL as the system of record, with SQLAlchemy and Alembic migrations so the schema can move forward without breaking existing data.
- Redis-backed background workers for the slow work. Inbox sync and AI analysis run off the request path so the API stays responsive.
- A React and TypeScript frontend built around the approval workflow, with types shared end to end so the UI and backend cannot quietly disagree about the data model.
- Auth that layers JWT and server-side sessions, CSRF protection on mutations, and RBAC scoped to each workspace.
The approval boundary is the product
The most important decision was that the AI cannot write to the CRM. It produces SuggestedActions, which are structured proposals, and nothing executes until a person approves the package. That boundary is what makes the AI safe to point at real customer data. It also made the system much easier to reason about, because there is exactly one place where AI output becomes durable state, and a human guards it.
Execution is a graph, not a chain
The obvious version of approve-and-execute is a fixed sequence: create the company, then the contact, then the deal. Real CRM data is not shaped that way. A contact can stand alone or belong to a company. A deal can link a contact, a company, or both. A task can attach to any combination. So execution became dependency resolution. The engine works out what each approved action needs, creates and links entities in the correct order inside a transaction, and writes a consistent graph where every reference resolves. Get it wrong and you get orphaned rows or half-applied state, which is the quiet kind of corruption a CRM can never have.
What I would tell someone starting one
Build the boring parts first. Tenancy, auth, migrations, and the job queue decide whether the interesting parts can exist safely. The AI is the fun 10%, and it only earns its place because the other 90% holds it in. Agentic CRM is in final validation ahead of a small beta, and the longest stretch of that work has had nothing to do with the model.