Module 25 · ai · intermediate
AI Lead Qualifier and Booking Agent
After this module you can answer every inbound lead in seconds, ask the right questions, and put qualified people straight onto your calendar, without double bookings and without a human in the loop.
What it does
The demo business is Northstar Automation (a small automation agency). Services, qualification thresholds, working hours and meeting rules live in Settings.
| Entry | What happens |
|---|---|
POST /webhook/lq/lead |
New lead (from a form, chat widget or email automation). One lead per email; form answers count as already answered |
POST /webhook/lq/reply |
The lead's next message. OpenAI extracts facts (need, budget, timeline, decision maker, slot choice); rules fill in when AI is off or fails. Code decides: next question, score with reasons, not a fit (with resources), nurture (follow-up date), handoff to a person, or 3 slots |
POST /webhook/lq/book |
Book an offered slot by id (for email buttons) |
GET /webhook/lq/lead/status?lead_id=… |
The lead's record, holds and booking |
POST /webhook/lq/cancel |
Cancel: frees the slot and holds |
Slots come from Google Calendar busy times (or the built-in internal calendar): working hours, 15-minute buffer, 4-hour minimum notice, 7-day horizon, one slot per day so the options are spread out. Offered slots are held for 30 minutes so two leads can't pick the same time. Booking creates a Google Calendar event with the lead invited, or records it internally and emails a confirmation. The owner is emailed on bookings, handoffs and anything that needs manual scheduling. If the calendar can't be read, no slots are made up: the lead hears that the owner will email times.
Request options for testing: now, busy (array of {start, end}), calendar_mode: "internal", ai: false.
Flow
New Lead / Reply / Book API ─┐
Lead Status API ─────────────┼→ Settings → Route ─message→ Intake → Valid? → Use AI? ─yes→ Extract Answers (OpenAI) ─┐
Cancel API ──────────────────┘ │ └no──────────────────────────────────┴→ Join AI → Pick Extraction
│ → Need Calendar? ─yes→ Get Busy Times (Google) ─┐
│ └no─────────────────────────────┴→ Join Calendar → Busy Times → Decide Next Step
│ → Book? ─yes→ Google Calendar? → Create Event → Record Booking ─┐
│ └no─────────────────────────────────────────────────────┴→ Join Outcome → respond / email owner / email lead
├status→ Lead Status → respond
└cancel→ Cancel Booking → respond
Verification status (n8n 2.43.6)
- 22 behavior checks (48 assertions) without credentials, using the internal calendar with an injected clock and busy times: questions one at a time, rule extraction when AI fails, budget/timeline parsing, scoring, slots around a busy block (buffer + notice, one per day), holds between leads with buffer, booking by number / day name / slot id, 409 for unknown or taken slots, not-a-fit / nurture / handoff, form answers up front, dedupe by email, cancel frees the slot, validation, and Google Calendar failure → manual scheduling. The test cancels its own bookings and is repeatable.
- Not run with OpenAI, Google Calendar or Gmail credentials (
WITH_CREDS=1 [CAL=1] ./test/test.sh). AI extraction quality and real calendar events are unverified.
Files
| File | Tier | Purpose |
|---|---|---|
| lesson.md | Free | Step-by-step build |
| workflow/starter.json | Free | Endpoints, Settings, intake, status |
| workflow/learner.json | Learner | Finished workflow |
| workflow/code/ | Learner | Readable copies of the Code nodes + AI prompt |
| exercises.md | Learner | Practice tasks |
| solutions.md | Learner | Exercise solutions |
| notes.md | Private | Learning log |
| sell/ | Private | Offer, video script, blog post |