# Spec: Leah/Sam Escalation Tool (`create_escalation`)

## Overview
Build a `create_escalation` handler in Twilio Functions that Leah and Sam call when they need human follow-up. Routes to different Slack channels based on type. All escalations get immediate acknowledgment to the customer.

## Context
- Leah = CS first-contact AI agent (Vapi, voice + SMS)
- Sam = Sales/bookings AI agent (Vapi, voice)
- Both run on Twilio Functions backend: service `ZS46e8a58afad9a49742ddbbe2e3d60bbe`
- Existing functions in: `~/nmc-phone/nmc-ivr/functions/`
- Current vapi-tools.js handles: `lookup_customer`, `get_price_estimate`, `get_booking_details`, `get_upcoming_booking`

---

## Routing Rules

### CS Escalations → Slack #customer-service (C0869E90MCJ)
Regular customer service items that need human follow-up:
- "Where are my cleaners?" (ETA request) — see Contractor DM section below
- Credit card update (send Launch27 portal link first: https://nomorechores.launch27.com/login)
- Rescheduling request (until Playwright automation exists)
- Invoice request
- General account questions Leah can't resolve
- Cancellation processing (until automated)
- Pre-auth charge confusion (after explaining, if customer still wants human)
- Tip addition request

### Complaint Escalations → Slack #issues (C0APWDMBD7S)
Actual complaints and issues. Must follow existing complaint SOP (`sops/complaint-handling-sop.md`):

| Code | Category | Urgency | Notify Mike? |
|------|----------|---------|-------------|
| QC | Quality (missed areas, poor clean) | HIGH | YES |
| DMG | Damage (broken items, stains) | CRITICAL | YES — immediately |
| BEH | Contractor behavior (rudeness, theft) | CRITICAL | YES — immediately |
| NS | No-show / late | HIGH | YES |
| BIL | Billing dispute | HIGH | YES — potential cost |
| SAF | Safety incident | CRITICAL | YES — immediately |

**Mike is informed of ALL complaints.** Any situation that could cost the company money goes to Mike directly. Abigael handles execution once Mike has visibility.

**General feedback (GEN)** does NOT go to #issues. Route to a separate channel (TBD — could be #customer-feedback in Slack, C0AJQTVST1B). Tag by feedback type: positive, suggestion, minor-gripe.

**Complaint posts must include:**
- Auto-assigned complaint ID: `[CODE]-[YEAR]-[###]` (e.g., QC-2026-003)
- Color-coded Slack attachment (red: DMG/SAF/BEH, yellow: QC/NS/BIL, blue: GEN)
- Source, customer name, phone, complaint summary, classification, urgency, recommended next steps

**Sequence tracking:** Use Twilio Sync map `complaint-ids` with key per category for the running count.

### Sales Escalations → Slack #sales-team (C072QU0EMRC)
All sales escalations get immediate acknowledgment. Every lead gets auto-nurture regardless of tier.

| Tier | Trigger | Quote Response Target | Nurture |
|------|---------|----------------------|---------|
| HOT | Recurring, commercial, multi-unit, property manager, real estate agent, >$500/visit, high-margin add-ons | Same day | Aggressive (24h, 48h, 7d) |
| WARM | Interested but wants callback, Sam couldn't answer confidently | 4 hours | Standard (48h, 7d, 14d) |
| COOL | Got quote but didn't commit, no urgency signals | 24 hours | Standard (48h, 7d, 14d) |
| LOST | Explicitly said no, went with competitor | N/A | Win-back (30d, 60d, 90d) |

**All tiers:** Immediate acknowledgment + response. The quote response target is how fast we get them a detailed/custom quote if the standard pricing tool wasn't sufficient.

**Key sales escalation triggers (→ human needed):**
- Customer mentions multiple properties or commercial
- Customer asks for custom/enterprise pricing
- Customer says "I need to talk to the owner/manager"
- Sam fails to answer a question confidently
- Customer is a real estate agent or property manager
- Anything Sam can't close after standard pitch

Sam handles: standard residential quotes, one-time bookings, recurring sign-ups, basic objection handling, frequency/discount questions.

### Urgent Notifications → WhatsApp group (Mike + Abigael)
For CRITICAL complaints (SAF, BEH, DMG) and HOT sales leads:
- Post to WhatsApp group [TBD — Mike to create group and provide details]
- Fallback until WhatsApp is set up: SMS to Mike (+14162726683)

Also notify Mike for ALL complaints (QC, NS, BIL) since any could cost money. Method: Slack DM to Mike (U5XDTHEPQ) as secondary notification alongside the channel post.

---

## Contractor Channel Message for ETA Requests (Experimental)

When a customer asks "where are my cleaners?":
1. Leah checks booking details (existing tool) to identify which contractor/team
2. If booking is today, Leah posts to the contractor's dedicated Slack channel asking for ETA
3. Leah tells customer: "I've reached out to your team for an ETA. They'll contact you shortly."
4. Post to #customer-service as backup

**No DMs to contractors. Ever.** Each contractor has their own Slack channel. Use those.
**Start with one contractor channel for testing.** Need to identify which contractor + their channel ID.

---

## Function Signature

Add to existing `vapi-tools.js` as a new tool handler:

```javascript
// Tool name: create_escalation
// Parameters:
{
  "type": "cs" | "complaint" | "sales",
  "urgency": "critical" | "high" | "normal" | "hot" | "warm" | "cool" | "lost",
  "category": "QC" | "DMG" | "BEH" | "NS" | "BIL" | "SAF" | "GEN" | null,
  "customer_name": "string",
  "customer_phone": "string",
  "summary": "string",
  "source": "voice" | "sms" | "webchat",
  "attempted_resolution": "string" | null,
  "estimated_value": "string" | null  // For sales: "$6,000/month", "$350 one-time"
}
```

## Return Value
```javascript
{
  "success": true,
  "escalation_id": "QC-2026-003",  // or "CS-20260406-001" for non-complaints, "SALE-20260406-001" for sales
  "channel": "#issues",
  "message": "I've flagged this for our team. Someone will follow up with you right away."
  // message always says immediate follow-up — no "within 4 hours" language to customer
}
```

## Slack Message Formats

### CS escalation (#customer-service):
```
🔔 *Customer Service Escalation* — CS-20260406-001
*Customer:* Jane Smith (+14165551234)
*Source:* Voice call
*Request:* Where are my cleaners? Cleaning was scheduled for 2pm, it's now 2:45pm.
*Leah's action:* Confirmed booking exists, unable to provide ETA. Reached out to contractor. Offered to have team contact customer.
*Action needed:* Follow up with ETA or resolution
```

### Complaint escalation (#issues):
Color-coded Slack attachments:
```
🔴 *DMG-2026-002 — Property Damage*
*Customer:* John Doe (+14165559876)
*Source:* Voice call
*Summary:* Customer reports broken vase during cleaning on Apr 5. Estimates $200 replacement.
*Classification:* DMG — Property Damage
*Urgency:* CRITICAL — respond immediately
*Recommended:* Acknowledge, request photos, assess liability per SOP 3B
*⚠️ Mike has been notified*
```

### Sales escalation (#sales-team):
```
🔥 *HOT Sales Lead* — SALE-20260406-001
*Customer:* Sarah Manager (+14165558888)
*Source:* Voice call via Sam
*Details:* Property manager with 12 units in downtown Toronto. Wants recurring biweekly for all units.
*Estimated value:* $6,000+/month
*Sam's attempt:* Provided per-unit pricing. Customer wants bulk discount and in-person meeting.
*Action needed:* Call back immediately
*⚠️ Mike has been notified*
```

### Feedback (#customer-feedback C0AJQTVST1B):
```
💬 *Customer Feedback* — positive
*Customer:* Maria B (+14167833357)
*Source:* Voice call
*Feedback:* "Your team did an amazing job, the kitchen was spotless"
*Tags:* #positive #quality-praise
```

---

## Dependencies
- Slack token: `~/.openclaw/secrets/slack-token.txt` (Bot token, starts with xoxb-)
- Slack API: `chat.postMessage` for channel posts, `chat.postMessage` with user ID for DMs
- Twilio client (already in scope for SMS)
- Twilio Sync (already used by sms-chat.js — service SID in env vars)

## Slack Channel IDs
- #customer-service: C0869E90MCJ
- #issues: C0APWDMBD7S
- #sales-team: C072QU0EMRC
- #customer-feedback: C0AJQTVST1B
- Mike's Slack DM: U5XDTHEPQ (use conversations.open + chat.postMessage)

## File Locations
- **Build here:** `~/nmc-phone/nmc-ivr/functions/vapi-tools.js` (add create_escalation handler to existing file)
- SOP reference: `~/.openclaw/workspace/sops/complaint-handling-sop.md`
- Leah prompt (read-only reference): `~/.openclaw/workspace/leah/versions/system-prompt-v3.4.txt`
- Sam prompt (read-only reference): `~/.openclaw/workspace/leah/versions/system-prompt-sam-v1.1.txt`

## What NOT to do
- Do NOT deploy to Twilio (Harvey handles deployment)
- Do NOT modify Vapi assistant configs (Harvey handles API pushes)
- Do NOT modify system prompts (separate spec for v3.5.0)
- Do NOT create Slack channels (they already exist)
- Just write the code in vapi-tools.js and save it

## QA Channel
Use existing #leah-qa (Slack C0AR2TAVD42) for QA of both Leah and Sam. Harvey will handle QA testing after deployment.

## Open Questions (for Mike)
1. ~~Abigael's phone number~~ — Mike creating WhatsApp group with Abigael directly
2. Which contractor (and their Slack channel ID) to test the ETA channel message with?
3. ~~WhatsApp group~~ — Mike handling creation. Share group details when ready for integration.
