Stonebriar · Automation Handoff n8n end-to-end · live audit 2026-06-18
Automation Handoff

The lead engine,
explained end to end.

Every firing n8n workflow behind Stonebriar's lead automation — what fires it, what each module does, and where it hands off next. Verified against the live system on 2026-06-18: only the workflows actually running in production are shown here, each at full module-flow depth.

Prepared for
Daylon · Stonebriar team
The stack
n8n · GoHighLevel · Retell · Twilio
Scale
19 firing workflows
Author
JJ · Automation engineer
Firing — running in production now Sub — reusable building block Standby — built, waiting to switch on Retired — unpublished, superseded
Orientation

01System overview

From a brand-new lead to a booked roof inspection — the whole journey runs itself. Here is what happens end to end, then the moving parts underneath.

Phase 1
Lead captured & tagged
Phase 2
Roof photo + Sarah calls
Phase 3
Inspection booked
Phase 4
Confirmed & followed up

The big picture

When a new homeowner lead lands in GoHighLevel, the system takes it from there. It texts a satellite photo of their roof, and Sarah — the voice AI — calls within seconds, qualifies them, and books a roof inspection straight into the calendar. Reminders, reschedules, and follow-up all run on their own. Your team only steps in to show up and inspect the roof, and every step is written back to the CRM, so nothing is invisible.

StartA new homeowner lead comes in — door-knock, web form, or Facebook adSource
Phase 1Contact created & tagged in GoHighLevelStage · New Lead
FireGoHighLevel WF-1 fires the First Touch webhook into n8nthe starting gun
Phase 2n8n texts a satellite roof photo, then Sarah (voice AI) dials the homeownerStage · Speed-to-Lead
CallSarah qualifies the homeowner and offers real inspection slotsStage · On Call
Phase 3The inspection is booked into the calendar — by voice, or by the SMS “Jenny” bot via the tag bridgeStage · Booked
Phase 4Confirmation, reminders, reschedules and safety-net checks run automaticallyStage · Confirmed
DoneThe roof inspection happens · every outcome is logged back to GoHighLevelStage · Done

The moving parts

Five layers do the work; n8n sits in the middle — it listens to GoHighLevel, makes the decisions, and orchestrates Retell, Twilio and the CRM.

01
FB Ads
Homeowner fills the lead form
02
GoHighLevel
CRM + Jenny SMS bot
03
n8n
The glue — triggers & logic
04
Retell
Sarah, the voice AI
05
Twilio
Carries calls & texts
Two ways the customer is handled
Voice is run by Retell (Sarah), triggered + processed by n8n. SMS is run by the GoHighLevel "Jenny" bot, which tags the contact and lets n8n's booking engines do the calendar work via the tag bridge. Every workflow writes a visible note or field back to GoHighLevel — if it happened, it's on the contact record.
The Lead Journey · starts here

How a lead enters

GoHighLevel · WF-1 14-Day Lead Cadencein GoHighLevelBefore any n8n runs, the lead is created and tagged in the CRM — that tag is what starts everything below.

Outcome A new contact tagged non-booked-funnel (or non-booked-funnel-lead) in GoHighLevel is the starting gun: GHL's WF-1 workflow fires the First Touch webhook (the next section), and from there n8n runs the whole journey.

01
New lead
door-knock · form · ad
02
GoHighLevel
creates the contact
03
Tag added
non-booked-funnel(-lead)
04
WF-1 fires
→ First Touch (n8n)
Part 1 · The Lead Journey
Lead Journey

Satellite roof image

Stonebriar_Roof_ImagefiringBuild a Google Static Maps satellite photo URL from the lead's property address and write it to the GHL contact for use in the intro SMS

Outcome A satellite photo of the lead's roof is saved onto their CRM contact — which First Touch then attaches to the intro text it sends the homeowner. (If the photo can't be built, First Touch just sends text only.)

n8n · Stonebriar_Roof_Image — actual build
Stonebriar_Roof_Image n8n canvas
The live n8n canvas.
6 nodes · Webhook -> GET Contact -> Build Map URL -> PUT Image URL -> Tag -> Respond OKLead Journey
Schematic · module flow — drag & zoom
drag to pan · scroll or +/− to zoom
Receive Request
Listens for an incoming request containing the homeowner's contact ID to start the process.
Fetch Contact
Pulls the homeowner's full record from the CRM, including their property address.
Build Satellite Link
Assembles a Google Maps satellite photo URL zoomed in on the homeowner's roof using their address.
Save Photo Link
Saves the satellite roof photo link back to the homeowner's CRM record so staff can view it.
Mark Image Ready
Tags the contact in the CRM as 'roof-image-ready' so the next step knows the photo is available.
Done
Confirms to the calling workflow that the roof image has been saved and the job is complete.
Writes WRDAthnXubJbA9GrYQbn field; First_Touch reads it 10 seconds later and attaches to the intro SMS6 nodes · Webhook -> GET Contact -> Build Map URL -> PUT Image URL -> Tag -> Respond OK

Trigger

HTTP POST to stonebriar/roof_image from Stonebriar_First_Touch immediately after guard checks pass. Payload: {contact_id}.

Module flow

  1. WebhookListens at stonebriar/roof_image; accepts POST with contact_id stonebriar/roof_image
  2. GET ContactFetches full GHL contact to extract address1, city, state fields for the map URL /contacts/{id} address1 city state
  3. Build Map URLCode node: encodes the property address into a Google Static Maps API URL with satellite maptype, 600x400 size, zoom=20; API key placeholder still present in code comment Google Static Maps API satellite zoom=20
  4. PUT Roof Image URLWrites the constructed satellite URL to GHL custom field WRDAthnXubJbA9GrYQbn on the contact WRDAthnXubJbA9GrYQbn /contacts/{id}
  5. Tag roof-image-readyAdds tag roof-image-ready to confirm the image field is populated and ready for SMS roof-image-ready /contacts/{id}/tags
  6. Respond OKReturns 200 to First_Touch so it can proceed to read the field after the 10-second wait
The satellite photo hook
Attaching a satellite image of the homeowner's own roof to the very first SMS dramatically increases engagement -- the lead sees their property immediately and understands the service before any rep speaks.
Lead Journey

Speed-to-lead first touch

Stonebriar_First_TouchfiringSend a satellite roof photo via SMS and place two outbound voice calls within minutes of a new lead entering the funnel

Outcome Within minutes of a new lead, the homeowner gets a text with a satellite photo of their own roof and Sarah calls them (twice if there's no answer). Whatever happens on the call is then handled by Post-call.

n8n · Stonebriar_First_Touch — actual build
Stonebriar_First_Touch n8n canvas
The live n8n canvas.
37 nodes · Guard Check -> [skip] Note + stop | [pass] Respond 200 -> Roof Image -> SMS -> Tag -> Wait -> Recheck -> Dial 1 -> Wait 3min -> Recheck -> Dial 2Lead Journey
Schematic · module flow — drag & zoom
drag to pan · scroll or +/− to zoom
New Lead Arrives
Receives the signal that a new lead arrived and the first-touch should start.
Fetch Lead Record
Pulls the homeowner's CRM record to check status before doing anything.
Safety Check
Checks if this lead should be skipped — already contacted, booked, or opted out.
Should We Skip?
Stops here if the safety check flagged this lead to avoid double-contacting.
Reply: Skipped
Returns a 'skipped' response and records the reason; no further action.
Reply: Accepted
Returns immediate confirmation so the caller does not wait; rest runs async.
Check Send Window
Checks if it is an OK hour to send (window removed by Jay — always sends).
OK to Send Now?
Proceeds immediately if in the send window; otherwise waits until the window opens.
Wait for Window
Holds the workflow until business hours begin if the lead arrived outside the send window.
Get Roof Photo
Fires the roof-image workflow to fetch a satellite photo from Google Maps.
Wait for Photo
Waits 10 seconds to give the roof-image step time to save the photo URL to the CRM.
Re-read CRM Record
Pulls the homeowner's record again so we can read the freshly-saved roof photo URL.
Get Photo URL
Reads the satellite roof photo URL out of the CRM custom field where it was just saved.
Check Photo Works
Confirms the photo URL loads a real image before adding it to the SMS.
Write SMS Text
Composes the intro text — includes the roof photo if valid, text-only if not.
Send First Text
Sends the introductory SMS with the satellite roof photo to the homeowner's phone number.
Build Send Note
Prepares the CRM note that records exactly what message was sent and when.
Log SMS to CRM
Logs a CRM note confirming the text was sent so the team can see it.
Tag: First Touch Sent
Marks the homeowner in the CRM as 'first-touch-sent' so we do not text them again.
Wait Before Calling
Pauses briefly after the text before making the first phone call attempt.
Re-check Before Call 1
Re-reads CRM before calling — skips if the homeowner already self-booked.
Should We Call? (Dial 1)
Decides if the first AI call should go out — skips if already booked or opted out.
Skip Call 1?
Skips the first call and logs it if the homeowner was already reached.
Log: Call 1 Skipped
Records in the CRM why the first outbound call was skipped.
Place Call 1 (Dial 1)
Fires off the first AI voice call — the voice AI (Sarah) will call the homeowner now.
Build Call 1 Note
Prepares the CRM note describing how the first call went (voicemail, error, etc.).
Log Call 1 Result
Writes the first-call outcome note to the homeowner's CRM record.
Wait 3 Min (Gap)
Waits 3 minutes between the first and second call to avoid appearing as spam.
Re-check Before Call 2
Re-reads the CRM to see if the homeowner answered call 1 and booked — skip call 2 if so.
Should We Call? (Dial 2)
Decides on call 2 — skips if call 1 was answered or homeowner booked.
Skip Call 2?
If the homeowner was reached or booked after call 1, skips the second call and logs it.
Build Skip Note (Dial 2)
Prepares the CRM note explaining why the second call was skipped.
Log: Call 2 Skipped
Writes the skip reason into the homeowner's CRM record for the team to see.
Place Call 2 (Dial 2)
Fires the second AI voice call attempt — designed to bypass iPhone call-screening.
Build Call 2 Note
Prepares the CRM note describing how the second call went.
Log Call 2 Result
Writes the second-call outcome to the CRM — end of the first-touch sequence.
Calls Stonebriar_Roof_Image (HTTP) and StoneBriar_voice_trigger_call (HTTP) x2; first-touch-sent tag written to GHL37 nodes · Guard Check -> [skip] Note + stop | [pass] Respond 200 -> Roof Image -> SMS -> Tag -> Wait -> Recheck -> Dial 1 -> Wait 3min -> Recheck -> Dial 2

Trigger

HTTP POST to stonebriar/first-touch from GHL Workflow-1 (fired by the non-booked-funnel tag). Payload: {contact_id}. Fires within seconds of Lead_Intake completing the tag write.

Module flow

  1. Webhook + Get ContactReceives contact_id; immediately fetches full GHL contact record for guard evaluation contact_id
  2. Guard Check + Skip? IFCode node evaluates skip conditions (DND, first-touch-sent, booked, ai-active); IF routes to Respond Skipped with reason note, or Respond Accepted to continue async DND first-touch-sent booked ai-active
  3. Window Check (always open)Code node always returns in_window=true -- send window removed 2026-06-15 per Jay; gate retained for fast re-enabling in_window
  4. Trigger Roof Image + Wait 10sHTTP POST to stonebriar/roof_image; waits 10 seconds for async satellite map build to complete stonebriar/roof_image WRDAthnXubJbA9GrYQbn
  5. Extract Roof URL + Verify ImageReads roof image URL from custom field WRDAthnXubJbA9GrYQbn; HTTP GET verifies image returns 200 with image/* content-type WRDAthnXubJbA9GrYQbn content-type
  6. Build Message + Send SMSAssembles intro SMS with roof photo; sends via GHL conversations API (with image if valid, text-only fallback if URL fails) /conversations/messages roof photo
  7. Write Note + Tag first-touch-sentWrites CRM note confirming SMS send result; adds tag first-touch-sent to prevent duplicate re-send first-touch-sent /contacts/{id}/notes
  8. Wait 10 Minutes + Recheck (Dial 1 guard)Waits 1 minute (node label says 10 min; actual config is 1 min); re-fetches contact to check for post-touch outcome tags before dialing Wait 10 Minutes
  9. Voice Decision + Voice Skip? (Dial 1)Code node checks if contact gained engaged/booked/callback/ai-active tags during the wait; IF skips Dial 1 and writes note if already answered engaged-not-booked callback-scheduled
  10. Trigger Voice Bridge Dial 1 + NoteHTTP POST to voice_trigger_call webhook (9f45335d); writes CRM note with Dial 1 outcome (success or error) 9f45335d-da8b-47c4-9465-6e9e6b2c571b Dial 1
  11. Wait 3 Min + Recheck For Answer (Dial 2 guard)Dial 2 gap: waits 3 minutes, re-fetches contact to check if Dial 1 was answered before placing Dial 2 Dial2 gap
  12. Trigger Voice Bridge Dial 2 + NoteHTTP POST to same voice_trigger_call webhook for second call attempt (iPhone call-screen bypass); writes Dial 2 outcome note Dial 2 call-screen bypass
Dispatch-time reguard before each dial
The workflow re-fetches the contact before Dial 1 AND again before Dial 2 -- if the lead answered or booked on any channel during the gap, the remaining call is skipped with a CRM note, preventing double-dial after connection.
Lead Journey

Outbound voice call dial

StoneBriar_voice_trigger_callfiringAssemble full contact and campaign context, check for existing bookings, guard against a suppressed call, enforce Retell concurrency limits, then dial the lead as Sarah

Outcome Sarah places the outbound call as herself, already knowing the homeowner's name, storm-damage details and timezone. When the call ends, Post-call logs it and updates the CRM.

n8n · StoneBriar_voice_trigger_call — actual build
StoneBriar_voice_trigger_call n8n canvas
The live n8n canvas.
16 nodes · config -> search_contact -> Get Custom Fields/Values -> Map Fields/Campaign -> GetAppointments -> Build Context -> suppress IF -> concurrency loop -> trigger_callLead Journey
Schematic · module flow — drag & zoom
drag to pan · scroll or +/− to zoom
Receive Dial Request
Listens for a dial request — another workflow sends the lead phone number here.
Set Credentials
Stores the dial-from number, voice AI key, and CRM key for later steps.
Look Up Contact
Searches the CRM by phone to get the contact name, email, and fields.
Get Field Definitions
Gets CRM field definitions so field IDs can be matched to human labels.
Decode Contact Fields
Translates raw CRM field IDs to readable values: roof age, type, damage.
Get Campaign Data
Fetches company-wide CRM settings: campaign name, storm damage type.
Decode Campaign Data
Reads campaign settings into clean variables like damage type and name.
Check Existing Appt
Checks right now if this contact is already booked — key safety check.
Build Sarah's Brief
Bundles contact and campaign data into a briefing packet for Sarah.
Safe to Call?
Checks if the call should be skipped — contact booked or no phone on file.
Log Call Skipped
If the call was blocked, writes a CRM note explaining why.
Check Active Calls
Checks how many calls are live right now to avoid overloading the lines.
Lines Full?
If 40 or more calls are already live, waits and retries rather than dropping the lead.
Wait for Free Line
Pauses briefly then loops back to re-check how many calls are active before trying again.
Dial Lead
Tells the voice AI to dial the lead with Sarah and their context loaded.
Retell dials the lead via Twilio; on call end Retell fires StoneBriar_voice_post_call16 nodes · config -> search_contact -> Get Custom Fields/Values -> Map Fields/Campaign -> GetAppointments -> Build Context -> suppress IF -> concurrency loop -> trigger_call

Trigger

HTTP POST to webhook path 9f45335d-da8b-47c4-9465-6e9e6b2c571b. Called by: Stonebriar_First_Touch (Dial 1 and Dial 2), GHL Automation directly for non-first-touch leads, and Tag_Bridge_Poller for the callback-requested bridge. Payload: {phone, contact_id, first_name, email, and optional custom data}.

Module flow

  1. configSet node: stores retell_api key, from_phone=+12149721282, GHL API key, and location ID U9eehdYVTaneVBVevw0b key_0e3e94c358e8b7827192512dcf1f +12149721282 U9eehdYVTaneVBVevw0b
  2. search_contactGHL /contacts/search by phone to fetch the full contact record /contacts/search
  3. Get_Custom_Fields + Get_Custom_ValuesFetches all GHL custom field definitions for the location and location-level custom values containing campaign metadata /customFields /customValues
  4. Map_Custom_Fields + Map_campaign_valuesTwo code nodes: first maps GHL field IDs to human-readable names for the contact; second extracts campaign values (storm_damage_type, campaign_name) customFields[] storm_damage_type campaign_name
  5. Call StoneBriar_GetAppointments_SubWorkflowExecutes sub-workflow to fetch existing confirmed future appointments -- GR-001 dispatch-time booking state recheck before dialing GetAppointments_SubWorkflow GR-001
  6. Build Universal Agent ContextCode node: assembles all data into named Retell variables -- roof_age, roof_type, lead_stage, call_number=1, previous_call_summary, prospect_timezone=America/Chicago hardcoded, suppressCall flag retell_llm_dynamic_variables prospect_timezone America/Chicago suppressCall
  7. If (suppress check)IF node: if suppressCall=true (contact already booked or no phone), routes to Note_Call_Suppressed (writes CRM note) and stops suppressCall Note_Call_Suppressed
  8. get_concurrency + If_Concurrency_Reached + Concurrency_WaitGET /get-concurrency from Retell; if current_concurrency >= 40, loops on Concurrency_Wait node until a slot opens /get-concurrency current_concurrency >= 40 Concurrency_Wait
  9. trigger_callHTTP POST to Retell /v2/create-phone-call with agent_c7489b1000369067c5ef69e0dc, from +12149721282, to phone, and full retell_llm_dynamic_variables bundle agent_c7489b1000369067c5ef69e0dc /v2/create-phone-call

Sub-workflows used: StoneBriar_GetAppointments_SubWorkflow

Context-rich dial
15+ dynamic variables pass to Sarah's Retell agent -- roof age, storm damage type, previous call summary, lead stage -- so Sarah sounds like she already knows the homeowner's situation from the first second of the call.
Lead Journey

Mid-call calendar tools

StoneBriar_Voice_Calendar_BookingsfiringRespond to Sarah's live function-tool calls during a voice conversation -- check availability, book, reschedule, or retrieve the homeowner's appointment, within a 10-second Retell timeout

Outcome While Sarah is live on the call she can check times, book, reschedule or look up the inspection on the spot — the booking lands on the CRM calendar and the contact is tagged booked, all before the call ends.

n8n · StoneBriar_Voice_Calendar_Bookings — actual build
StoneBriar_Voice_Calendar_Bookings n8n canvas
The live n8n canvas.
49 nodes · Webhook -> Set Variables -> Switch -> [5 routes each terminating in respondToWebhook]Lead Journey
Schematic · module flow — drag & zoom
drag to pan · scroll or +/− to zoom
Receive Tool Call
Receives a request from the voice AI mid-call to check or book a slot.
Load Config
Sets the calendar ID, API key, and timezone so every branch below has them ready.
Route by Tool
Reads which action Sarah requested and routes the job down the right path.
Prep Slot Window
Calculates the search-window start for the availability check route.
Set Start Time
Formats the start of the search window as the calendar expects it.
Add One Day
Adds a day to build a 24-hour window for the slot search.
Set End Time
Formats the end of the search window so the calendar knows where to stop looking.
Fetch Open Slots
Asks the CRM calendar for all available appointment times in that window.
Format Slots
Converts raw slot data into spoken times Sarah can read to the homeowner.
Reply: Slots Ready
Sends the list of open times back to the voice AI so Sarah can offer them to the caller.
Store Contact ID
Saves the homeowner's CRM ID so the booking step knows whose record to update.
Format Booking Date
Converts the caller's chosen date into the exact format the CRM expects.
Combine Data
Joins the contact details and the formatted date into one package for the booking call.
Book Appointment
Creates the inspection appointment on the Stonebriar calendar in the CRM.
Did Booking Work?
Checks whether the CRM confirmed the appointment was created successfully.
Prep Success Data
Packages the new appointment ID and details ready to be saved on the homeowner's record.
New or Re-book?
Checks if this is a first booking or a repeat to pick the right CRM tag.
Clear Old Tags
Clears stale CRM status tags before applying the fresh 'booked' tag.
Tag as Booked
Marks the homeowner as 'booked' in the CRM so the team can see it.
Contact Check (Off)
Disabled gate that once decided whether to update the contact — now off.
Field Check (Off)
Disabled secondary check that decided which contact fields to write — no longer active.
Update Contact (Off)
Disabled step that would have saved the appointment ID — now superseded.
Alt Update (Off)
Disabled alternate contact-update step — no longer active.
Reply: Booking Confirmed
Tells the voice AI the booking worked so Sarah can confirm with the caller.
Reply: Booking Failed
Tells the voice AI the booking failed so Sarah can offer another option.
Prep Slot Window 2
Calculates the search window for the grouped-slots view (route: check calendar slots).
Set Start Time 2
Formats the start timestamp for the second slot-check route.
Add One Day 2
Extends the window by a day for the grouped-slots search.
Set End Time 2
Formats the end timestamp for the second slot-check route.
Fetch Open Slots 2
Pulls available appointment times from the CRM calendar for the grouped-slots view.
Group Slots
Groups open times into chunks (e.g. Tuesday morning) for Sarah to offer.
Reply: Grouped Slots
Sends grouped available times back to the voice AI to offer the caller.
Store Contact ID 2
Saves the homeowner's CRM ID for the reschedule path.
Get Calendar Info
Looks up the Stonebriar calendar details needed to reschedule the existing appointment.
Format New Date
Converts the new date and time into the exact format the CRM expects for the reschedule.
Combine Reschedule Data
Joins the calendar info and the new date into one package for the reschedule API call.
Reschedule Appointment
Moves the homeowner's inspection to the new date and time in the CRM calendar.
Did Reschedule Work?
Checks whether the CRM confirmed the appointment was moved successfully.
Reply: Reschedule Confirmed
Tells the voice AI the reschedule worked so Sarah can confirm the new date.
Reply: Reschedule Failed
Tells the voice AI the reschedule failed so Sarah can assist another way.
Clear Old Tags 2
Removes old status tags from the CRM record before applying the updated booking tag.
Tag Rescheduled
Marks the homeowner's CRM record with the updated booking status after rescheduling.
Get Appointments
Fetches the homeowner's existing appointments from the CRM (route: get appointment).
Split Appointments
Splits the appointments list so each one can be evaluated individually.
Keep Future Only
Drops any past or cancelled appointments, keeping only confirmed upcoming ones.
Sort by Date
Orders the remaining appointments so the soonest one comes first.
Take Next One
Keeps only the single next upcoming appointment to report back.
Format Appointment
Formats the appointment into a readable summary Sarah can speak to the caller.
Reply: Appointment Found
Sends the appointment details back to the voice AI to confirm the booking.
Responds synchronously to Retell during the live call; booking writes event_id to GHL contact and updates tags49 nodes · Webhook -> Set Variables -> Switch -> [5 routes each terminating in respondToWebhook]

Trigger

HTTP POST to f9d1c743-5530-4ac0-9770-63aab57dac06 from the Retell voice agent whenever she calls one of 5 registered function tools mid-call. The body.name field identifies which tool. responseMode=responseNode means a respondToWebhook node must fire within Retell's tool timeout.

Module flow

  1. Webhook -> Set VariablesWebhook receives Retell tool call; Set Variables loads calendarId=HwJD5Ujgck1FJERzBZVw, time_zone, API key, user_id HwJD5Ujgck1FJERzBZVw f9d1c743-5530-4ac0-9770-63aab57dac06
  2. Switch -> 5 routes on body.nameSwitch routes on: check_calendar_availability (out0), book_appointment (out1), check_calendar_slots (out2), update_appointment (out3), get_appointment (out4) check_calendar_availability book_appointment check_calendar_slots update_appointment get_appointment
  3. Route 0: check_calendar_availabilityCode3 -> date math (startTime/addDay/endDate) -> GET /calendars/free-slots (timezone from Set Variables) -> Code formats voice-ready slot list -> respondToWebhook /calendars/free-slots time_zone
  4. Route 2: check_calendar_slotsCode2 -> date math -> GET /calendars/free-slots (America/Chicago hardcoded) -> Code1 formats grouped time ranges -> respondToWebhook /calendars/free-slots America/Chicago
  5. Route 1: book_appointmentsetContactIdFound -> date format + Merge -> calls appointment_booking_sub_workflow (mjLv4YHPv7CtDCES) -> on success: writes event_id to contact, removes stale tags, adds booked or ai-booked based on lead_stage -> respondToWebhook success or failure message mjLv4YHPv7CtDCES event_id booked ai-booked
  6. Route 3: update_appointmentsetContactIdFound1 -> date format + Merge1 -> calls Update_Appointment_SubWorkFlow (D0E0AxALdJmYcfLx) -> on success: writes new event_id, updates tags -> respondToWebhook D0E0AxALdJmYcfLx event_id
  7. Route 4: get_appointmentHTTP GET /contacts/{id}/appointments -> Split Out -> Filter (confirmed + future, America/Chicago) -> Sort desc -> Limit 1 -> format fields -> respondToWebhook with summary or no-appointment message /contacts/{id}/appointments America/Chicago confirmed

Sub-workflows used: stoneBriar_appointment_booking_sub_workflow StonBriar_Update_Appointment_SubWorkFlow

10-second clock, 5 tools
Every route must respond to Retell within the function-tool timeout or the voice call breaks mid-sentence. responseMode=responseNode holds the HTTP connection open until the calendar API responds, then replies in one shot.
Lead Journey

Post-call processing

StoneBriar_voice_post_callfiringAfter every Retell call ends: enforce DNC compliance, update conversation state on call_started, generate an AI memory summary, move the pipeline stage, and schedule callbacks

Outcome After every call the homeowner is routed correctly: opt-outs are set to Do-Not-Call and stopped; everyone else gets a written call summary, the right pipeline stage, and a callback scheduled if they asked. This is what keeps the CRM truthful after each call.

n8n · StoneBriar_voice_post_call — actual build
StoneBriar_voice_post_call n8n canvas
The live n8n canvas.
28 nodes · dnc_check -> [DNC: Set DND + tags, stop] | [pass: config -> Switch -> [call_started: conversation state] | [call_analyzed: 3-way parallel -> outcome routing -> pipeline move]]Lead Journey
Schematic · module flow — drag & zoom
drag to pan · scroll or +/− to zoom
Call Ended Signal
Receives a notification from the voice AI (Sarah) the moment any call ends.
Do-Not-Call Gate
Checks if the caller asked to opt out; if yes, marks them Do-Not-Call and stops.
Mark Do-Not-Call
Turns on the Do-Not-Call flag in the CRM so this contact is never dialed again.
Add DNC Tags
Adds 'DNC' and 'dnc-honored' labels to the contact in the CRM to track the opt-out.
Set Credentials
Loads the API keys and location settings needed for all the steps that follow.
Route by Event Type
Decides which path to take: call just started, connected, or fully ended.
Call Live Check
Confirms the call is actually connected before marking it as in-progress in the CRM.
Mark Call Active
Updates the CRM to show that a live call is happening with this contact right now.
Fetch Appointments
Looks up the contact's upcoming appointments in the CRM to determine the call outcome.
Call Analyzed Gate
Confirms this is a fully analyzed call (not a mid-call event) before routing the outcome.
QA Evaluator
Sends the call recording to an external quality-review tool for scoring and coaching.
Save Call Log
Runs a sub-process that saves a full call record to the CRM for reporting and history.
Callback Requested?
Checks if the lead asked Sarah to call them back at a specific time.
Calculate Callback Time
Converts the requested callback time into the format needed to schedule the return call.
Schedule Return Call
Books a future outbound call with the voice AI (Sarah) at the time the lead requested.
AI Call Summary
Uses AI to write a short summary of the callback-scheduled call.
Save Callback Notes
Writes the call summary and callback details back to the contact's record in the CRM.
Tag Callback Scheduled
Labels the contact 'callback scheduled' so the team knows a return call is coming.
AI Call Summary
Uses AI to write a short summary of the no-answer or missed call.
Was Call Answered?
Checks whether the lead actually answered the call or if it went unanswered.
Log Unanswered Call
Records in the CRM that this call was not answered and saves a brief summary.
Save Call Summary
Writes the AI-generated call notes and outcome to the contact's record in the CRM.
Already Booked?
Checks if a booking happened during the call to avoid overwriting the booking status.
Tag Engaged, Not Booked
Labels the contact in the CRM as talked-to but not yet scheduled for an inspection.
Determine Pipeline Stage
Decides which sales stage to move the lead to based on how the call went.
Find Lead's Deal
Looks up this contact's active deal record in the CRM sales pipeline.
Move Pipeline Stage
Moves the lead's deal to the correct stage in the sales pipeline (e.g. Inspection Booked).
Writes to GHL contact, conversation, opportunity, and call_logs; schedules future Retell batch call on callback path28 nodes · dnc_check -> [DNC: Set DND + tags, stop] | [pass: config -> Switch -> [call_started: conversation state] | [call_analyzed: 3-way parallel -> outcome routing -> pipeline move]]

Trigger

HTTP POST to webhook path 12d1db5a-4bc9-4c17-88b3-9ca5f5b20872 from Retell's post-call webhook. Fires for every call event. body.event is either call_started (call connected) or call_analyzed (call ended and analyzed). First node is always the DNC gate.

Module flow

  1. dnc_checkIF node: checks custom_analysis_data.opt_out_requested -- if true, sets contact DND=true and adds tags DNC + dnc-honored, then stops all further processing opt_out_requested DND DNC dnc-honored
  2. config + SwitchSet node loads GHL and Retell creds; Switch routes on body.event: call_started to out0, call_analyzed to out1 call_started call_analyzed
  3. Call_Started -> Change_conversation_StateOn call_started event: IF verifies call_status=ongoing, then PUTs GHL conversation to active state for real-time CRM visibility during the call /conversations/{id} active
  4. HTTP Request + If1 (appointments fetch)Fetches contact appointments to inform outcome routing; If1 gates entry into the call_analyzed branch /contacts/{id}/appointments
  5. Call_Back_Requested IF -> schedule_call_backBranches on lead_qualification_status=Qualified - Callback Scheduled; TRUE path parses callback time and POSTs Retell create-batch-call with trigger_timestamp Qualified - Callback Scheduled /create-batch-call trigger_timestamp
  6. Generate Memory Summary1/2 + Update_contactOpenAI generates a call memory summary; writes it back to GHL contact along with call disposition and lead_stage fields OpenAI ai_interaction_summary previous_call_summary
  7. Pick_Stage code nodeMaps call outcome to GHL pipeline stage IDs: booked->Inspection Booked, callback/voicemail/hang_up/no_answer->Contact Attempted, wrong_number->No-Show/Cancel, opted_out->Dead-Max Attempts booked callback_scheduled no_answer wrong_number opted_out fMFWsnKweG7UwwUTnDJ2
  8. Search_Opportunity -> update_pipeline_stageSearches GHL for the contact's open opportunity then PUTs the new stage ID to move the pipeline card /opportunities/search /opportunities/{id}
  9. Call save_voice_logs_ghlExecutes shared sub-workflow (wpxsVyOfCMMedkDs) to create a call_logs custom object record in GHL linked to the contact wpxsVyOfCMMedkDs call_logs

Sub-workflows used: save_voice_logs_ghl

DNC-first architecture
The opt-out check is the very first node after the webhook -- before config, before the Switch, before anything else. An opt-out stops all writes immediately, ensuring compliance regardless of what else is in the call payload.
Part 2 · SMS Booking & Ops
SMS Booking & Ops

GHL tag bridge

Stonebriar_Tag_Bridge_PollerfiringPoll GHL every 3 minutes for 5 intent tags set by Jenny (GHL Conversation AI), strip each tag first to prevent re-fire, and forward the contact to the correct n8n engine workflow

Outcome The GoHighLevel “Jenny” SMS bot can trigger any booking action just by tagging a contact — every few minutes this turns that tag into the matching workflow (book, reschedule, cancel, schedule-check, or call-me-back).

n8n · Stonebriar_Tag_Bridge_Poller — actual build
Stonebriar_Tag_Bridge_Poller n8n canvas
The live n8n canvas.
2 nodes (trigger + single code node handling all 5 bridges) · Every 3 min -> Tag Bridge PollerSMS Booking & Ops
Schematic · module flow — drag & zoom
drag to pan · scroll or +/− to zoom
Every 3 Minutes
Wakes up automatically every 3 minutes to scan the CRM for any new action tags.
Tag-to-Action Bridge
Checks the CRM for 5 intent tags (cancel, schedule-check, book, reschedule, callback), strips each found tag to prevent double-firing, then triggers the correct workflow for each. If a workflow fails to start, the tag is re-added for the next cycle.
Fires: Stonebriar_Appt_Cancel, Stonebriar_Schedule_Check, Stonebriar_SMS_Booking_Engine (book + reschedule), StoneBriar_voice_trigger_call (callback)2 nodes (trigger + single code node handling all 5 bridges) · Every 3 min -> Tag Bridge Poller

Trigger

n8n Schedule trigger: every 3 minutes. No external webhook -- pure poller. GHL Conversation AI (Jenny) sets tags on contacts based on homeowner intent; this workflow is the bridge that converts those tags into n8n engine calls.

Module flow

  1. Every 3 minSchedule trigger fires every 3 minutes around the clock minutesInterval: 3
  2. Bridge: cancel-requestedGHL search by tag cancel-requested -> strip tag first (GR-008 dedupe) -> POST stonebriar/cancel-appt {contact_id} -> if webhook fails, re-add tag (self-heal) cancel-requested stonebriar/cancel-appt
  3. Bridge: schedule-checkGHL search by tag schedule-check -> strip tag -> POST stonebriar/schedule-check {contact_id} -> self-heal on failure schedule-check stonebriar/schedule-check
  4. Bridge: booking-requestedGHL search by tag booking-requested -> strip tag -> POST stonebriar/sms-book {contact_id, action:book} -> self-heal on failure booking-requested stonebriar/sms-book action:book
  5. Bridge: reschedule-requestedGHL search by tag reschedule-requested -> strip tag -> POST stonebriar/sms-book {contact_id, action:reschedule} -> self-heal on failure reschedule-requested action:reschedule
  6. Bridge: callback-requestedGHL search by tag callback-requested -> strip tag -> POST voice_trigger_call webhook 9f45335d {contact_id, phone} -> self-heal on failure (P21 pattern, added v2.0 2026-06-15) callback-requested 9f45335d-da8b-47c4-9465-6e9e6b2c571b
Strip-first deduplication
The tag is removed before the downstream webhook fires -- not after. If the webhook fails, self-heal re-adds the tag for the next poll cycle. Strip-first prevents the engine from firing twice if GHL also processes the tag natively.
SMS Booking & Ops

SMS booking engine

Stonebriar_SMS_Booking_EnginefiringHandle all calendar operations for the SMS channel -- book, reschedule, cancel, check, or prefetch slots against the GHL native calendar, then write the result to booking_reply so Jenny can merge it into her next message

Outcome The appointment is actually booked or changed on the CRM calendar and a truthful confirmation is written back to the contact — which Jenny reads out to the homeowner, so the text they get always matches what really happened.

n8n · Stonebriar_SMS_Booking_Engine — actual build
Stonebriar_SMS_Booking_Engine n8n canvas
The live n8n canvas.
3 nodes · Webhook -> SMS_Booking_Engine code -> Respond_OK (booking_reply and available_slots written inside the code node)SMS Booking & Ops
Schematic · module flow — drag & zoom
drag to pan · scroll or +/− to zoom
Receive Booking Request
Receives a booking action (book, reschedule, cancel, or check appointment) for a specific homeowner.
Calendar Brain
Handles the full booking request: checks open slots, books or changes the appointment in the CRM calendar, and writes the result and available times to two CRM fields the SMS bot reads to reply to the homeowner.
Done
Confirms the booking action is complete so the calling workflow can continue.
Writes 3 GHL custom fields: booking_reply, available_slots, appointment_time_display; Jenny reads booking_reply on her next outbound message3 nodes · Webhook -> SMS_Booking_Engine code -> Respond_OK (booking_reply and available_slots written inside the code node)

Trigger

HTTP POST to stonebriar/sms-book from Tag_Bridge_Poller with {contact_id, action}. Action values: book, reschedule, cancel, check, prefetch. Cloned from Beem n8n_beem_book.js v6 (2026-06-16), adapted for GHL-native calendar.

Module flow

  1. WebhookListens at stonebriar/sms-book; accepts {contact_id, action} stonebriar/sms-book contact_id action
  2. SMS_Booking_Engine code nodeSingle code node implementing all 5 actions: book (POST /calendars/events/appointments), reschedule (PUT), cancel (DELETE), check (GET appointments + format), prefetch (GET free-slots + format for bot prompt). Timezone hardcoded America/Chicago throughout. America/Chicago /calendars/events/appointments /calendars/free-slots book reschedule cancel check prefetch
  3. Write booking_reply fieldWrites the natural-language outcome (e.g. 'Your inspection is booked for Tuesday June 24 at 10 AM') to GHL LARGE_TEXT field mj2pMnYp9cOsiAo9y0qT -- Jenny merges this via {{contact.booking_reply}} mj2pMnYp9cOsiAo9y0qT booking_reply
  4. Write available_slots fieldOn prefetch/check actions: writes formatted slot list to field 0gK2qWEIrK94ysqGDzEX so Jenny's prompt includes real availability 0gK2qWEIrK94ysqGDzEX available_slots
  5. Write appointment_time_displayOn successful book/reschedule: writes human-readable appointment time to TEXT field BlD6F0J5yvDzcgUV7uWN for CRM display BlD6F0J5yvDzcgUV7uWN appointment_time_display
  6. Respond_OKFinal respondToWebhook confirming engine completed
booking_reply as the truth source
Rather than Jenny guessing the booking outcome from LLM memory, the engine writes the confirmed result into a GHL field that Jenny merges verbatim -- eliminating hallucinated confirmations, carried forward from the Beem v6 pattern.
SMS Booking & Ops

Appointment lookup

Stonebriar_Schedule_CheckfiringLook up a contact's next upcoming appointment and write the result to booking_reply -- handles both voice (skip SMS) and SMS channels

Outcome The homeowner is told their real upcoming inspection — by text, or read out by Sarah on a call — straight from the calendar, with no guessing.

n8n · Stonebriar_Schedule_Check — actual build
Stonebriar_Schedule_Check n8n canvas
The live n8n canvas.
17 nodes · Webhook -> Config -> Get Appointments -> Filter -> [found: Write Display + Write booking_reply + CRM Note -> Channel Gate -> SMS or skip] | [not found: Write booking_reply + CRM Note -> Channel Gate] -> Respond OKSMS Booking & Ops
Schematic · module flow — drag & zoom
drag to pan · scroll or +/− to zoom
Receive Request
Listens for an incoming request asking whether this contact has an appointment booked.
Set Variables
Stores the contact ID, API keys, and channel type so every later step has what it needs.
Fetch Appointments
Asks the CRM for all upcoming appointments linked to this contact.
Find Next Appt
Filters the list to just the next upcoming appointment and formats the date/time nicely.
Appointment Exists?
Checks whether a future appointment was actually found. Routes to 'yes' or 'no' branches.
Save Appt Display
Saves the appointment date/time to the CRM so Sarah (voice AI) can read it back.
Write Found Reply
Writes the confirmation message to the CRM reply field for Sarah to say.
Log Appt Found
Logs a CRM note confirming an appointment was found and the customer was told.
Via Voice Call?
If the request came from a voice call, skips the text — Sarah speaks the answer.
Send Appt Text
Sends the customer a text message confirming their upcoming appointment date and time.
Log SMS Error
If the text fails to send, logs a CRM note so the team knows.
Log No Appt
Adds a note to the CRM confirming no upcoming appointment was found for this contact.
Write No-Appt Reply
Writes the no-appointment message to the CRM reply field for Sarah to read.
Via Voice Call?
If the no-appointment result came from a voice call, skips the text message.
Send No-Appt Text
Sends the customer a text message letting them know there is no appointment on file.
Send Answer Back
Sends the final answer back to Sarah or the SMS bot to continue the conversation.
Writes booking_reply (mj2pMnYp9cOsiAo9y0qT) and appointment_time_display (BlD6F0J5yvDzcgUV7uWN) to GHL; sends SMS confirmation for non-voice callers17 nodes · Webhook -> Config -> Get Appointments -> Filter -> [found: Write Display + Write booking_reply + CRM Note -> Channel Gate -> SMS or skip] | [not found: Write booking_reply + CRM Note -> Channel Gate] -> Respond OK

Trigger

HTTP POST to stonebriar/schedule-check from Tag_Bridge_Poller (tag=schedule-check) or directly from a Retell voice agent function tool call (with channel=voice in payload). Payload: {contact_id, channel?}.

Module flow

  1. Webhook + ConfigWebhook at stonebriar/schedule-check; Config set node loads GHL API creds and calendar ID HwJD5Ujgck1FJERzBZVw stonebriar/schedule-check HwJD5Ujgck1FJERzBZVw
  2. Get_Contact_AppointmentsGET /contacts/{id}/appointments to retrieve all appointments for this contact /contacts/{id}/appointments
  3. Filter_And_FormatCode node: filters for confirmed future appointments on calendar HwJD5Ujgck1FJERzBZVw, sorts by start time, formats in Central Time (America/Chicago) confirmed America/Chicago
  4. Appointment_Found? branchesIF: appointment found -> Write_Appt_Display_Field then Write_Booking_Reply_Found then CRM_Note_Found; not found -> Write_Booking_Reply_None then CRM_Note_None Write_Booking_Reply_Found Write_Booking_Reply_None
  5. Channel_Is_Voice_Found / None gatesIF on each path: if channel=voice, goes directly to Respond_OK (skips SMS); otherwise sends SMS confirmation via GHL conversations API channel=voice /conversations/messages
  6. CRM_Note_SMS_FailedcontinueErrorOutput on the SMS node: if SMS send fails, writes a CRM note and still responds OK -- booking_reply field is already written CRM_Note_SMS_Failed
  7. Respond_OKrespondToWebhook terminates the workflow; Retell reads booking_reply from GHL field if calling as a function tool
SMS Booking & Ops

Appointment cancel

Stonebriar_Appt_CancelfiringCancel the contact's next upcoming inspection appointment, remove the booked tag, write booking_reply, and notify the homeowner -- with voice-channel awareness to skip the SMS when called from Sarah

Outcome The inspection is cancelled on the calendar, the booked tag is removed, and the homeowner gets a confirmation — keeping the calendar and the CRM in sync.

n8n · Stonebriar_Appt_Cancel — actual build
Stonebriar_Appt_Cancel n8n canvas
The live n8n canvas.
22 nodes · Webhook -> Config -> Get Appointments -> Find Upcoming -> [not found: Note + exit] | [found: Cancel -> [fail: Note + exit] | [success: Remove Tag + Clear Field + Write booking_reply + Tag -> Channel Gate -> SMS or skip]] -> Respond OKSMS Booking & Ops
Schematic · module flow — drag & zoom
drag to pan · scroll or +/− to zoom
Cancel Request
Receives a cancel request from the voice AI (Sarah) or the SMS system for this contact.
Set Credentials
Loads the API keys and location settings needed for all the steps that follow.
Fetch Appointments
Pulls this contact's upcoming appointments from the CRM to find the one to cancel.
Find Next Appointment
Identifies the soonest upcoming appointment in the list to be the one that gets cancelled.
Appointment Exists?
Checks whether this contact actually has an upcoming appointment to cancel.
Cancel Appointment
Deletes the appointment from the calendar in the CRM.
Cancel Worked?
Checks whether the cancellation actually went through successfully.
Log Cancellation Note
Writes a note in the CRM confirming the appointment was cancelled and when.
Remove Booked Label
Removes the 'booked' label from the contact because they no longer have an appointment.
Clear Appointment Time
Wipes the appointment time field in the CRM so it doesn't show an old, cancelled time.
Write Cancellation Reply
Saves a cancellation message to the CRM so the bot can relay it to the customer.
Tag As Cancelled
Labels the contact in the CRM as 'cancelled' so the team knows the appointment is gone.
Voice or SMS?
Skips the text message if the request came from a phone call instead of SMS.
Send Cancel Confirmation SMS
Texts the customer to confirm their appointment has been cancelled.
Log SMS Failure
Writes a CRM note if the confirmation text failed, so nothing is lost silently.
Log Cancel Failure
Writes a note in the CRM if the cancellation failed so staff can follow up manually.
Log Appt Not Found
Writes a note in the CRM when no upcoming appointment was found to cancel.
Write Not-Found Reply
Saves a 'no appointment found' message to the CRM so the bot can relay it to the customer.
Voice or SMS?
Checks if this came from a phone call or SMS to decide whether to send a text reply.
SMS: No Appt Found
Texts the customer to let them know no upcoming appointment was found to cancel.
Send Response
Sends the final 'done' signal back to the voice AI or SMS system to close out the request.
Clears booking_reply and appointment_time_display in GHL; booked tag removed; SMS sent for non-voice channel22 nodes · Webhook -> Config -> Get Appointments -> Find Upcoming -> [not found: Note + exit] | [found: Cancel -> [fail: Note + exit] | [success: Remove Tag + Clear Field + Write booking_reply + Tag -> Channel Gate -> SMS or skip]] -> Respond OK

Trigger

HTTP POST to stonebriar/cancel-appt from Tag_Bridge_Poller (tag=cancel-requested) or from a Retell voice agent function tool call (with channel=voice). Payload: {contact_id, channel?}.

Module flow

  1. Webhook + ConfigWebhook at stonebriar/cancel-appt; Config loads GHL creds and calendar ID HwJD5Ujgck1FJERzBZVw stonebriar/cancel-appt HwJD5Ujgck1FJERzBZVw
  2. Get_Contact_Appointments + Find_Upcoming_ApptGET appointments; code node finds the soonest confirmed future event and extracts its event_id for the DELETE call /contacts/{id}/appointments event_id
  3. Appointment_Found? -> Cancel_EventIF: if appointment found, DELETE /calendars/events/{eventId}; if not found, branches to CRM_Note_Not_Found and exits /calendars/events/{eventId} DELETE
  4. Cancel_Succeeded? -> CRM_Note_CancelledIF: on successful delete, writes CRM note; on failure writes CRM_Note_Cancel_Failed and exits CRM_Note_Cancelled CRM_Note_Cancel_Failed
  5. Remove_Booked_Tag + Clear_Appt_Time_DisplayRemoves booked tag from contact; clears appointment_time_display field BlD6F0J5yvDzcgUV7uWN booked BlD6F0J5yvDzcgUV7uWN /contacts/{id}/tags
  6. Write_Booking_Reply_CancelledWrites cancellation confirmation text to booking_reply field mj2pMnYp9cOsiAo9y0qT for Jenny to merge mj2pMnYp9cOsiAo9y0qT booking_reply
  7. Add_Cancelled_Tag_Fallback + Channel_Is_Voice_CancelledAdds a cancelled tag for funnel tracking; Channel IF: voice channel goes directly to Respond_OK; SMS channel sends confirmation via GHL conversations API channel=voice /conversations/messages
  8. CRM Note branches (all paths)Every exit path (cancelled, failed, not found, SMS failed) writes a CRM note -- GR-008 visible artifact on every branch CRM_Note_SMS_Failed CRM_Note_Not_Found
SMS Booking & Ops

Inbound caller lookup

Stonebriar_inbound_lookupfiringIdentify an inbound caller in real time -- normalise the phone, search GHL, find their upcoming appointment, and return a structured summary to the Retell inbound agent within the function-tool timeout

Outcome When a homeowner calls the main line, Sarah instantly knows who they are and their next inspection, so she greets them by name and helps right away instead of “let me look you up.”

n8n · Stonebriar_inbound_lookup — actual build
Stonebriar_inbound_lookup n8n canvas
The live n8n canvas.
11 nodes · Webhook -> Config -> Normalize -> Has Phone? -> [no: No_Match] | [yes: GHL Search -> Pick Contact -> Contact Found? -> [no: No_Match] | [yes: Get Appointments -> Format Found]] -> RespondSMS Booking & Ops
Schematic · module flow — drag & zoom
drag to pan · scroll or +/− to zoom
Receive Call Request
Fires when a call comes in — Sarah asks this workflow who is calling.
Set Variables
Stores the CRM API key and location ID so the lookup steps have what they need to search.
Clean Phone Number
Converts the caller number to +1XXXXXXXXXX format so the CRM search works.
Phone Present?
Checks that a valid phone number was provided before attempting a CRM search.
Search CRM by Phone
Looks up the caller's phone number in the CRM to find any matching contact record.
Select Best Match
If the CRM returns multiple matches, picks the most relevant contact to use for this call.
Known Caller?
Checks if the caller is in the CRM — routes to known or unknown branch.
Fetch Appointments
Retrieves any upcoming appointments booked for this contact so Sarah knows their schedule.
Build Contact Summary
Packages name, contact ID, and next appointment into a summary for Sarah.
Build Unknown Response
Prepares an unknown-caller response so Sarah treats them as a new lead.
Send Answer to Sarah
Sends the caller summary back to Sarah so she can greet them by name.
Returns data to Retell inbound agent synchronously; no GHL writes11 nodes · Webhook -> Config -> Normalize -> Has Phone? -> [no: No_Match] | [yes: GHL Search -> Pick Contact -> Contact Found? -> [no: No_Match] | [yes: Get Appointments -> Format Found]] -> Respond

Trigger

HTTP POST to stonebriar/inbound-lookup called by the Retell inbound agent as a lookup_caller function tool when a homeowner calls the Stonebriar main line. Payload contains either body.args.phone or body.call.from_number (two shapes are handled after a bug fix).

Module flow

  1. Webhook + ConfigWebhook at stonebriar/inbound-lookup; Config loads GHL API key and location ID stonebriar/inbound-lookup
  2. Normalize_PhoneCode node: handles both body.args.phone and body.call.from_number input shapes; normalises to E.164 (+1XXXXXXXXXX) body.args.phone body.call.from_number E.164
  3. Has_Phone? -> GET_Contacts_By_PhoneIF: if normalised phone is valid, search GHL /contacts/ by phone; if not, go directly to No_Match response /contacts/ phone
  4. Pick_ContactCode node: selects the best GHL contact match from search results
  5. Contact_Found? -> Get_Contact_AppointmentsIF: if contact found, GET /contacts/{id}/appointments; if not found, go to No_Match with empty response /contacts/{id}/appointments
  6. Format_FoundCode node: builds structured response with contact_id, first_name, email, has_appointment (bool), appointment_summary (plain text), event_id contact_id first_name has_appointment appointment_summary event_id
  7. No_Match + RespondNo_Match code returns empty-contact response; single Respond respondToWebhook node handles both found and not-found paths
Part 2 · Email Assistant
Email Assistant

The email AI assistant

StoneBriar_Email_Bot-Multi-AgentfiringWhen a lead emails in, a multi-agent AI reads the full contact context, routes to the right specialist, drafts a personalized reply, and sends it.

Outcome Inbound emails get an on-brand, context-aware reply in seconds. The right specialist agent handles each one -- book, answer, handle an objection, or escalate -- and every exchange is logged back to the CRM.

n8n · StoneBriar_Email_Bot-Multi-Agent — actual build
StoneBriar_Email_Bot-Multi-Agent n8n canvas
The live n8n canvas.
30 nodes -> reads context -> multi-agent reply -> Send_Reply -> Log ConversationEmail Assistant
Schematic · module flow — drag & zoom
drag to pan · scroll or +/− to zoom
New Lead Webhook
Entry point — inbound email
Workflow Configuration
Loads the location, keys & settings
Check Conversation History
Checks prior email history
Check If Welcome Email Sen
Welcome email (currently deactivated)
Send Welcome Email
Welcome email (currently deactivated)
Log Welcome Email Sent
Welcome email (currently deactivated)
Get Conversation Thread
Loads the prior email thread
Log Conversation
Logs the exchange back to GHL
Send Reply
Sends the email reply
Webhook
Entry point — inbound email
Get Conversation
Reads the conversation record
Search contact1
Pulls the emailer's full GHL record
Get Custom Fields
Reads the contact's custom fields
Get Custom Values
Reads campaign values
Map campaign values
Maps campaign data into context
Map Custom Fields
Maps the fields into context
Call 'Stone Briar Get Appo
Pulls the contact's appointments
Config
Loads the location, keys & settings
Build Universal Agent Cont
Assembles everything into agent variables
Open AI Chat Model2
The LLM behind the agent
Conversation Memory1
Remembers the thread so replies stay coherent
Think1
Lets the agent reason before replying
Ultimate Assistant
The multi-agent AI: routes to the right specialist
Booking agent
Specialist: books the appointment
Simple response agent
Specialist: quick factual reply
Information agent
Specialist: answers product / service questions
Objection handling agent
Specialist: handles objections
Escalation agent
Specialist: escalates to a human
Update GHL Contact Memory
Remembers the thread so replies stay coherent
Generate Memory Summary
Remembers the thread so replies stay coherent
Reads the contact + appointment + thread context, replies by email, logs to GHL30 nodes -> reads context -> multi-agent reply -> Send_Reply -> Log Conversation

Trigger

Fires on an inbound email. It loads the contact's full GoHighLevel record, custom fields, campaign values, appointments, and the prior email thread before the AI replies.

Module flow

  1. config + Search_contactLoads settings and pulls the emailer's full GoHighLevel record.
  2. Custom fields + campaign valuesMaps the contact's fields and campaign data into context. GHL
  3. Get appointments + conversation threadPulls existing appointments and the prior email thread so the AI has the full picture.
  4. Build Universal Agent ContextAssembles everything into the variables the AI reads.
  5. Ultimate Assistant (multi-agent)A LangChain agent with memory plus 5 specialist tools: booking, simple-response, information, objection-handling, escalation. OpenAI memory
  6. Send_Reply + Log ConversationSends the email reply and logs the exchange back to GoHighLevel. visible artifact
Why multi-agent
One prompt cannot be great at everything. A router with specialist sub-agents (booking, objections, info, escalation) sends each email to the right expert, while the conversation memory keeps replies coherent across a thread -- and every message lands back on the contact record.
Part 2 · Supporting
Supporting

Rep SMS reply poller

Stonebriar_Rep_Reply_PollerfiringMonitor the GHL inboxes of two field reps every minute and forward any new inbound text messages to Rep_Outcome_Catcher for outcome processing

Outcome A field rep just texts 1, 2 or 3 after an inspection and it's picked up automatically and handed to the outcome catcher — no app, no form to fill in.

n8n · Stonebriar_Rep_Reply_Poller — actual build
Stonebriar_Rep_Reply_Poller n8n canvas
The live n8n canvas.
2 nodes · Every 1 min -> Poll rep replies (single code node, both staff numbers)Supporting
Schematic · module flow — drag & zoom
drag to pan · scroll or +/− to zoom
Every 1 Minute
Wakes up every minute to check whether any reps have sent new text messages in.
Check Rep Inboxes
Reads new inbound SMS messages from two staff phone numbers in the CRM. Any new reply is forwarded straight to the Rep Outcome Catcher workflow to record the inspection result.
POSTs new rep messages to Stonebriar_Rep_Outcome_Catcher at stonebriar/rep-outcome2 nodes · Every 1 min -> Poll rep replies (single code node, both staff numbers)

Trigger

n8n Schedule trigger: every 1 minute. Polls GHL conversations for two hardcoded staff phone numbers: Darian (+14693436120) and a second rep (+18325852875). Uses n8n staticData to track the last-seen message ID per rep so only genuinely new messages are forwarded.

Module flow

  1. Every 1 minSchedule trigger fires every 60 seconds minutesInterval: 1
  2. Poll rep replies -> catcherCode node: queries GHL conversations for Darian (+14693436120) and a second rep (+18325852875); uses staticData to track last-seen message ID per number; for each new inbound message, POSTs {from_phone, body, contact_id} to stonebriar/rep-outcome; bootstrap guard on first run seeds seen state without replaying history +14693436120 +18325852875 stonebriar/rep-outcome staticData pit-b4407fda-bbf6-44c4-9007-bee80f590d00
Supporting

Rep outcome recorder

Stonebriar_Rep_Outcome_CatcherfiringAccept a rep's 1/2/3 digit text, map it to the homeowner who just had an inspection, record the appointment outcome in GHL, and confirm back to the rep

Outcome The result the rep texted is written onto the right customer's record and the rep gets a confirmation — so the pipeline reflects what actually happened in the field.

n8n · Stonebriar_Rep_Outcome_Catcher — actual build
Stonebriar_Rep_Outcome_Catcher n8n canvas
The live n8n canvas.
3 nodes · Webhook -> Catcher code node -> Respond 200Supporting
Schematic · module flow — drag & zoom
drag to pan · scroll or +/− to zoom
Receive Rep Text
Receives the digit (1, 2, or 3) that a field rep texted in after completing a roof inspection.
Record Outcome
Maps the rep's digit to the correct pending homeowner, writes the inspection result to their CRM record, removes the pending tag, and texts the rep a confirmation. If multiple customers are pending, asks the rep to clarify which one.
Done
Confirms the outcome has been recorded and the workflow is finished.
Writes appointment outcome field to GHL customer contact; GHL WF reads this field to move the opportunity stage3 nodes · Webhook -> Catcher code node -> Respond 200

Trigger

HTTP POST to stonebriar/rep-outcome from Stonebriar_Rep_Reply_Poller. Payload: {from_phone, body, contact_id}. The body field contains the rep's reply digit (1=completed, 2=no-show, 3=reschedule).

Module flow

  1. WebhookListens at stonebriar/rep-outcome; receives {from_phone, body, contact_id} from Rep_Reply_Poller stonebriar/rep-outcome from_phone body
  2. Catcher code nodeValidates from_phone is a known staff number; maps body digit (1/2/3) to appointment outcome text; searches GHL for contacts tagged outcome-pending; sets appointment outcome field (27quKIEu2BIBFCyszE0E) on the matching customer; strips outcome-pending tag; texts the rep a confirmation; handles disambiguation if multiple pending customers exist 27quKIEu2BIBFCyszE0E outcome-pending appointment outcome +14693436120 +18325852875
  3. Respond 200respondToWebhook terminates the workflow after outcome is recorded
Rep-native interface
Field reps report outcomes by texting a single digit from their personal phone -- no app, no login. The catcher's phone allowlist ensures only known staff numbers can write outcome data to contacts.
Supporting

Appointment safety net

Stonebriar_Appt_Safety_NetfiringCatch any inspection appointment that ended without a rep outcome being recorded -- auto-mark it as a no-show after 3 hours or escalate with a GHL task after 4 hours

Outcome No inspection slips through the cracks — if a rep forgets to report, this auto-marks a no-show after a few hours and flags overdue ones, keeping the pipeline honest on its own, every hour.

n8n · Stonebriar_Appt_Safety_Net — actual build
Stonebriar_Appt_Safety_Net n8n canvas
The live n8n canvas.
2 nodes · Schedule Trigger -> Outcome Poller (all logic in one code node)Supporting
Schematic · module flow — drag & zoom
drag to pan · scroll or +/− to zoom
Every Hour
Runs automatically every hour to catch any appointments that have ended without a recorded outcome.
No-Show Auto-Detector
Scans the last 26 hours of ended appointments. If a rep never reported an outcome and 3+ hours have passed, it auto-marks the homeowner as a no-show in the CRM and moves them to the correct pipeline stage. After 4 hours it also creates a follow-up task for the rep.
Writes to GHL contacts (tags, outcome field), moves opportunity pipeline stage, creates GHL tasks for reps2 nodes · Schedule Trigger -> Outcome Poller (all logic in one code node)

Trigger

n8n Schedule trigger: every 1 hour. Scans GHL calendar HwJD5Ujgck1FJERzBZVw for all appointments that ended within the last 26 hours. Uses n8n staticData to act at most once per appointment ID.

Module flow

  1. Schedule TriggerFires every 60 minutes to scan for unresolved inspection outcomes hoursInterval: 1
  2. Stonebriar Outcome Poller code nodeQueries GHL calendar events for appointments ended in last 26h; for each: checks outcome field (27quKIEu2BIBFCyszE0E) and outcome-set tag -- skips if already handled; if ended >3h and no outcome: writes CRM note FIRST (GR-008), moves pipeline to No-Show stage (bc717599), adds no-show + outcome-no-show tags, removes booked; if ended >4h and not flagged: writes CRM note, creates GHL task for rep, adds outcome-overdue tag; within 3h grace window: skip. staticData deduplicates across runs. 27quKIEu2BIBFCyszE0E outcome-set bc717599-e7e6-4133-bbb7-c8306495e1ca no-show outcome-no-show outcome-overdue HwJD5Ujgck1FJERzBZVw staticData
CRM note before pipeline move
The safety net writes the CRM note as the very first GHL write before the pipeline stage move -- ensuring a visible audit trail in GHL even if the stage update fails mid-execution.
Supporting

Bulk reactivation push

Stonebriar_Reactivation_Bulk_PushfiringRe-enter a batch of dormant leads into the nurture system by tagging them for the 7-touch reactivation cadence or the full 14-day fresh funnel

Outcome A batch of dormant leads is dropped back into a re-engagement cadence in one go — turning the 2,000–10,000-lead database back into booked inspections.

n8n · Stonebriar_Reactivation_Bulk_Push — actual build
Stonebriar_Reactivation_Bulk_Push n8n canvas
The live n8n canvas.
5 nodes · Webhook -> Respond Accepted (async split) -> Config + Parse -> Process Leads -> Batch SummarySupporting
Schematic · module flow — drag & zoom
drag to pan · scroll or +/− to zoom
Receive Lead List
Receives a list of dormant leads (as a JSON file) to re-engage, along with campaign settings.
Confirm Received
Immediately tells the sender 'got it' while the lead processing continues in the background.
Validate & Configure
Reads the lead list, sets the campaign mode (reactivation or fresh funnel), and checks for dry-run mode.
Tag Each Lead
Loops through every lead, upserts them in the CRM, and applies the reactivation tag to restart their follow-up sequence.
Batch Report
Tallies how many leads were processed, skipped, or errored and returns a final count summary.
Tags trigger GHL WF-6 (60-day-sunset path) or GHL WF-1 (non-booked-funnel path); no direct n8n downstream5 nodes · Webhook -> Respond Accepted (async split) -> Config + Parse -> Process Leads -> Batch Summary

Trigger

HTTP POST to stonebriar/reactivation-bulk-push with {leads:[{contact_id,...}], mode, dry_run?, entry_tag?}. Mode=reactivation tags with 60-day-sunset (GHL WF-6). Mode=fresh tags with non-booked-funnel (GHL WF-1). Supports dry_run=true for testing without writing tags.

Module flow

  1. WebhookListens at stonebriar/reactivation-bulk-push; receives the leads batch with mode and optional dry_run stonebriar/reactivation-bulk-push leads[] mode dry_run
  2. Respond AcceptedSends immediate 200 to the caller before the batch begins (prevents HTTP timeout on large batches)
  3. Config + ParseCode node: validates body.leads array, determines tag to apply (60-day-sunset for mode=reactivation, non-booked-funnel for mode=fresh), sets throttle delay between contacts 60-day-sunset non-booked-funnel mode
  4. Process LeadsCode node: iterates the leads array sequentially with throttle; for each valid contact_id, applies the tag to GHL /contacts/{id}/tags; dry_run skips all GHL writes; tracks processed/skipped/error counts /contacts/{id}/tags dry_run throttle
  5. Batch SummaryCode node: assembles and logs batch results (total, processed, skipped, errors) for operator review processed skipped errors
Supporting

Referral lead intake

Stonebriar_Referral_IntakefiringParse a field rep's free-text referral message into a phone number and name, create the referral contact in GHL, and update the referring rep's record with a capture confirmation

Outcome A rep's quick “my neighbor has hail damage” text becomes a real new lead in the CRM (and the referrer gets credited) — so word-of-mouth enters the same machine as every other lead.

n8n · Stonebriar_Referral_Intake — actual build
Stonebriar_Referral_Intake n8n canvas
The live n8n canvas.
21 nodes · Webhook -> Respond Accepted -> Get Referrer -> Parse Referral -> [no phone: Tag Pending + Note] | [phone: Upsert -> New/Existing -> Read Back -> Update Referrer -> Note + Tag Captured]Supporting
Schematic · module flow — drag & zoom
drag to pan · scroll or +/− to zoom
Referral Received
Receives a referral submission from a sales rep via text message or the CRM.
Acknowledge Receipt
Immediately confirms the referral was received so the rep's system knows it went through.
Look Up Rep
Pulls the referring sales rep's contact record from the CRM using their ID.
Extract Name & Phone
Reads the rep's free-text message and pulls out the new lead's name and phone number.
Phone Number Found?
Checks if a valid phone number was found; if not, flags it for manual follow-up.
Create or Update Lead
Creates a new contact for the referred lead in the CRM, or updates them if they exist.
Brand New Lead?
Checks if the referred person is a new contact or someone already in the CRM.
Set Lead Details
Fills in the source and other details on the new lead's record in the CRM.
Tag as New Referral
Labels the new lead 'referred-lead' so they enter the right follow-up process.
Tag Existing Contact
Labels a known contact 'referred-existing' so staff knows they were referred again.
Verify Lead Saved
Re-reads the new lead's record from the CRM to confirm the data was saved correctly.
Confirm Data Correct
Checks that the name, phone, and tags were actually written to the CRM without errors.
Credit the Rep
Updates the referring rep's record in the CRM to count this referral toward their total.
Clear Pending Tag
Removes the pending label from the rep now that this referral is fully captured.
Build Receipt Message
Builds a confirmation message for the rep summarising the new lead that was just created.
Save Receipt Note
Writes the confirmation summary as a note on the rep's contact record in the CRM.
Tag Referral Captured
Labels the rep's contact as 'referral-captured' to mark this referral loop as complete.
Flag for Manual Entry
Writes a note on the rep's record: no phone number found, manual follow-up needed.
Tag Referral Pending
Labels the rep 'pending' so staff knows there's an incomplete referral to follow up on.
Build Manual Notice
Builds a message for the rep: referral received but a phone number is still needed.
non-booked-funnel tag on new referral contact triggers GHL WF-1; referrer record updated in GHL21 nodes · Webhook -> Respond Accepted -> Get Referrer -> Parse Referral -> [no phone: Tag Pending + Note] | [phone: Upsert -> New/Existing -> Read Back -> Update Referrer -> Note + Tag Captured]

Trigger

HTTP POST to stonebriar/referral_intake from a GHL Workflow triggered when a rep tags a contact with stonebriar-referral. Payload: {referrer_contact_id, referral_text}. The referral_text is the rep's raw SMS message containing a name and/or phone number.

Module flow

  1. Webhook + Respond AcceptedWebhook at stonebriar/referral_intake; Respond Accepted fires immediately for async processing stonebriar/referral_intake referrer_contact_id referral_text
  2. Get ReferrerGET /contacts/{referrer_contact_id} to fetch the referring rep's full record /contacts/{id}
  3. Parse ReferralCode node: extracts a US phone number (normalised to E.164) and name from free text using regex; three outcomes: phone+name found, name only, unparseable E.164 regex
  4. Has Phone? -> Upsert ReferralIF: if phone found, POST /contacts/upsert by phone to create or find existing contact; if no phone, branches to manual-follow-up path /contacts/upsert
  5. New Contact? -> Set New Fields + Tag NewIF: if new contact, sets fields (name, source=referral) and tags referred-lead + non-booked-funnel; if existing, tags referred-existing referred-lead non-booked-funnel referred-existing
  6. Read Back Referral + Verify WriteRe-fetches the upserted contact and verifies the write succeeded (read-back confirmation pattern)
  7. Update Referrer Fields + Remove Pending TagIncrements referral count field on referrer; removes referral-intake-pending tag; adds referral-captured tag referral-intake-pending referral-captured
  8. Write Receipt NoteWrites a CRM note on the referrer contact confirming the referral was captured (name, phone, new contact ID) /contacts/{id}/notes
  9. Manual path (no phone found)Tags referrer referral-intake-pending; writes a note asking rep to provide a phone number; Manual Receipt code builds the note body referral-intake-pending Note Manual
Supporting

Error alert

Stonebriar_error_alertfiringCatch any workflow failure on the n8n instance and send an immediate Gmail alert to Jay with full error context

Outcome If any workflow ever fails, Jay gets an email instantly with the details — so problems are caught and fixed fast instead of silently breaking the system.

n8n · Stonebriar_error_alert — actual build
Stonebriar_error_alert n8n canvas
The live n8n canvas.
2 nodes · Error Trigger -> Send Gmail (jjcavada1@gmail.com)Supporting
Schematic · module flow — drag & zoom
drag to pan · scroll or +/− to zoom
Catch Any Error
Fires automatically whenever any Stonebriar workflow crashes or hits an unexpected error.
Email Jay
Sends an email to jjcavada1@gmail.com with the workflow name, the node that failed, the error message, and a direct link to the failed run.
Terminal -- sends email to jjcavada1@gmail.com; no downstream workflows2 nodes · Error Trigger -> Send Gmail (jjcavada1@gmail.com)

Trigger

n8n errorTrigger -- fires automatically when any workflow that has errorWorkflow set to WMmYytB6NH41OMHy encounters an unhandled error. No webhook or schedule. This is the global error handler for all Stonebriar workflows.

Module flow

  1. Error TriggererrorTrigger node: receives error context from any failing workflow -- workflow name, node name, error message, execution ID errorTrigger workflow.name node.name error.message executionId
  2. Send a message (Gmail)Sends email to jjcavada1@gmail.com with workflow name, failed node, error text, and a direct link to the n8n execution log jjcavada1@gmail.com Gmail execution URL
GR-002 compliance anchor
Every production Stonebriar workflow sets errorWorkflow=WMmYytB6NH41OMHy. This single workflow is what makes the error alerting system work -- without it wired, failures are silent. All alerts route to jjcavada1@gmail.com, never the dead devteam@ inbox.
Platform layer · the CRM

GoHighLevel · the CRM layer

GoHighLevel is the system of record: it holds every contact, runs the SMS bot, drives the pipeline, and fires the n8n workflows by adding tags. n8n does the heavy lifting; GHL is where the lead lives and where every action is written back so a human can always see it.

“Jenny” — the SMS Conversation-AI bot
Inbound texts are handled by GoHighLevel's built-in Conversation AI, “Jenny.” She answers, captures intent, and tags the contact (booking / reschedule / schedule-check / cancel). Those tags are the bridge: the n8n Tag-Bridge Poller picks them up and fires the right booking engine. Jenny talks; n8n does the calendar work.

The tags that drive everything

Adding a tag in GoHighLevel is what fires an automation. This is the wiring between GHL and n8n.

TagWhat it triggers
non-booked-funnel · -leadStarts the lead — GHL WF-1 fires the First Touch webhook into n8n
booking-requestedJenny captured a booking intent → SMS Booking Engine books it
reschedule-requested · cancel-requested→ the reschedule / cancel engine
schedule-check→ reads the appointment back from the calendar
bookedState tag: suppresses further dials and nurture (GR-001)
ai-active · engaged-not-bookedLead is mid-conversation — don't cold-call over it
rep-accountExcludes field-rep phones from the customer bot (GR-019)

GHL-side workflows & pipeline

In GoHighLevelRole
WF-1 · 14-Day Lead Cadence [Non-Booked]Two tag triggers fire the First Touch webhook + run the 14-day follow-up cadence
Jenny Conversation AIThe SMS bot: answers, captures intent, tags the contact
Lead pipelineNew Lead → Contacted → Booked — moved by the n8n post-call + booking engines
Custom fieldsRoof-image URL, booking_reply (the exact line the bot speaks), appointment fields
Platform layer · the voice agent

Retell · the voice agent

Retell is the voice. A GPT-4.1 outbound agent calls new storm-damage leads and an inbound line answers the main number. Mid-call, the agent reaches into n8n through function tools to read and write the calendar in real time.

AgentRole
Stonebriar OutboundCalls new leads, qualifies, books the inspection · gpt-4.1
Stonebriar Inbound (Jenny)Answers the main line, books + looks up callers
Primary number+1 469 224 4004

Functions — the tools the agent calls mid-call

Each is a live webhook into the n8n booking + CRM workflows. The agent uses them while talking.

FunctionWhat it does
check_calendar_availabilityIs a specific date/time open for an inspection?
check_calendar_slotsPull available slots from a given date
book_appointmentBook the roof inspection
get_appointment · update_appointment · cancel_appointmentRead, reschedule, or cancel the existing inspection
get_current_datetimeCurrent time in the prospect's timezone
schedule_callbackLog a callback time when they can't talk now
send_sms · send_emailText or email the booking link / details mid-call
update_ghl_contactWrite tags or fields to the contact mid-call
log_objectionCapture an objection verbatim
transfer_to_daylonLive-transfer to a human during AZ business hours

Dynamic variables — context passed in at call time

Injected from GoHighLevel so the agent already knows the lead before it speaks:

first_namelast_namephoneemailsb_property_addressproperty_typeroof_agesb_storm_damage_typesb_inspection_urgencyprimary_concernwarning_signsservice_areacompany_short_namecompany_phonecompany_websitecurrent_time

Prompt structure

The agent prompt is engineered, not improvised. Its backbone:

SectionWhy it's there
Identity + brand pronunciationWho she is and how to say the company name
NEVER FABRICATE DATAIf a lookup is empty, don't invent — a hard guard from a real incident
Existing-appointment CONFIRM MODERe-checks for a booking before offering a time — anti double-booking (GR-001)
Voice & style + banned phrasesSound like a warm human admin; no “AI tells”
Recording & complianceDiscloses recording near the top of the call
Greetings (outbound / inbound)A different opener depending on who called whom
Part 3 · Developer Reference

Full workflow inventory

All 35 workflows with live status. firing = running now · sub = building block called by others · standby = built, off, ready · retired = unpublished 2026-06-18. The 19 firing entry points are detailed in full above; the sub-workflows below are the reusable building blocks they call.

Sub-workflows (in use, called by the flows above)

Sub-workflowJob
GetFreeSlots_SubWorkflowQuery open inspection slots
GetAppointments_SubWorkflow (+ _JJ)List a contact's appointments
check_Availability_Sub_WorkflowsVerify a specific slot is open
appointment_booking_sub_workflowBook a confirmed slot
Update_Appointment_SubWorkFlowReschedule an appointment
Contact_Update_SubWorkflowAI-assisted contact field writer

What triggers what

The master map: every source event, the workflow it hits, and what happens next.

Source→ WorkflowDownstream effect
New lead created + tagged in GoHighLevelGHL WF-1 → first-touchGHL fires First Touch + runs the 14-day cadence
GHL tag non-booked-funnelfirst-touchRoof MMS → Dial 1 → Dial 2
First_Touch (internal)roof_image · voice_trigger_callRoof photo · Sarah dials
Retell agent (mid-call)voice_calendar_bookingsCheck / book / reschedule / get appt
Retell agent (inbound)inbound-lookupReturn caller + appointment to Sarah
Retell (call ends)voice_post_callDNC gate → summary → pipeline → log
GHL "Jenny" bot tags a contactTag_Bridge_PollerStrips tag → fires the right engine ↓
tag booking/reschedule-requestedsms-bookSMS_Booking_Engine books / reschedules
tag schedule-check / cancel-requestedschedule-check · cancel-apptRead back / cancel appointment
Field rep SMS (1/2/3)rep-reply-poller → rep-outcomeSet outcome field, confirm rep
cron · 1 hourAppt_Safety_NetAuto no-show / escalate
Any workflow errorerror_alertEmail to jjcavada1@gmail.com

Key IDs & config

Identifiers the workflows rely on. Secrets (keys/tokens) are redacted to their shape — real values live in the credential vault.

ItemValue
GHL locationU9eehdYVTaneVBVevw0b
Lead pipelinefMFWsnKweG7UwwUTnDJ2
Inspection calendarHwJD5Ujgck1FJERzBZVw
TimezoneAmerica/Chicago
Voice number+1 214 972 1282
Retell outbound agentagent_c7489b1000369067c5ef69e0dc
GHL token (PIT)pit-xxxxxxxx-xxxx-…
Retell API keykey_xxxxxxxx…
n8n instanceguerilla-fi.app.n8n.cloud

Retired / not in use

Verified against live execution history (2026-06-18). These are not firing — listed so the team knows exactly what's dormant and why. All reversible.

Retired — unpublished 2026-06-18 retired

The old n8n SMS chatbot subtree, superseded by the GoHighLevel "Jenny" bot + the tag bridge + the booking engines. Zero executions on record. Deactivated on 2026-06-18; can be switched back on if ever needed.

WorkflowWasReplaced by
sms_chatbotn8n LangChain SMS agentGHL Jenny bot + Tag_Bridge + engines
Send_SMS · Send_SMS_NotificationDirect Twilio SMS sendGHL conversations API

Standby / off (already inactive)

WorkflowStatus
Reactivation_Callstandby Sarah re-dial cadence — switch on when Twilio is live + 100+ leads queued
Slots_Prefetchoff redundant — SMS_Booking_Engine prefetches inline
Inbound_SMS_Handleroff old Twilio receiver — superseded
Simple_Response copy 2archived duplicate

Open items · for the dev

Surfaced by the live audit, ranked by priority. None block the system running — these are the "before you fully trust it" checks.

Worth tightening (medium)
Hardcode America/Chicago at the workflow level on voice_post_call + Voice_Calendar_Bookings. Confirm the inbound number routes to Retell (Twilio trunk Origination). Add the post-booking duplicate-check safety net in Voice_Calendar_Bookings.

Who to contact

RoleContact
Automation engineerJJ · jjcavada1@gmail.com
Stonebriar — primaryDarian Stephens · +1 469 343 6120
Stonebriar — opsAllison Dunn
Error alerts go tojjcavada1@gmail.com
n8n instanceguerilla-fi.app.n8n.cloud