Skip to content

Nick Jungmarker · Case study · production system

An AI CRM for my real estate team

Leads from my website, contracts with eight deadlines each, and follow-ups across a two-agent team were slipping through spreadsheets and email, and a missed contract date can cost a client money. I wanted a CRM that also reads: one where Claude reads contracts and drafts follow-ups, and a person approves anything that changes a record or reaches a client.

Who uses it
Me and the second agent on my team. Every record is scoped to the agent who owns it.
Status
In use. Built from February 2026; the code is private because it holds client data.
My role
Designed the rules and data model, built it with Claude Code as a pair programmer, and run it day to day.

A contract, end to end

Highlighted steps are done by a person.
  1. 1. System

    Intake

    A ratified contract arrives by upload or the deal inbox. A lead arrives from a website form.

  2. 2. Claude

    Extract or draft

    Claude pulls the parties, price and eight deadlines with supporting quotes, or tags a lead’s areas and language.

  3. 3. Agent

    Review

    The deal waits in “Needs review”. Each date read by the AI is marked “Not verified”, and a missing one is “Unknown”, never “Waived”.

  4. 4. Agent

    Confirm

    The agent confirms. The change runs through the same functions as the dashboard and is written to the audit log.

  5. 5. Claude

    Follow up

    Reminders track each confirmed milestone. The daily agent drafts check-ins that wait for the agent to send them.

Leads follow the same pattern: Claude tags a new lead’s areas and language. If the call fails, times out or the key is missing, a keyword matcher takes over, so the form never waits more than about 8 seconds, and the lead lands with the right agent and email series. There are no screenshots here because the live system holds client data.

What I can show

Behavior I built and checked. There are no outcome metrics yet.

Safeguards Implementation fact

  • AI writes are proposals. Nothing changes until the record’s owner confirms.
  • No AI tool sends email or texts, or deletes records.
  • Every record belongs to one agent, and a record you don’t own looks the same as one that doesn’t exist.
  • Text from emails, notes and alerts is treated as untrusted input.
  • Every AI action is logged with its actor and tool, and rate-limited.

Each one is enforced in code; details are in the eight rules below.

Limitations

  • I haven’t measured time saved, response times or conversion, so this page describes behavior, not outcomes.
  • It serves one two-agent team. Search is Postgres full-text rather than embeddings, which is enough for one book of business and may not be for more.
  • Voice notes use the browser’s speech recognition, which does worse on long recordings than server transcription.
  • Contract extraction is only as good as the review: the safeguard is that a person confirms every date, not that the AI is always right.

Problems I found and fixed

From the system’s changelog, October 2026.
  1. Found: A contingency left blank could be read as waived, so a missing date and a waived one looked the same.

    Changed: Each deadline now has a state: Unknown, Not verified, Confirmed, Waived, Not applicable or Completed. Dates read by the AI stay Not verified and are flagged until the agent confirms them. Reminders skip dates that are Waived, Not applicable or Unknown.

  2. Found: A two-agent review found the daily follow-up run, started from the team view, filed the second agent’s follow-ups under me and blocked hers for the week.

    Changed: The team-view run now covers only my records, reassigning a contact moves its tasks and suggestions with it, and regression tests cover both.

  3. Found: A security pass found the scheduled-job endpoints trusted a request header that can be forged.

    Changed: They now require a secret and fail closed. Sign-in links trust only the site’s own hosts.

Decisions and tradeoffs

What I chose, what I passed on, and when I’d change it.
  • Postgres full-text search, not vector embeddings

    Why: No new service or cost, and it’s enough for one team’s book of business

    Revisit: If recall on memory questions drops; pgvector is the upgrade path

  • Pure logic files with no imports

    Why: Routing, deadlines, matching and the work queue are tested directly with node --test, no database needed

    Revisit: Not planning to; it keeps tests fast

  • MCP over plain JSON responses, no streaming

    Why: Works with serverless functions and every client I use

    Revisit: If a tool needs long-running progress updates

  • Browser speech recognition for voice notes

    Why: Free and runs on the device

    Revisit: For long recordings, where server transcription does better

  • Haiku for tagging and drafts, a larger model for the copilot

    Why: Tagging must be fast and cheap; the copilot needs reasoning over several tool calls

    Revisit: Re-check as models and prices change

In October 2026 I also migrated the segment email drips (buyers, sellers, investors, first-time buyers, past clients) from ActiveCampaign to REV (BoldTrail).

How it fits together

Three ways in, one review step, one log

Leads come from the website, documents come through a deal inbox, and I work the CRM through a dashboard copilot or any MCP client such as Claude Desktop. All three paths share the same tools, the same ownership checks and the same audit log.

  1. Website forms → AI tagging with a keyword fallback → contact and email series
  2. Deal inbox and uploads → AI extraction → “Needs review”
  3. Copilot and MCP clients → reads run, writes become proposals
  4. A person confirms → same functions as the dashboard → one audit log

The eight rules in detail

Each is backed by code and, where it can be, by a test.
  1. Rule 1: Reads run. Writes are proposals.

    When the copilot wants to add a task, update a stage or draft an email, it creates a proposal. Nothing changes until the agent who owns the record clicks Confirm. Proposals call the same functions as the dashboard, so validation is identical.

  2. Rule 2: The AI can’t send, delete or quietly edit.

    No AI tool sends email or texts, and none deletes records. The MCP server is read-only except for one tool that queues a note for review.

  3. Rule 3: “Not yours” looks the same as “doesn’t exist.”

    Every record belongs to one agent. Queries are scoped automatically, and a record you don’t own returns the same 404 as a missing one, so IDs never reveal what exists. A test scans every API file and fails on any unscoped query of an owned table.

  4. Rule 4: Outside text is untrusted.

    Notes, emails and alerts can contain instructions, and email senders can be forged. MLS alert emails may only ever touch listings, never leads or deals, and every change they make is logged. The MCP server tells clients not to follow instructions found in CRM data.

  5. Rule 5: A slow AI call doesn’t hold up a lead.

    When a lead submits a form, Claude tags the areas and language. If the call fails, times out or the key is missing, a keyword matcher takes over, so the form waits at most about 8 seconds and the lead is still created and routed.

  6. Rule 6: A person checks every extracted date.

    Claude reads the ratified contract and pulls out the parties, price and eight deadlines with supporting quotes. The deal stays in “Needs review” until the agent confirms every date. The PDF isn’t stored by the reader.

  7. Rule 7: Counts come from the rows they describe.

    The work queue’s counts are computed from the same items the filter shows, so clicking “3 overdue” shows those three rows. If a count’s inputs fail to load, it shows “–” rather than 0.

  8. Rule 8: Every AI action is logged and limited.

    Copilot, MCP and inbox actions all write to one log with the actor and tool. Rate limits cap tool calls and captures per hour.

What it does

Six parts of the system

Lead intake and routing

Forms and a down-payment program quiz create the contact in REV, tag it (buyer MD or DC, seller, CMA, investor, first-time, Spanish) and start the matching drip. The second agent’s leads go only to her.

routing, fallback, bilingual

Copilot and MCP server

Ask “who haven’t I talked to in 90 days?” from the dashboard, Claude Code or Claude Desktop. Tools search contacts, memories, tasks, pipeline and deal deadlines.

MCP, tool use, proposals

Transaction coordinator

Contracts arrive by upload or a deal inbox. Claude extracts the dates, the agent confirms them, and a reminder engine tracks each milestone, including whether a date is trusted yet.

extraction, deadlines, review

Relationship memory

Facts a client mentions are stored with their source, confidence and whether I verified them. Newer verified facts replace older ones. Answers to questions cite where each fact came from.

citations, full-text search

Daily follow-up agent

Each morning it finds overdue and stale contacts, likely duplicates and missing info, and drafts check-ins for the top ten. Drafts wait for me. Nothing is sent.

signals, drafts, dedupe

Traffic and AI search

Google and Bing search queries, on-site actions and referrals from AI assistants. Sellers get a private link to their listing’s online activity. Pages are prerendered with structured data so AI assistants can read them.

analytics, SEO and AEO, llms.txt

Stack

App
Vite, React, TypeScript
API
Serverless TypeScript functions
Data
Postgres (Supabase), private file storage
AI
Claude via the Anthropic SDK; Haiku for quick tagging and drafts
Email drips
REV / BoldTrail, migrated off ActiveCampaign in Oct 2026
Other
Search Console and Bing data, first-party analytics, Obsidian sync

For scale: 178 commits from February to November 2026, and 7 tools on the MCP server, all read-only except one that queues a note for review.

From a two-agent team to a sales org

Company-scale versions of the same patterns, built on Ledgerly, a synthetic B2B SaaS company, so the work can be shared. Their results are synthetic benchmarks.
  • Ledgerly CRM MCP

    Rules 1 to 4 and 8 at company scale: roles and territories, approval by someone other than the requester, rollback, tamper-evident audit evidence.

  • Lead-to-Pipeline Systems

    My lead routing, redesigned as Salesforce lifecycle stages, routing, validation rules, a test plan and release notes.

  • GTM Signal Agent

    The follow-up agent for account teams, with an evaluation suite that scores every change.

  • Weekly Business Review Pack

    Rule 7 as an executive pack: every headline number checked against a second source.

  • Churn Early Warning

    Who’s going quiet, back-tested, with plain-English reasons an agent can quote.

  • Campaign Lift Lab

    What actually causes a booked call, measured with holdouts instead of dashboards.

How it was built: Nick Jungmarker with Claude Code as a pair programmer. I wrote the rules and failure cases, reviewed the changes and keep the tests green; Claude wrote most of the code. This page describes the system without showing code or client information.