DEV Community

Luis Cruz
Luis Cruz

Posted on

Building a Production AI Booking Agent: Architecture Notes from a Retell + n8n + GoHighLevel Build

I built an AI agent that answers inbound leads by voice and
SMS, qualifies them, checks live calendar availability
across two locations, and books the appointment. No human
step anywhere in the flow.

Here is how it is architected, and the decisions that made
it reliable.

The architecture

Three layers, with a hard boundary between them:

  • Retell AI handles conversation - voice and SMS, prompt design, qualification logic
  • n8n orchestrates - slot lookup, availability filtering, booking calls, error routing
  • GoHighLevel owns state - CRM records, calendar, and all message delivery

Decision 1: the LLM writes, the CRM sends

The most important boundary in the system. Retell generates
reply text and nothing else. It never holds a phone number
and never touches the send path.

Everything that delivers a message goes through GHL. This
means exactly one system is responsible for delivery, so
threading stays intact and every message is traceable to a
single source. Letting the model act directly on the send
path is where these systems get non-deterministic and
undebuggable.

Decision 2: timezone is configured, not inferred

The clinic runs two locations in Eastern time; the account
was provisioned in Central. Calendar timezone in GHL is set
per calendar and does not inherit from the account, so it
gets set explicitly - America/New_York - as a
configuration step, not an assumption.

Downstream, n8n datetime fields are built in Expression
mode with Luxon and setZone: true, so the local time you
constructed is the local time that arrives. Anything less
explicit coerces to UTC silently.

Decision 3: validation that fails loudly

Booking success is confirmed by testing the actual status
value the API returns - status === "booked" - not an
assumed status code. A booking system that reports success
on failure is worse than one that crashes, because nobody
finds out until a patient shows up to an appointment that
does not exist.

Same principle on the request side: GHL's booking endpoint
requires a title field, and its absence surfaces as a
validation error that appears to be about something else
entirely. Every required field is asserted before the call
rather than discovered from an error message.

What shipped

Full architecture diagrams, agent prompts for both voice
and SMS paths, the complete n8n workflow, a per-platform
testing checklist so the client could verify it themselves,
and a walkthrough video for handover.

Walkthrough: https://www.loom.com/share/dd792a043d6b4d4483adba463bbe02f3

I build AI agents, RAG pipelines, and automation systems
end to end. Available for contract work.

github.com/topstar-ai
jeanlimaav@gmail.com

ai #automation #n8n #showdev

Top comments (0)