← Back to CRM
The operating principle — sensor, not gate. A GATE blocks an action until confidence clears a bar; it fails by inaction (a hot lead gets silence — the worst outcome, because you never see it). A SENSOR lets the AI act, then measures the outcome, learns, and only raises a flag for genuine, high-stakes ambiguity; it fails by an occasional recoverable, visible, learnable slip. So: the no-spam check stays a hard GATE (a wrong send to a closed / member / DnD contact is unrecoverable). Everything else — opener, reply to an engaged lead, offer the next step — is a SENSOR. Deterministic where we can be; learning on top, not in the way.
The flow
AI acts (deterministic)
Sensor / learning
Hard gate / checkpoint
Outcome
flowchart TD
A(["New lead submits / re-submits"]):::act --> GATE{"Who is this? (no-spam gate)"}:::gate
GATE -->|"member"| JACK["Stays member — Jack's ownership"]:::gate
GATE -->|"DnD / opted-out"| RC{"Did THEY re-contact us?"}:::sensor
RC -->|"no — we'd be cold-initiating"| NEVER["Never outbound"]:::gate
RC -->|"yes — re-submit = opt-in"| WB["Reopen + clear DnD →
welcome_back opener"]:::act
GATE -->|"closed / not-interested"| WB
GATE -->|"fresh lead"| B["Cold OPENER — deterministic.
A/B: 'couple of questions?' vs
'what are you hoping to change?'"]:::act
WB --> C
B --> C{"Lead replies?"}:::sensor
C -->|"no reply"| N["Nurture drip:
follow-up 24h, reactivation 48h, win-back 96h"]:::act
C -->|"reply"| D["DISCOVERY: goal +
'beginner, or some experience?'"]:::act
D --> AMB{"Clear answer?"}:::sensor
AMB -->|"ambiguous / complaint /
ungroundable question"| X["CHECKPOINT to Jack —
AI keeps ownership, resumes"]:::gate
AMB -->|"clear"| E{"Read confidence / readiness"}:::sensor
E -->|"LOW / beginner / nervous"| F["Offer: PHONE CALL —
understand + guide them in"]:::act
E -->|"HIGH / keen"| G["Offer: FREE TASTER —
lowest friction"]:::act
E -->|"MIDDLE / unsure"| H["Offer: A/B —
1:1 PT vs taster, lean 1:1"]:::act
F --> I{"Picks a time?"}:::sensor
G --> I
H --> I
I -->|"call"| J(["BOOKED — call (BOOKING marker)"]):::book
I -->|"taster"| K(["BOOKED — taster (BOOK_CLASS marker)"]):::book
I -->|"1:1 PT"| L["Hand to Jack — PT booking next phase"]:::gate
I -->|"not ready"| N
N --> M{"Re-engages?"}:::sensor
M -->|"yes"| D
M -->|"no, silence-capped"| Z(["CLOSED — nurtured out"]):::book
classDef act fill:#e8f5e9,stroke:#2e7d32,stroke-width:1.5px,color:#1b3a1d;
classDef sensor fill:#fff3e0,stroke:#f57c00,stroke-width:1.5px,color:#5a3a00;
classDef gate fill:#fdecea,stroke:#c62828,stroke-width:1.5px,color:#5a1414;
classDef book fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d3a6a;
The messages — what we actually say (default questions)
| Step | Message | Why |
| Opener A LIVE |
"Hey {name}, thanks for reaching out — can I ask a couple of quick questions so I can point you the right way?" |
Low friction, invites an easy yes. opener_couple_of_questions (Meta-approved). |
| Opener B A/B — to submit |
"Hey {name}, it's Jack from CrossFit Bodmin — what are you hoping to change? Weight, strength, confidence, or something specific?" |
Direct discovery — opens the conversation with the goal. We A/B A vs B and let reply-rate pick the winner. |
| Discovery |
"How confident are you with training or gyms — a complete beginner, or have you got some experience?" |
One easy binary. This single answer routes the offer (below). Never stack questions. |
| Offer — LOW act |
"Honestly the easiest start is a quick call so I can get where you're at and point you the right way — I've got [2-3 times], any of those suit?" |
Beginner / nervous → a guided call. Emits [BOOKING:]. |
| Offer — HIGH act |
"Love it — easiest thing's to come try a session, no cost, see how it feels. We've got [2-3 class times] — fancy one of those?" |
Keen → a free taster, lowest friction. Emits [BOOK_CLASS:]. |
| Offer — MIDDLE act |
"Ok, a couple of routes in — a couple of 1:1 sessions to build your technique and give you a solid base; or a free taster class to see how it feels first. I like starting people with the 1:1s, but it's whatever works best for you. Want to start with a taster, or a bit of personal training?" |
Unsure → A/B the lead (lean 1:1). Taster books; 1:1 PT hands to Jack until PT-booking ships. |
The role of learning (the sensor)
Learning never blocks the tree — it sits
on top, observing every branch and outcome, and feeding the next decision:
- Opener A vs B — which wins more replies. The tree picks the winner over time.
- Offer routing — did low→call / high→taster actually convert for each lead type? Re-weight if not.
- Voice — anchored to Jack's real sent messages, sharpening with every send (warm, British, no corporate hedging).
- Timing & cadence — when a nudge lands a reply vs gets ignored.
- The checkpoints — when Jack takes over a genuinely-hard one, the AI learns the pattern for next time.
Quality — no spammy / uncertain messaging
Five guarantees, so every message is a vetted step, never a free-form gamble:
- GATE No-spam — never message closed / member / DnD / silence-capped. Code-enforced, structural.
- Approved templates only for first touch — Meta-approved, no dead-ends (every opener invites a reply).
- Deterministic routing — every message is a known node on this tree, not an improvised reply.
- Grounding — the AI states only facts it can ground (real class times, prices from business knowledge); a genuine unknown → checkpoint, never invented.
- Voice anchor — Jack's tone, mined from his own sends; over-apology / corporate hedging stripped.
Deterministic outcomes — always driving to a booking
The tree never dead-ends and never waits to be asked — after discovery it
always offers the next step. Every path resolves to one of four states, and each transition is measured:
BOOKED — call BOOKED — taster HANDED TO JACK — 1:1 PT CLOSED — nurtured out
Funnel measured per branch: opener → reply rate · reply → offer rate · offer → booking rate. A drop at any stage points to the exact node to fix.
Where we are right now
| Piece | State | Note |
| Deterministic opener at intake | LIVE | New leads get a direct, ungated opener (was confidence-gated → 27% silently dropped). Fixed 2026-06-04. |
| Dead-end "welcome" opener | KILLED | Removed from every first-touch path — every opener now invites a reply. |
| Offer routing (call / taster / A/B) | LIVE | Routes by the lead's confidence, in Jack's voice. OFFER_AI_BOOKING=1. |
| Engaged reply → AI acts (not "ask Jack") | IN PROGRESS | Make the AI progress a clear discovery answer (sensor), instead of raising an operator task (Lisa). |
| Opener A/B test | NEXT | Submit Opener B for approval, then 50/50 split + reply-rate compare. |
| CRM PT booking (1:1 route) | NEXT PHASE | Wire [PT_BOOKING:] so the A/B's PT route closes itself. |