Building an Attended SMS Confirmation Handler for Lead Automation: Architecture and Tool Integration
This post documents the design and implementation of a message monitoring system for GetMyBoat lead intake, with a focus on responsible automation patterns. The challenge: acknowledge warm leads immediately while preserving human oversight for confirmations that affect crew scheduling.
What Was Done
We built a two-layer confirmation system for a charter booking operation:
- Immediate layer: Automated acknowledgment (SMS) fires within seconds of inbound lead
- Human layer: Drafted confirmation sits in cache, waiting for one-tap send approval before SMS leaves the system
This pattern deliberately rejects unattended scheduled sending. Even for a single confirmation, automatic overnight SMS to crew members introduces latency in error detection and removes the human glance that catches typos in call times, dates, or role assignments.
Technical Details: Session Architecture
Message Monitoring & Data Access
The session involved reading macOS message archives to establish baseline state:
# Verified read access to SQLite chat database
# File: ~/Library/Messages/chat.db
# Query pattern: isolate inbound texts on JADA phone line (6199867344)
# Purpose: establish baseline of unanswered texts, prepare for new lead detection
Key decision: We're reading from the local Messages database rather than polling GetMyBoat's API directly. This gives us a unified view of all inbound communication (SMS, iMessage, third-party apps) in one source of truth. The tradeoff is that this only works in attended mode — the process runs when you're present, not on a background schedule.
Tool Verification & Capabilities
Before writing any automation, we verified the send-sms tool exists and is executable:
# Verify tool availability
which send-sms
file /path/to/send-sms
# Test capability (no actual send)
send-sms --help
The send-sms binary is the execution layer for outbound messages. It's called only after:
- Draft text is prepared and cached in memory
- Human operator confirms the text visually
- Operator taps approval (one-tap send)
Playwright Integration for Settings Automation
The session included planning for Playwright-based automation to route GetMyBoat notifications:
# Check Playwright availability
npm list playwright
# or
python -m pip show playwright
# Verify credentials for GMB login exist (labels only, values masked)
cat /path/to/creds.txt | grep -i "gmb\|getmyboat"
The goal: use Playwright to navigate GetMyBoat's notification settings and ensure incoming messages route to jadasailing@gmail.com. This is a one-time setup task, not part of the continuous confirmation loop.
Infrastructure & Data Flow
Data Sources Mapped
During exploration, we documented the scattered state of JADA's operational data:
- Local (macOS): Chat database, credentials file, proposal documents in iCloud Drive at
~/Library/Mobile Documents/com~apple~CloudDocs/jada-ops/ - EC2 (remote): Code repos, historical research docs, site configs at
~/repos - DynamoDB: Charter records, crew roster, revenue ledger (no direct access in this session)
- Lambda/Stripe: Magic-link subdomain pattern for crew confirmations, Stripe key storage
Why this matters: the monitor script will eventually need to query multiple sources. Rather than building a unified schema now, we're deliberately keeping this session attended-only, which means the human operator provides context that ties these pieces together.
Proposal Template Synthesis
We extracted pricing and structure from three recent proposals:
- Dylan proposal (baseline terms)
- Noelle proposal (pricing variant)
- Molly proposal (3-hour charter structure, $X pricing — extracted and cached)
- Giovanna proposal (Oct 10, written to
jada-ops/proposals/giovanna-oct10-proposal.txt)
New lead proposals will be drafted by synthesizing these templates, then presented to you for review before sending. No proposal goes to a lead without your visual approval.
Key Decisions & Rationale
Why Attended Mode, Not Scheduled Automation
The natural question: "Can't this just run overnight and send confirmation texts automatically?"
Answer: Technically yes, but we deliberately chose not to because:
- Reversibility: An SMS sent at 2 AM with a typo in the call time can't be unsent. Human eyes before send provides a safety gate.
- Context drift: If crew availability changes after a proposal is drafted but before the confirmation SMS goes out, an unattended send might confirm something that's no longer true.
- One-tap simplicity: "Attended mode" isn't slower for you — it's one tap tomorrow morning. The risk reduction justifies that micro-friction.
This is a deliberate architectural choice: **favor human oversight for outbound actions that affect real people's schedules.**
Quiet Hours Enforcement
The session established a quiet-hours rule: no SMS to crew between 17:00 and 08:00. This is enforced at the tool level, not as a suggestion. If you ask for an SMS outside these hours, the tool refuses (and the request waits in cache for the next valid window).
Message Routing via GMB Settings
Rather than polling GetMyBoat's API endpoint, we're configuring GetMyBoat itself to send notifications to a dedicated Gmail address. This is simpler and uses GetMyBoat's own infrastructure; we're not building a custom poller. Playwright handles the UI automation needed to change the setting one time.
What's Next
Three clear next steps, in order:
- Confirm Travis situation: Is there a crew confirmation needed tonight or tomorrow? If tomorrow, we'll cache the charter details now so morning-you has instant draft text ready.
- Set up the message monitor polling: Once you restart the session tomorrow and say "start the crew monitor," we'll set up a loop that watches the chat database and fires an ack SMS within seconds of new inbound lead.
- Playwright settings automation: One-time setup to route GetMyBoat notifications to the Gmail inbox that feeds the monitor.
Until the restart, nothing runs unattended. The send-sms tool is verified and ready. The proposal templates are cached. Tomorrow morning, one word from you starts the flow.