Outreach Stage 1
Stage 1 is the first-touch SMS from RERI to a wholesaler or contract holder (CH) for a newly-ingested deal. It is the entry point of the acquisitions conversation — all subsequent follow-up (Stages 2-4) depends on this send. Stage 1 is OpenPhone-only (not SalesMsg). Every send passes all 5 compliance gates defined in compliance-gates before any message leaves. Read this hub after reading compliance-gates. Owner: acquisitions agent.
Critical rules — do not skip:
- NEVER bypass the compliance gate (all 5 gates required on every first-touch send)
- NEVER run without —dry-run during audit (use
--dry-runto validate without sending)- NEVER send without explicit Henry auth (per feedback_never_send_without_auth)
- Stage 1 only — this skill sends first-touch only. Follow-ups (Stage 2+) go to followup-stages-2-3-4
Quick reference
| Field | Value |
|---|---|
| Stages | Deal ingest → Approval gate → 5-gate compliance → Template select → Mentor voice compose → OpenPhone send → Quo note |
| Primary agent | _summary |
| Supporting agents | _summary, _summary |
| Agent handoff chain | deal-ingestion → checkApprovalGate → unified-outreach-engine → gate-computer → compliance-gate → blast-safety → thread-context → response-generator → openphone-sms → quo-note-builder → outreach-stage1 audit → [if reply received] followup-stages-2-3-4 |
| Compliance gates list | gate-computer, compliance-gate, blast-safety, thread-context, response-generator |
| Skills invoked | acquisitions-outreach, messaging-compliance-gate |
| Success metrics | openphone_events row with event_type='outbound_sms'; Quo internal note posted; deal qualification_status transitions logged |
| Cost per stage | ~0.0075/segment) |
| Throughput | ~50-200 deals/day evaluated; ~20-80 Stage 1 sends/day (after gate filtering) |
| Last run result | See openphone_events most recent event_type='outbound_sms' row |
| Failure modes | Gate trips → no send; approval gate red-zone → CLI-only; lineId missing → no note (fail-closed); OpenPhone 429 → rotate line |
Architecture
acquisition_deals row (newly ingested, qualification_status='pending')
│
▼
[checkApprovalGate(deal)] — B7 three-zone gate
│
├─ 🟢 Green: reri_arv_flag=null or 'ok' → auto-approve
├─ 🟡 Yellow: reri_arv_flag='pre_negotiation' → 4h hold
└─ 🔴 Red: reri_arv_flag='manual_review_required' → CLI only
│ approved
▼
[unified-outreach-engine.js] — coordinator
│
├─→ [gate-computer.js] — select gate 1-5 + template scenario
├─→ [compliance-gate.js] — quiet hours, TCPA, 24h dedup
├─→ [blast-safety.js] — cross-deal dedup, suppression, line saturation
├─→ [thread-context.js] — prior message history, lineId resolution
├─→ [mentor-voice.js] — touch count → mentor selection
└─→ [response-generator.js] — v3 Dispo Conversion Agent compose
│ all 5 gates pass
▼
[openphone-sms.js] — OpenPhone send (acq is OpenPhone-only)
│
▼
[quo-note-builder.js] — §4.1 canonical 7-line Quo internal note
│
▼
openphone_events (Supabase CCP audit trail)
│
▼
→ [[wiki/_hubs/processes/followup-stages-2-3-4]] (when CH replies OR 4h passes)
B7 Approval Gate (three zones)
Checked before every first-touch send via checkApprovalGate(deal):
| Zone | Condition | Behavior |
|---|---|---|
| 🟢 Green | reri_arv_flag is null or 'ok' | Auto-approve; engine picks up immediately |
| 🟡 Yellow | reri_arv_flag='pre_negotiation' | Hold 4h; deal-outreach-auto-approver.js (every 30 min) flips qualification_status='approved' after window |
| 🔴 Red | reri_arv_flag='manual_review_required' | CLI only: node deal-outreach-worker.js --deal-id=X --approve |
qualification_status='approved' overrides any flag. qualification_status='rejected' blocks permanently.
SMS template scenarios
Gate result maps to template scenario via resolveStage(deal, gateResult):
| Scenario | Template file | Trigger |
|---|---|---|
initial-outreach | deal-qualification/templates/sms/initial-outreach.json | Gate 1, no pre-negotiation flag |
detail-request | deal-qualification/templates/sms/detail-request.json | Gate 2-3 |
gap-fill | deal-qualification/templates/sms/gap-fill.json | Gate 4 |
pre-negotiation | deal-qualification/templates/sms/pre-negotiation.json | reri_pre_negotiation_triggered=true (tight spread) |
offer-inquiry | deal-qualification/templates/sms/offer-inquiry.json | Gate 5 / qualifying deal |
reri_pre_negotiation_triggered=true always routes to pre-negotiation regardless of gate.
Mentor voice cadence
feedback_acq_mentor_voice_cadence — touch count determines which mentor’s voice is applied:
| Touch | Mentor | Voice style |
|---|---|---|
| T1-2 | Mike Ferry | Direct, confident, one question, no filler |
| T3-6 | Mandeep Damji | Relational, warm, references their situation |
| T7-13 | David Norton | Certain, anchors commitment, no hedging |
| T14-20 | Grant Cardone | Urgency, scarcity framing, action-oriented |
| T21+ | Sean Terry | Objection-counter, floor-probing |
One question per send (Mike Ferry rule). feedback_acq_no_pass_and_pivot — never use pass+pivot. feedback_acq_thread_history_aware_gates — skip gates already satisfied by thread history.
Quo internal note format (§4.1)
After every outbound send, quo-note-builder.js posts a 7-line emoji note to the Quo conversation. Fail-closed: if lineId cannot be resolved from fromNumber, no note is posted. No hardcoded fallbacks.
📍 City / State / Zip
📈 Stage: <label>
🔗 IL URL
📁 HubSpot link
👤 N total deals from this CH on file
🗺️ STATE · STATE
⏳ Only deal on file from this CH (or +N more...)
Entry points (CLI)
Bulk worker
node /home/opsadmin/.openclaw/workspace/scripts/workers/unified-outreach-engine.js \
[--state=FL] # filter to deals in this state
[--limit=N] # max deals per run
[--dry-run] # gate + compose, NO send — ALWAYS run dry-run during audit
[--phase=new|followup|all] # filter by action typeSingle-deal trigger
node /home/opsadmin/.openclaw/workspace/scripts/workers/deal-outreach-worker.js \
--deal-id=<acquisition_deals.id> \
[--approve] # flip qualification_status='approved' (red-zone CLI override)
[--dry-run]Yellow-zone auto-approver (background timer)
node /home/opsadmin/.openclaw/workspace/scripts/workers/deal-outreach-auto-approver.js \
[--dry-run]
[--hours=4] # review window (default 4)Runs automatically via deal-outreach-auto-approver.timer (every 30 min).
OpenPhone line routing
Stage 1 sends are OpenPhone-only. Line selection uses STATE_LINES map in unified-outreach-engine.js:
| State | Line |
|---|---|
| CA | CA line |
| NV | NV line |
| FL | FL line |
| GA | GA line |
| AZ | AZ line |
10DLC note: All OpenPhone lines are subject to A2P 10DLC carrier compliance. Until osil-twilio-10dlc-resubmission-2026-05-03 B14 resolves (campaign resubmission approved), carrier filtering may reduce deliverability. Monitor delivery rates in
openphone_events.
Components
workspace/scripts/workers/unified-outreach-engine.js— coordinator (canonical entry point)workspace/scripts/workers/deal-outreach-worker.js— single-deal triggerworkspace/scripts/workers/deal-outreach-auto-approver.js— yellow-zone 4h timerworkspace/scripts/workers/smart-outreach-worker.js— batch legacy (superseded by engine)workspace/scripts/lib/gate-computer.js— 5-gate qualification progressionworkspace/scripts/lib/compliance-gate.js— TCPA / quiet hours (see compliance-gates)workspace/scripts/lib/blast-safety.js— dedup + suppression (see compliance-gates)workspace/scripts/lib/thread-context.js— prior message history (see compliance-gates)workspace/scripts/lib/response-generator.js— v3 Dispo Conversion Agentworkspace/scripts/lib/mentor-voice.js— touch→mentor cadenceworkspace/scripts/lib/quo-note-builder.js— §4.1 Quo internal noteworkspace/scripts/lib/openphone-sms.js— OpenPhone send wrapperdeal-qualification/templates/sms/— 5 SMS template filesworkspace/knowledge-base/openphone/OUTREACH-RULES.md— 10 compliance rulesworkspace/knowledge-base/openphone/MENTORS.md— mentor profiles + anti-patterns
How it’s used
- Trigger: new deal created (via deal-ingestion) AND
qualification_statustransitions toapprovedorauto-approved; OR Henry instructs “send initial outreach for deal X” - Workflow: approval gate → 5-gate compliance check → template select → mentor compose → OpenPhone send → Quo note → audit log
- Agents involved: _summary (orchestrator), _summary (monitoring + Quo note via gateway)
- Handoff: after Stage 1 send, deal waits for reply; if no reply in 4h → followup-stages-2-3-4 picks up
NO_REPLY_4Htrigger - Success criteria:
openphone_eventsrow withevent_type='outbound_sms';acquisition_deals.last_outreach_atupdated; Quo conversation has 7-line note
Cross-links
Agents that touch this
- _summary — primary orchestrator; runs engine, evaluates approval gate
- _summary — monitoring; posts Quo internal notes via gateway
- _summary — deal field audit before approval gate
- _summary — Solara variant uses separate follow-up-scheduler (not Stage 1)
Skills that invoke this
- acquisitions-outreach — canonical wrapper for this entire stage
- messaging-compliance-gate — standalone compliance check (single-send validation)
Plans that govern this
- osil-twilio-10dlc-resubmission-2026-05-03 — B14: 10DLC blocks carrier delivery; 5 additional gates pending B14a
- openclaw-fragmentation-fix-2026-05-01 — G-BLOCKER-SURFACING; service restart gate
Feedback rules
- feedback_acq_no_pass_and_pivot — banned pass+pivot in response-generator compose
- feedback_acq_thread_history_aware_gates — skip gates already satisfied by thread history
- feedback_acq_mentor_voice_cadence — touch count → mentor voice selection
- feedback_quo_lineid_required — fail-closed on missing lineId; no hardcoded fallback
- feedback_never_send_without_auth — explicit Henry auth required for any live batch send
- feedback_aurora_outbound_guardrails — outbound send rules per Aurora dispatch
- feedback_action_gate_violation_repeated — service restarts require explicit auth, not assumed
- feedback_no_em_dash — no em-dashes in outbound SMS copy
KB / source docs
System maps
- vm-messaging-flow — SMS routing overview
- vm-acq-agent-flow — acquisitions dispatch flow
Related: SMS/Carrier compliance cluster
| Hub | Role |
|---|---|
| compliance-gates | Prerequisite — all 5 gates defined here; outreach-stage1 depends on this |
| followup-stages-2-3-4 | Downstream — picks up after Stage 1 send (4h no-reply or inbound reply) |
| openphone-quo | OpenPhone send channel + inbound webhook (:18792) |
| twilio | Carrier compliance, 10DLC B14 blocker |
| salesmsg | SalesMsg handles follow-up SMS (Stage 2+ via handler :18793) |
| deal-ingestion | Upstream — deal must exist before Stage 1 can fire |
Open issues / TODOs
- B14: 10DLC campaign resubmission pending — carrier deliverability impacted until resolved. Monitor OpenPhone delivery rates.
- Yellow-zone auto-approver (
deal-outreach-auto-approver.timer) — verify timer is running:systemctl --user status deal-outreach-auto-approver.timer smart-outreach-worker.jsis legacy (superseded byunified-outreach-engine.js) — retirement pending Phase cleanup- Mentor voice touch counter (
acquisition_deals.touch_count) vs actualopenphone_eventssend count — verify parity monthly
Recent activity
- 2026-05-03: hub created (W1-S8)