AI Voice, SMS, and Worker Dispatch System for Service Businesses
This brief proposes an AI voice and SMS dispatch system for a one-person field-service operation moving to a remote model: local sub-contractors perform on-site work while the owner manages bookings from another time zone. The architecture would combine Vapi.ai for inbound voice, Twilio for SMS, Make.com as the orchestration layer, OpenAI for unstructured text interpretation, and a job-management CRM such as ServiceM8 or Tradify — automating the path from first phone call through property-access negotiation to sub-contractor confirmation.
Proposed outcome: A hands-free dispatch pipeline where callers receive a booking link mid-call, paid web forms create provisional job cards, Make.com texts real-estate agents for access, and sub-contractors accept jobs via Y/N SMS — with WhatsApp escalation only when automation cannot resolve the thread.
Scenario
This is a proposed solution for a recurring pattern: a solo operator in the trades or inspection space who must scale without being on the phone all day.
- Business model: One-person service business (e.g. building inspections, pest control, handyman) based in Sydney, Australia, transitioning to remote management from overseas
- Workforce: Preferred and backup sub-contractors mapped by postcode; owner dispatches work but does not attend sites
- Customer entry: Inbound phone calls for quotes/bookings; website form with payment for confirmed jobs
- Access coordination: Real-estate agents control property access; SMS negotiation for lockbox codes and time slots
- CRM: ServiceM8, Tradify, or equivalent field-service software (Google Sheets acceptable as a staging layer during migration)
- Escalation channel: Owner WhatsApp for ambiguous agent replies, declined sub-contractors, or SLA breaches
Problem
When the owner moves time zones, the manual loop — answer phone, text agent, call subbie, update CRM — becomes a single point of failure. Missed calls mean lost revenue; delayed access texts stall the whole day.
- Always-on phone burden — customers expect immediate answers; voicemail kills conversion for time-sensitive inspections
- Fragmented booking path — caller details live in call notes, form data in email, and job status in CRM; nothing links automatically
- Agent SMS ambiguity — replies like “should be fine, code 4821” or “how about Friday?” need human judgment unless structured parsing exists
- Sub-contractor chase — texting one subbie, waiting, then manually trying the backup burns hours the owner no longer has in-market
- CRM hygiene — addresses pasted from forms arrive malformed; provisional vs dispatched job states drift without enforced state machine
- Compliance & trust — Australian Privacy Act applies to customer phone numbers; SMS must identify the business; recorded voice calls need clear disclosure where required
Requirements
Functional
- Workflow 1 — Inbound voice + booking SMS: Vapi assistant on Twilio number answers with owner script; mid-call
send_smstool fires booking link to caller’s mobile - Workflow 2 — Form → provisional job: Website payment webhook triggers Make.com; OpenAI normalizes address; CRM job card created in Provisional status
- Workflow 3A — Agent access request: On new booking, Twilio SMS to listing agent requesting access at proposed date/time
- Workflow 3B — Agent reply parsing: Inbound agent SMS → OpenAI structured JSON (yes / no / alternate_time / lockbox_code / unclear); router updates calendar or escalates
- Workflow 3C — Sub-contractor dispatch: Postcode lookup → text preferred subbie with job details; Y accepts, N or 30-min timeout → backup subbie; all-decline → WhatsApp alert
- State machine: Job statuses:
provisional→access_pending→access_confirmed→dispatch_pending→dispatched→escalated - Owner override: WhatsApp commands or CRM manual flag to pause automation on a job
Non-functional
- Latency: Booking SMS during call < 5 s; agent outbound within 60 s of form submit
- Idempotency: Duplicate webhooks must not create twin job cards or double-text agents
- Observability: Make.com execution history + central log sheet or Airtable for SMS thread audit
- Timezone: All scheduled times stored in Australia/Sydney; displayed correctly in CRM and SMS copy
- Secrets: API keys in Make connections vault; no credentials in scenario JSON exports shared to client
- Testability: Staging Twilio numbers and mock agent/subbie contacts for end-to-end rehearsal before go-live
Architecture
Three Make.com scenarios (voice-adjacent webhook, booking intake, SMS conversation hub) sit between customer touchpoints and the CRM. Vapi owns real-time voice; Twilio owns SMS transport; OpenAI modules classify agent and subbie replies.
System architecture — Vapi handles voice and mid-call SMS; Make.com orchestrates booking intake, agent negotiation, and sub-contractor dispatch with CRM as system of record
Agent reply sequence — OpenAI classifies unstructured SMS; confirmed access triggers sub-contractor loop; ambiguous threads escalate to owner
Component map by integration layer (major services per tier)
End-to-end flow
Happy-path pipeline — escalation branches (agent confusion, subbie decline) route to owner without blocking other jobs
Automation coverage by workflow stage (% of steps handled without owner intervention on happy path)
Indicative job distribution across CRM states during steady-state operations
Recommended stack
Recommendation: Keep the client’s stated stack — Make.com for routers and delays, Vapi.ai for voice, Twilio for SMS, OpenAI GPT-4o inside Make for JSON extraction — paired with ServiceM8 (strong AU tradie adoption) or Tradify if already licensed. A Google Sheet or Airtable sms_threads table would act as a lightweight conversation index when the CRM API lacks native SMS logging.
| Layer | Technology | Why |
|---|---|---|
| Voice AI | Vapi.ai + Twilio number | Native function-calling for mid-call SMS; lower latency than bolting STT/LLM/TTS yourself |
| SMS transport | Twilio Messaging | Separate inbound webhooks per number; delivery receipts for Make error branches |
| Orchestration | Make.com (3 scenarios) | Visual routers, sleep modules for 30-min subbie timeout, OpenAI module with JSON schema output |
| LLM parsing | OpenAI GPT-4o via Make | Structured outputs for agent intent; temperature 0 for classification tasks |
| Job CRM | ServiceM8 API (or Tradify) | Native job statuses, staff assignment, AU address fields; webhook on job create optional |
| Booking form | Existing site form + Stripe | Webhook to Make on successful payment — avoids building custom checkout |
| Subbie roster | Google Sheet or Airtable | Postcode → primary/backup mapping editable without redeploying scenarios |
| Owner alerts | WhatsApp Business Cloud API or Twilio WhatsApp | High-priority template messages when automation stops |
| Audit log | Google Sheet dispatch_log | Every SMS in/out with job_id, timestamp, parsed intent — cheap ops visibility |
Why Make.com over custom code? The owner needs maintainable scenarios they can inspect; Make’s router modules map directly to the YES / alternate / NO branches. Custom Node would be cheaper at scale but harder to hand over.
Why Vapi over Twilio Studio + OpenAI? Studio struggles with natural multi-turn dialog and tool calls during live audio. Vapi’s send_sms server tool fires while the caller is still on the line — the exact UX the workflow demands.
ServiceM8 vs Tradify vs Sheets? ServiceM8’s REST API and job-status model fit provisional → scheduled → dispatched. Sheets work for MVP roster lookup but should not be the long-term job system of record.
Agent & component design
1 — Vapi inbound voice assistant
- Input: PSTN call via Twilio-imported number; caller ID for SMS destination
- Persona: Owner-provided script — services offered, pricing FAQs, booking CTA
- Tool:
send_booking_link→ Vapi server URL or Twilio Messages API with{{customer.number}}and static booking URL - Output: Call transcript webhook to Make (optional logging); SMS delivery confirmation
- QA gate: Test calls with 3 script variations; verify SMS arrives before call ends; failover message if SMS fails
2 — Make scenario: booking-intake
- Trigger: Website form webhook (payment success payload)
- Steps: Dedupe by
payment_intent_id→ OpenAI address normalizer → ServiceM8Create Job(status: Provisional) → write row todispatch_log→ HTTP call to wakeaccess-dispatchscenario - OpenAI prompt: Return JSON
{ street, suburb, state, postcode, formatted }; reject if confidence low → WhatsApp owner - QA gate: 10 sample addresses including unit numbers and rural routes before prod
3 — Make scenario: access-dispatch (router hub)
| Branch | Trigger | Actions |
|---|---|---|
| 3A — Outbound access | New job event | Lookup agent mobile from job custom field → Twilio SMS template → set CRM access_pending |
| 3B — Agent inbound | Twilio inbound SMS webhook | Match thread_id by agent number + open job → GPT parse → router |
| 3B — YES / lockbox | intent=confirmed | Store code in CRM note → branch 3C |
| 3B — Alternate time | intent=reschedule | Update job schedule → confirmation SMS to agent |
| 3B — Escalate | intent=unclear|declined | CRM escalated → WhatsApp owner with thread link |
| 3C — Subbie offer | Access confirmed | Sheet lookup by postcode → SMS primary → sleep 30 min → router on reply |
| 3C — Accept | Reply matches Y | Assign staff in CRM → status dispatched → confirmation SMS |
| 3C — Decline / timeout | N or no reply | Try backup subbie; if exhausted → WhatsApp owner |
4 — OpenAI reply classifier (shared module)
- Input: Raw SMS body + job context (address, proposed slot, prior messages)
- Output schema:
{ intent, lockbox_code, proposed_datetime, confidence, summary } - Router thresholds: Auto-act if
confidence ≥ 0.85; else escalate - QA gate: Golden-set of 20 agent reply fixtures in Make test runs
5 — Sub-contractor roster service
- Source: Google Sheet columns:
postcode_prefix,primary_name,primary_mobile,backup_name,backup_mobile - Lookup: Make
Search Rowswith filter; fallback to owner alert if postcode unmapped
Typical dispatch lifecycle — median vs p95 duration by stage (illustrative, happy path)
Implementation plan
Phase 1 — Discovery & account wiring (week 1)
Confirm CRM choice (ServiceM8 vs Tradify), export API credentials, inventory website form webhook shape, and document subbie postcode roster. Provision Twilio AU number, Vapi assistant shell, Make organization, and staging contacts for mock agent/subbie. Define job status enum aligned to CRM native values.
Risk: CRM API limits on trial tier — upgrade before integration tests. Rollback: manual job creation remains available; automations disabled via Make scenario toggle.
Phase 2 — Workflow 1: Vapi voice + mid-call SMS (week 2)
Import Twilio number to Vapi; load owner script; configure send_booking_link server tool hitting Twilio Messages API. Record 5 test calls; tune interruption sensitivity and SMS timing. Optional: post-call webhook to dispatch_log.
Risk: Caller ID ≠ mobile (landline) — script branch asks for mobile to text. Rollback: forward number to owner mobile while Vapi is adjusted.
Phase 3 — Workflow 2: Form → provisional job (week 2–3)
Build booking-intake scenario: payment webhook, idempotency key store, OpenAI address module, ServiceM8 job create. Validate 20 historical addresses. Connect form staging URL for UAT.
Risk: Malformed webhook payloads from form plugin — add Make Data Store schema validation. Rollback: email notification to owner with raw payload for manual entry.
Phase 4 — Workflow 3A–3B: Agent SMS loop (week 3–4)
Outbound access template; inbound Twilio webhook to access-dispatch; GPT classifier with JSON schema; routers for confirm / reschedule / escalate. Thread matching via job custom field storing agent mobile. Live test with mock agent phone.
Risk: Agent replies to wrong thread if they manage multiple listings — include address in every outbound SMS. Rollback: pause outbound; owner texts agents manually from CRM.
Phase 5 — Workflow 3C: Sub-contractor dispatch (week 4–5)
Postcode roster sheet; primary/backup SMS offer; 30-minute sleep + timeout router; CRM staff assignment on accept. WhatsApp alert template for all-decline. End-to-end rehearsal: call → form → agent YES → subbie Y.
Risk: Subbie replies “Yes” vs “Y” — normalize with GPT or regex OR-list. Rollback: disable auto-dispatch; owner assigns staff in CRM.
Phase 6 — Hardening, docs & handover (week 5–6)
Error-handler sub-scenarios on every Twilio/OpenAI/CRM module; runbook for scenario toggles; Loom walkthrough of mock E2E test; credential rotation notes. Monitor first two weeks of prod with daily execution review.
Risk: Make operation quota during burst bookings — upgrade plan or add queue delay. Rollback: scenario snapshots exported to JSON; one-click restore.
Reporting & ops
| Signal | Source | Cadence |
|---|---|---|
| Vapi call volume + SMS tool success | Vapi dashboard + Twilio delivery logs | Daily email digest first 14 days |
| Make scenario failures | Make execution history + error handler route | Immediate WhatsApp on CRM write failure |
| Agent response time | dispatch_log timestamps | Weekly — alert if median > 4 h |
| Subbie accept rate | CRM dispatched vs offers sent | Weekly per postcode region |
| Escalation rate | Jobs in escalated status | Weekly — tune GPT prompts if > 15% |
| OpenAI parse confidence | Logged confidence field | Monthly review of low-confidence samples |
| Booking funnel | Calls → SMS sent → form paid → dispatched | Monthly conversion chart in Sheet |
Ops cadence would include a 15-minute daily check (failed Make runs, escalated jobs) while the owner is in a distant time zone, then a weekly 30-minute tuning session for Vapi script and SMS templates. Twilio balance and Make operation usage alerts prevent silent outages.
Proposed deliverables
Following the phased plan, a build would ship these artifacts:
- Configured Vapi assistant on production Twilio number with
send_booking_linktool and owner script - Three production Make.com scenarios (
booking-intake,access-dispatch, shared error handler) with staging clones - OpenAI classifier prompt + JSON schema documented in runbook
- ServiceM8 (or Tradify) job template with custom fields: agent mobile, lockbox code, automation status, thread ID
- Sub-contractor postcode roster Google Sheet with primary/backup columns
dispatch_logaudit sheet — every SMS and state transition- WhatsApp escalation templates wired to owner number
- Recorded end-to-end test: live call → form submit → mock agent YES → mock subbie Y → CRM dispatched
- Operator runbook: scenario toggles, credential locations, common failure fixes
Effort estimate
Indicative effort for the three workflows through E2E test and handover (assumes CRM API access, existing website form, and owner available for UAT calls):
| Scope | Hours (range) |
|---|---|
| Phases 1–6 (Vapi + 3 Make workflows + E2E test) | 70–110 hrs |
| CRM migration (if starting from Sheets only) | +12–20 hrs |
| Ongoing tuning (scripts, postcode roster, GPT fixtures) | 2–4 hrs/month |
| Platform costs (indicative monthly) | Make Pro, Vapi usage, Twilio SMS, OpenAI — typically AUD 150–350 at low volume |
The hour range reflects ServiceM8 vs Tradify API familiarity, whether the website form already emits clean webhooks, and how many edge cases appear in real agent SMS threads during UAT. A fixed-price engagement would scope exactly three workflows with one CRM integration and two subbie tiers per postcode.
Glossary
| Term | Meaning |
|---|---|
| Vapi | Voice AI platform that connects telephony to LLM assistants with server-side tool calling |
| Make.com scenario | Visual automation workflow — equivalent to a Zap with routers, filters, and sleep modules |
| Provisional job | CRM job card created on payment but not yet confirmed for dispatch — access and subbie steps still pending |
| Router module | Make.com branching node that sends execution down exactly one path based on filters |
| Structured output | LLM response constrained to a JSON schema — used here for agent intent classification |
| Thread ID | Correlation key linking inbound SMS to an open job — typically agent mobile + job UUID |
| Idempotency key | Unique payment or webhook ID preventing duplicate job creation on retry |
| ServiceM8 | Australian field-service job management platform with REST API for jobs, staff, and scheduling |
| Sleep module | Make.com delay step — used for 30-minute sub-contractor response timeout |