AGT-501 — Customer Health Monitor

Layer 5: Post-Sale Retention · Daily health scoring · 7 dimensions + ConvIntelligence adj + payment modifier · Canonical source for AGT-502 and AGT-503
L5 · Agent 01 Specced · v19 original + v25 ripple update L8 ripple: seat utilization dimension reads UsageMeteringLog explicitly
L8 ripple update (v25)
Update — seat utilization dimension source: UsageMeteringLog
The seat utilization dimension (18 pts max) previously referenced "AGT-804 usage data feed" without specifying the schema table. UsageMeteringLog now exists as the canonical usage data source (added in v25 with AGT-804).

AGT-501 seat utilization dimension reads:
 · UsageMeteringLog WHERE account_id = [account] AND sku_id LIKE 'SKU-SEAT%' AND period_end >= [trailing 30-day window]
 · Utilization rate = units_consumed ÷ commit_units for the most recent complete metering period
 · Score: >80% utilization = full points; 60–80% = partial; <60% = low utilization signal

Non-blocking dependency: if UsageMeteringLog has no records for this account (AGT-804 not live or seat SKU not metered), the seat utilization dimension is flagged as data_gap — same behavior as before. No change to scoring logic, only the explicit data source is now named.
Update — CSM call ConvIntelligence adjustment: call_owner_role filter
ConvIntelligence.call_owner_role field (added v23) enables AGT-501 to correctly filter CSM-owned calls for the ConvIntelligence adjustment (+12 pts max). AGT-501 reads ConvIntelligence WHERE account_id = [account] AND call_owner_role = 'CSM' AND call_date >= [trailing 30 days]. Selling-role calls (AE, SDR, SE) are excluded from this adjustment — they are not signals of customer health, only of deal activity.
Purpose

AGT-501 runs daily batch scoring for all active customer accounts. It writes CustomerHealthLog as the canonical daily record — AGT-502 (Churn Risk Detector) and AGT-503 (Expansion Trigger) read exclusively from this table. It is the single source of truth for account health across the post-sale stack.

Scoring model — 7 dimensions (100 pts base)
DimensionMax ptsSourceNotes
Product usage trend22UsageMeteringLog — consumption trend across trailing 3 periodsTrending up = full pts. Flat = partial. Declining = low pts.
Exec sponsor engagement20Contacts — economic_buyer and champion persona typesPersona-typed engagement from Contacts table (v18 L2 ripple pattern)
Seat utilization18UsageMeteringLog WHERE sku_id LIKE 'SKU-SEAT%'Most recent complete period. Data_gap if no records.
NPS / CSAT14NPS/CSAT survey system (external feed)No OnboardingLog proxy — data_gap during onboarding by design.
Engagement recency12ConvIntelligence, QBRLog, ABMEngagementLogDays since last meaningful touchpoint across all channels.
Support ticket trend8Support system feed (external)Volume + severity trend. Escalating tickets = lower score.
Competitive threat6ConvIntelligence.competitors_mentioned, CompetitiveKnowledgeBaseActive competitive evaluation signal.
During onboarding (Accounts.onboarding_status = 'active'): AGT-501 substitutes OnboardingLog signals for dimensions where live data doesn't exist. Seat utilization, exec sponsor engagement, usage trend, and engagement recency all have defined OnboardingLog substitutes. Records flagged in_onboarding = TRUE in CustomerHealthLog.
Adjustments and modifiers (applied after 7-dimension base)
AdjustmentValueSource
ConvIntelligence adjustmentUp to +12 ptsConvIntelligence WHERE call_owner_role = 'CSM' — trailing 30-day pattern of sentiment, talk ratio, next-step quality (v23)
Payment health modifierCap or floorCustomerHealthLog.payment_health_status from AGT-803: Current = no effect; Overdue = cap at 77; Failed = cap at 62; Suspended = floor at Critical. Applied last.
Key outputs — CustomerHealthLog fields
FieldNotes
raw_health_score7-dimension score + ConvIntelligence adjustment, before payment modifier
health_scorePost-modifier final score. This is what AGT-502 and AGT-503 read.
score_deltaChange from prior day. Used by AGT-502 for ≥15 pt drop alert.
payment_health_statusWritten by AGT-803. AGT-501 reads and applies modifier.
sponsor_departure_flagPasses to AGT-502 immediately on same run — does not wait for next AGT-502 cycle.
in_onboardingTRUE when Accounts.onboarding_status = 'active'. Signals OnboardingLog substitution mode.
data_gap_dimensionsJSON array of dimensions scored as data_gap this run.