Automating GetMyBoat Inquiries: Building an Intelligent Inquiry-to-Booking Pipeline for JADA
What Was Done
We assessed the gaps in JADA's existing booking automation stack and designed a comprehensive inquiry handling system to bridge the manual work that Carole had been managing. The existing infrastructure—platform_inbox_scraper.py, CalendarSync.gs, and Google Calendar as the source of truth—handles confirmed bookings well. What was missing: a structured pipeline for the inquiry → response → provisional hold → payment → confirmation lifecycle.
Rather than implement everything at once, we've documented a phased automation approach that extends the current architecture without requiring a complete rewrite. The key insight: GetMyBoat inquiries are already landing in Gmail; we just need to parse them, extract structured data, and trigger downstream actions the same way confirmed bookings do.
Technical Details: The Inquiry Handler Pattern
Current Flow (What Exists):
- GetMyBoat confirmed booking → Gmail notification
platform_inbox_scraper.pydetects email, extracts booking ID, dates, customer- Data pushed to Google Calendar iCal feed
CalendarSync.gs(15-min poll) syncs to Calendar and triggers crew/cleaner SMS dispatch
Missing Flow (What We're Adding):
- GetMyBoat inquiry (not yet a booking) → Gmail notification
- No structured extraction or response trigger
- No provisional calendar hold while negotiating
- No auto-response or SLA tracking
Proposed Enhancement:
Extend platform_inbox_scraper.py with a new InquiryHandler class that:
- Detects inquiry patterns in email subject/body (e.g., "GetMyBoat Inquiry" vs. "Booking Confirmed")
- Extracts: customer name, requested dates, vessel preference, party size, special requests
- Creates a provisional calendar entry (marked as "Inquiry – Hold") with 2-hour TTL
- Stores inquiry metadata in a DynamoDB table (
jada-getmyboat-inquiries) as source of truth - Sends a templated auto-response via Gmail (with operator review before sending in MVP)
- Alerts operator via SMS if no response within 4 hours (configurable SLA)
Infrastructure: DynamoDB + Lambda + EventBridge
Rather than add complexity, we lean on AWS services already in the JADA stack:
DynamoDB Table: jada-getmyboat-inquiries
Partition Key: inquiry_id (GetMyBoat inquiry ID, e.g., "GMB-12345678")
Sort Key: created_timestamp (ISO 8601)
Attributes:
- customer_name (string)
- customer_email (string)
- requested_dates_start (ISO 8601)
- requested_dates_end (ISO 8601)
- vessel_preference (string, nullable)
- party_size (number)
- special_requests (string)
- inquiry_status (enum: "new", "responded", "provisionally_booked", "declined")
- response_timestamp (ISO 8601, nullable)
- calendar_event_id (Google Calendar event ID, nullable)
- calendar_hold_expires (ISO 8601)
- gmb_link (string, GetMyBoat direct message URL)
- operator_assigned (string, nullable)
Lambda Function: ProcessGetMyBoatInquiry
Triggered by SNS event (from platform_inbox_scraper.py` when it detects an inquiry email):
Runtime: Python 3.11
Environment variables:
DYNAMODB_TABLE=jada-getmyboat-inquiries
GOOGLE_CALENDAR_ID=jada-charter@googlegroups.com
SQS_QUEUE_URL=https://sqs.us-west-2.amazonaws.com/.../jada-responses
Handler: lambda_function.lambda_handler
Key steps:
1. Parse SNS payload (email metadata from scraper)
2. Call GetMyBoat API (or email regex) to extract inquiry fields
3. Insert record into DynamoDB
4. Create provisional Google Calendar event (title: "INQUIRY: {customer_name} – {dates}")
5. Store calendar_event_id in DynamoDB
6. Send SNS notification to operator (email + SMS)
7. Return success/failure
EventBridge Rule: InquiryResponseSLA
Scheduled rule that runs every 30 minutes:
Cron: rate(30 minutes)
Target: Lambda function ProcessInquirySLA
Logic:
- Query DynamoDB for inquiries with status="new" AND created_timestamp < now-4h
- For each stale inquiry, send operator SMS alert
- Update inquiry status to "sla_violated" for reporting
Key Decisions & Trade-offs
Why EventBridge instead of Step Functions?
Step Functions would add orchestration overhead for an event pattern that's naturally asynchronous. GetMyBoat inquiries arrive at unpredictable times; EventBridge's publish-subscribe model matches that better. Step Functions becomes useful if we add approval workflows (operator approves auto-response before sending); we can add that later without rearchitecting.
Why Google Calendar events for provisional holds?
Carole was already using Calendar as source of truth. By keeping provisional holds in Calendar (with a distinct event title prefix), we leverage existing visibility. The operator can see at a glance: confirmed bookings (green), inquiries (yellow), and conflicts.
Why a separate DynamoDB table instead of storing in Gmail labels?
Gmail labels are human-friendly but not queryable at scale. DynamoDB gives us: fast status lookups, SLA reporting, audit trails, and the ability to join inquiry data with booking data later (e.g., "which inquiries converted, and how long did it take?").
Why SMS alerts for SLA violations instead of email?
Email is async and easy to miss. Inquiries are time-sensitive (customer is comparing multiple charters). SMS is immediate and demands attention—critical for a 4-hour SLA on a charter business.
Phased Implementation Plan
Phase 1 (MVP): DynamoDB + Lambda inbox parser, manual operator response (no auto-response yet)
Phase 2: Templated auto-response (operator approves before sending)
Phase 3: Payment integration (GetMyBoat payment webhook → Stripe → confirm booking)
Phase 4: Automated provisional calendar holds with conflict detection
Monitoring & Observability
All Lambda invocations log to CloudWatch. Create a dashboard (JADA-InquiryMetrics) tracking:
- Inquiries received (daily, hourly)
- Response time (mean, p95, p99)
- Conversion rate (inquiries → confirmed bookings)