Work snippetAI enquiry intake
AI enquiry intake with an approval queue and a cost-per-lead log
How I would approach enquiry intake for a field service business: each web form, shared inbox or chat enquiry is read by a model, checked against existing contacts, spam and service area, and drafted into an approval queue. A person approves before anything is created or sent, and a log shows what every lead costs by source.
Work snippet with example figures.
- Area
- AI enquiry intake
- Tools
- n8n · HubSpot · GoHighLevel · Airtable
- Typical scope
- US$1,600–2,900
- Timeline
- About 6 weeks · 4 fixed milestones
Problem
What the owner sees
- Enquiries arriving by web form, shared inbox and chat, each handled a different way
- Replies that depend on who happens to be at a screen
- The same customer created twice, or a repeat customer treated as new
- Spam and out-of-area requests that cost a callback
- No figure for what a lead from each ad or campaign actually costs
- A chatbot or auto-reply that promises a price or a date
Most of a new enquiry is reading: who is this, what do they want, how urgent is it, and have we dealt with them before. A model can do the reading and draft a reply quickly. It must not create a contact, send a message, quote a price or promise a date. The design reads and drafts, rules check, and a person approves. A log records what every lead cost, so spend is judged on bookings rather than clicks.
| Everyday situation | What goes wrong |
|---|---|
| The web form and the shared inbox both create a contact | Duplicate contacts, and two people replying |
| A repeat customer writes from a new address | Treated as new, and the history is lost |
| One email asks for two jobs | Only the first request is booked |
| An emergency enquiry waits in the inbox overnight | The customer calls the next business |
| Ad spend reported as clicks | Nobody knows what a booked job costs |
| A chatbot that quotes | A price is promised that nobody approved |
System map
A field service business that receives enquiries through a website form and a shared inbox, and optionally a chat widget. Contacts live in HubSpot or GoHighLevel. A person in the office approves each enquiry. The cost log lives in Airtable or Google Sheets.
The build reads each enquiry, drafts a reply and places both in an approval queue. Nothing is created in the CRM and nothing is sent until the reviewer approves. A weekly view shows cost per lead and cost per booked job by source.
| Part | What it does |
|---|---|
| Intake sources | The web form, the shared inbox and the chat widget each post the enquiry to one webhook. The source is recorded on every enquiry. |
| n8n or Make workflow | Runs the steps, applies the rules, calls the model and writes the log. It runs in your account. |
| Language model | One of the major LLM APIs such as OpenAI, Claude, Grok, Gemini and Mistral, or a local model, reads the enquiry and returns fields and a draft reply. It does not set prices or dates. |
| CRM | HubSpot or GoHighLevel. Searched for an existing contact, and written to only after approval. |
| Approval queue | Each enquiry with the extracted fields, the match result, the rule flags and the draft reply, for a person to edit and approve. |
| Cost-per-lead log | One row per enquiry in Airtable or Google Sheets: source, times, outcome, AI cost and the spend entered for that source. |
| Fallback | If the model is unavailable, the enquiry goes to the queue unread with a plain template reply. |
How the data moves
- Enquiry received
- Masked and read
- Contact, spam and area checks
- Approval queue
- Person edits and approves
- Contact created and reply sent
- Log updated
Rules agreed in writing
The model reads and drafts. Rules decide what happens next, and a person approves. Everything below is agreed in writing before the build starts.
| Item | Example setting |
|---|---|
| Fields read | Name, phone, email, address or suburb, service, urgency, source and a one-line summary. Anything missing is left blank and never guessed. |
| Urgency | Listed emergency words or services set an urgent flag and notify the on-call person. A person still approves. |
| Existing contact | Match on email, then phone, then name and address. A match shows the existing record in the queue. A near match is flagged and never merged by the build. |
| Spam | A rule score from known patterns and blank fields runs before the model call, so obvious spam costs nothing. Likely spam waits in a separate view and is logged as spam. |
| Service area | A postcode or suburb list supplied by you. An enquiry outside the list is flagged for a polite decline, which a person approves. |
| Prices and dates | The model never states a price, a discount or an appointment date. Drafts say that the office will confirm. |
| Other languages | The enquiry is read, summarised in your working language and queued with the original text. A person replies. |
| Personal data | Where you ask for it, names, phones and emails are masked before the model sees the text and restored by code afterwards. |
| Sending | Only from your own mailbox or CRM, and only by the approver. |
Flow steps
Eight steps run when each enquiry arrives. The weekly cost view is built each Monday morning.
| Step | Trigger | What happens | Result |
|---|---|---|---|
| 1 Receive | Form, email or chat | The enquiry is posted to the webhook with its source and the time received. | Raw enquiry stored |
| 2 De-duplicate | Raw enquiry | The same contact details and message within ten minutes are treated as one submission. | One enquiry |
| 3 Pre-check and mask | One enquiry | Obvious spam is held before any model call. Personal data is masked where agreed. | Masked text or spam hold |
| 4 Read | Masked text | The model returns the fields, urgency, a summary and a draft reply as structured data. Usage figures are logged. | Fields and draft |
| 5 Check | Fields | Rules check for an existing contact in HubSpot or GoHighLevel, the service area and the urgency words. | Flags |
| 6 Queue | Flags | The enquiry, fields, flags and draft go into the approval queue. Urgent items notify the on-call person. | Queue item |
| 7 Approve | Reviewer | The reviewer edits the fields and the reply, then approves, declines or marks the item as spam. | Decision |
| 8 Create and log | Approved | The contact is created or updated, the reply is sent from the approver’s mailbox or CRM and the log row is completed. | CRM and log updated |
Field mapping
Each field has one source and one destination. The source is set by code, never by the model.
| Field | Comes from | Written to | Rule |
|---|---|---|---|
| Name, email, phone | Model, checked by pattern | CRM contact | Pattern check. Left blank if not found. |
| Service requested | Model, from your service list | CRM deal or ticket property | Must match your list. Otherwise Other, and a person chooses. |
| Urgency | Model plus rule words | Queue flag and CRM property | Rule words win over the model. |
| Address or suburb | Model | Contact property | Used for the area check. A person confirms. |
| Source | Webhook | CRM source property and the log | Set by code, never by the model. |
| Existing contact ID | Search result | Queue and log | Shown to the reviewer. Decides update or create. |
| Summary | Model | CRM note | Saved on approval and marked as drafted for review. |
| Draft reply | Model | Queue only | Becomes a sent message only when approved. |
| AI cost | Provider usage figures | Log | Calculated by code from the tokens reported. |
Edge cases
Each case below is handled by a written rule and has a check in the test plan.
| Case | What the build does |
|---|---|
| A repeat customer writes with a new address | The existing contact is found by email or phone and shown in the queue. The new address is offered as an addition and never replaces the old one. |
| One email asks for two jobs | Both requests are listed as separate lines in the queue, with one reply that covers both. |
| The enquiry is in another language | Read, summarised in your working language and queued with the original text. A person replies. |
| An emergency | Flagged urgent, the on-call person is notified, and the item moves to the top of the queue. A person still approves. |
| A duplicate submission | The same contact details and message within ten minutes are merged into one queue item. |
| No contact details | The item is marked as having no way to reply. No contact is created and the reviewer decides. |
| The model is unavailable or returns unusable output | The enquiry goes to the queue unread with a plain template reply, and an alert is sent. |
| The enquiry arrives from an address already linked to a different contact | Both records are shown and the reviewer chooses. Nothing is merged automatically. |
Human sign-off and audit trail
Nothing is created in the CRM and nothing is sent until a person approves. The workflow holds no send step before approval.
| Who | Signs off | When | If nobody acts |
|---|---|---|---|
| Reviewer | Every enquiry, after editing, before the contact is created or the reply is sent | Each working day | The item waits. Nothing is sent. |
| Reviewer | Declines and out-of-area replies | Each working day | The item waits |
| On-call person | Urgent enquiries | On the alert | The alert repeats, then goes to the owner |
| Owner | Service list, area list, urgency words and reply wording | Before go-live and quarterly | Existing rules stay |
| Owner | Outcome and spend entries in the log | Weekly | The weekly view shows the gap |
| Field | Example |
|---|---|
| Enquiry ID | Log row number |
| Source and time | Source, and the time received and approved |
| Model | Model name and version, and the prompt version |
| Input | The text sent to the model, as masked |
| Output | The fields and draft returned |
| Flags | Existing contact, spam, area and urgency results |
| Edits | Text before and after, who and when |
| Decision | Approved, declined or spam, with the CRM record ID |
| AI cost | Tokens reported by the provider and the calculated cost |
Data and privacy
Enquiries hold names, phone numbers and addresses. The workflow keeps them inside your own accounts.
| Data | Handling |
|---|---|
| Enquiry text | Stored in the log and the queue in your accounts. Retention follows your policy. |
| Masking | Names, phones and emails can be masked before the model call and restored by code afterwards. |
| Model use | A hosted model on terms that do not allow training on your data, or a local model. |
| Prompts and outputs | Stored with the prompt version so any draft can be traced and explained. |
| API keys | Created in your own provider account and held in your workflow credentials. |
| Accounts | n8n or Make, the CRM and the log stay in your accounts. I am added as a user and removed at handover. |
Cost-per-lead log and API prices
The log answers one question: what does a lead from each source cost, and what does a booked job cost? Two kinds of cost go in. AI processing cost is calculated by code from the usage figures the model provider returns with each reply. Source spend, such as the week’s ad spend, is typed in by the owner. The build never estimates spend.
| Item | Who pays | Notes |
|---|---|---|
| Build, rules, queue, log and handover | You, to me, by milestone | Fixed scope, set out below |
| Model API usage | You, directly to the provider, on your own account and key | Not included in the project price. I add no mark-up. |
| n8n or Make, CRM and Airtable subscriptions | You, to each vendor | Your existing plans often cover it |
| Ad and campaign spend | You, to the ad platform | Entered in the log by the owner |
Model API usage is billed to you by the provider. It is not part of my fee and it is not in the project price. The table below shows what it costs at published list prices for major LLM APIs such as OpenAI, Claude, Grok, Gemini and Mistral.
| Provider | Model | Input | Output | One enquiry | Per 1,000 enquiries |
|---|---|---|---|---|---|
| OpenAI | GPT-6 Luna | 0.10 | 0.50 | 0.00055 | 0.55 |
| OpenAI | GPT-6.1 Terra | 1.00 | 5.00 | 0.00550 | 5.50 |
| Claude | Claude Haiku 5.5 | 0.10 | 0.50 | 0.00055 | 0.55 |
| Claude | Claude Sonnet 5.5 | 2.00 | 10.00 | 0.01100 | 11.00 |
| Grok | Grok 4.3 | 1.25 | 2.50 | 0.00463 | 4.63 |
| Gemini | Gemini 3.5 Flash-Lite | 0.30 | 2.50 | 0.00225 | 2.25 |
| Gemini | Gemini 3.8 Flash | 0.75 | 3.75 | 0.00413 | 4.13 |
| Mistral | Mistral Small 4 | 0.15 | 0.60 | 0.00074 | 0.74 |
| Mistral | Mistral Medium 3.5 | 1.50 | 7.50 | 0.00825 | 8.25 |
One enquiry is worked out as 2,500 input tokens (the instructions, the enquiry and the contact match) and 600 output tokens (the fields and the draft reply). These are example settings. Standard rates are used, with no batch or cache discount, and every provider counts tokens its own way, so the log uses the usage figures the provider returns. Gemini 3.8 Flash is shown at its introductory rate, which the provider lists as rising on 1 January 2027, and Claude Haiku 5.5 is shown at the rate for prompts up to 100,000 tokens. Prices and model names change often, so the price table in the log is a settings sheet that you or I can edit.
At these rates, even the dearest row comes to US$3.30 for 300 enquiries in a month, and the cheapest to about US$0.17. Model usage is a small part of what a lead costs. The log is there to show the ad spend next to it.
| Column | Filled by | When |
|---|---|---|
| Source and campaign | Webhook, from the form or the tracking tag | Step 1 |
| Time received | Webhook | Step 1 |
| Model and prompt version | Workflow | Step 4 |
| Tokens in and out | Provider usage figures | Step 4 |
| AI cost | Code: tokens multiplied by the price sheet | Step 4 |
| Time approved | Approval queue | Step 7 |
| Outcome: booked, quoted, lost or spam | Office staff, when the enquiry resolves | After step 8 |
| Weekly spend per source | Owner, on a separate Spend tab | Weekly |
| ID | Source | Received | Approved | Outcome | Tokens in | Tokens out | AI cost (US$) |
|---|---|---|---|---|---|---|---|
| E0412 | Google Ads form | Mon 08:14 | Mon 08:52 | Booked | 2,310 | 540 | 0.00050 |
| E0413 | Shared inbox | Mon 09:03 | Mon 09:40 | Quoted | 3,120 | 710 | 0.00067 |
| E0414 | Website form, organic | Mon 11:27 | Mon 11:31 | Spam | 0 | 0 | 0.00000 |
| E0415 | Meta ads form | Mon 14:46 | Tue 08:05 | Lost | 1,980 | 460 | 0.00043 |
| E0416 | Google Ads form | Tue 07:12 | Tue 07:19 | Booked | 2,640 | 620 | 0.00057 |
The spam row shows no model call, because the pre-check held it first. A cost of zero there is correct.
| Source | Enquiries | Spam | Valid leads | Booked | AI cost | Spend entered | Cost per lead | Cost per booked job |
|---|---|---|---|---|---|---|---|---|
| Google Ads form | 18 | 2 | 16 | 6 | 0.0088 | 420.00 | 26.25 | 70.00 |
| Meta ads form | 14 | 3 | 11 | 2 | 0.0061 | 280.00 | 25.46 | 140.00 |
| Website form, organic | 11 | 1 | 10 | 4 | 0.0055 | 0.00 | 0.00 | 0.00 |
| Shared inbox | 7 | 0 | 7 | 3 | 0.0039 | 0.00 | 0.00 | 0.00 |
| All sources | 50 | 6 | 44 | 15 | 0.0242 | 700.00 | 15.91 | 46.67 |
Cost per lead is the AI cost plus the spend entered for that source, divided by valid leads. Cost per booked job divides the same total by the jobs booked. Spam is counted in enquiries but not in valid leads. Sources with no spend show 0.00 because the AI cost alone is far under one cent per lead. The figures show the arithmetic only and are not a client result.
| Check | Method | PASS when |
|---|---|---|
| Monthly AI cost | Add up the AI cost column and compare it with the provider’s usage page for the same month | The two agree within 2% |
| Price sheet | Compare the price sheet with the provider’s published price list each quarter | Every rate matches, or the sheet is updated and the change is logged |
Testing and checks
Every check has a written pass condition and fail condition before it is run. A FAIL stops go-live until it is cleared and the check is run again.
| ID | Check | Method | PASS when | FAIL when |
|---|---|---|---|---|
| T1 | Reading accuracy | Run a labelled set of past enquiries that your staff have marked for service and urgency | Service agrees on at least 90% and every emergency is flagged | Below 90%, or any emergency missed |
| T2 | Duplicate submission | Submit the same form twice within minutes | One queue item | Two queue items |
| T3 | Two requests in one email | Send an email that asks for two jobs | Two lines in the queue and one reply | Only one request captured |
| T4 | Other language | Send an enquiry in another language | Original and summary shown, reply left to a person | A reply drafted without the original shown |
| T5 | No contact details | Send an enquiry with no way to reply | Marked as no way to reply, no contact created | A contact is created |
| T6 | Price and date guard | Send enquiries that ask for a price and a date | No draft contains a price, a discount or a date | Any draft states one |
| T7 | Masking | Inspect the request sent to the model | No masked field appears in it | A name, phone or email appears |
| T8 | Existing contact | Write from a new address as a known customer | The existing record is shown, no second contact | A second contact is created |
| T9 | Emergency | Send an enquiry with an emergency word | Urgent flag and an alert to the on-call person | No alert |
| T10 | No action before approval | Review the workflow and permissions | No node creates a contact or sends a message before approval | Any route that does |
| T11 | Weekly view | Recompute one week by hand from the log | Every figure equals the view | Any difference |
| T12 | Model unavailable | Block the model connection | Enquiry queued unread with a template reply and an alert | Enquiry lost or no alert |
| T13 | AI cost reconciliation | Compare a month of logged cost with the provider’s usage page | Within 2% | More than 2% apart |
Scope and milestones
A fixed scope agreed in writing before anything starts. Each milestone is paid when you sign off its deliverable.
| Area | Included |
|---|---|
| Systems Audit | Review of how enquiries arrive and who handles them, your CRM contact setup and your service and area lists, a 45-minute call, written findings and a fixed quote |
| Intake | One web form and one shared inbox into one workflow in n8n or Make |
| Reading and drafting | The fields in the mapping above, draft replies, and prompts stored with a version |
| Rules | Existing-contact check in HubSpot or GoHighLevel, spam pre-check, service area and urgency words |
| Approval queue | Queue with edit, approve, decline and spam actions, and urgent alerts |
| Cost-per-lead log | Log in Airtable or Google Sheets, a price sheet, a Spend tab and the weekly view of cost per lead and per booked job by source |
| Safety | Masking where you ask for it, a stored audit trail and a manual fallback |
| Testing | Thirteen checks, run to a pass before go-live |
| Handover | Written SOPs, a recorded handover video and files you own, plus 14 days of fixes after go-live |
| Not included | Tax filing and statutory returns. |
| Also outside the scope | A chat widget build, a second CRM or more intake sources, which are quoted separately. Replying without approval. Model API usage fees, billed to you by the provider. Ad account management and the ad spend itself. |
| Milestone | Deliverable | Timing | Share |
|---|---|---|---|
| M1 Rules and fields | Field list, service list, area list and urgency words signed, and the labelled set agreed | Week 1 | 25% |
| M2 Intake and reading | Intake, masking and the model step, T1 to T7 pass | Weeks 2 to 3 | 30% |
| M3 Queue and log | Approval queue, CRM write after approval, the cost log and the weekly view, T8 to T11 pass | Week 4 | 30% |
| M4 Handover | Two weeks of supervised use, T12 and T13 pass, SOPs, handover video, 14 days of fixes | Weeks 5 to 6 | 15% |
Typical scope for this kind of project: US$1,600–2,900
About 6 weeks across 4 fixed milestones. The Systems Audit (US$300, fixed) comes first and confirms the scope.
Describe how enquiries reach you today, and I will say where I would start.
Send a short note through the form on the home page. I will reply with where I would start, and whether the US$300 Systems Audit is the right first step.