Una Claude Skill que corre cada mañana, jala cada cuenta que cruzó un umbral de churn-risk en las últimas 24 horas, y postea un digest de una página a un canal de Slack: nombre de la cuenta, ARR en riesgo, el evento que disparó el cambio, el owner, y una próxima acción específica. Reemplaza el digest ruidoso de email de Gainsight que la mayoría de los CSMs ya filtran a una carpeta, con algo lo suficientemente apretado como para leerse entre el standup y la primera llamada con cliente.
El bundle del artifact vive en apps/web/public/artifacts/churn-risk-summarizer-claude/ — SKILL.md más tres archivos de referencia (1-risk-signal-weights.md, 2-sample-digest.md, 3-escalation-criteria-thresholds.md) que la Skill carga en cada run.
Cuándo usarlo
Tienes Gainsight (o una plataforma de CS comparable) produciendo deltas de risk-score en los que confías a nivel dirección, pero el digest existente es demasiado largo para leerse o demasiado genérico para actuar. Tienes un equipo de CSMs que ya se reúne cada mañana y se beneficiaría de una lectura compartida de tres minutos sobre lo que cambió de un día para otro. Quieres que el razonamiento por cuenta de “qué cambió y qué hacer al respecto” sea uniforme entre CSMs en vez de que cada uno invente su propio encuadre.
La skill encaja cuando el run diario cae en 5-15 cuentas después de filtrar. Por debajo de 5, no necesitas una skill — lee la vista de Gainsight directamente. Arriba de 15, los umbrales en references/3-escalation-criteria-thresholds.md necesitan subirse antes de que valga la pena correr el digest siquiera.
Cuándo NO usarlo
No tienes risk scores en los que confíes. Garbage in, garbage out. Esta skill resume los scores que le des; no los computa ni los corrige. Si tu modelo de riesgo de Gainsight está roto, arréglalo primero.
Quieres un trigger automático de acción del CSM. La skill es señal read-only. Postear un digest a un canal está bien; auto-crear tareas, mandar emails de playbook, o abrir casos está fuera de alcance y te va a meter en problemas rápido (ver “alert fatigue” abajo).
Quieres copy de cara al cliente. Nada de lo que la skill produce está aprobado para mandar al cliente. Trata todo el output como interno.
Quieres análisis longitudinal de churn. El prompt está afinado para las últimas 24-168 horas. Para “qué pasó a través de Q3” usa BI sobre el warehouse de Gainsight.
Tu equipo de CSM es de dos personas. El costo de levantar esto supera el costo de que uno de ustedes lea la vista de Gainsight a las 7am. Vale la pena a partir de cuatro CSMs, donde la uniformidad del encuadre empieza a componerse.
Setup
Define el umbral. Decide qué significa concretamente “cruzó al churn risk”. Los defaults en references/3-escalation-criteria-thresholds.md usan signal_score >= 12 para Red y una caída de health_score de -15 para Amber. Edita esos números contra dos semanas de datos históricos antes de ir a producción.
Instala la Skill. Pega el bundle en ~/.claude/skills/churn-risk-summarizer/. Configura GAINSIGHT_TOKEN y SLACK_WEBHOOK_CHURN_DIGEST en tu env.
Configura el alcance. Edita references/3-escalation-criteria-thresholds.md con tu piso min_arr (la mayoría de los equipos usan $50k para un digest diario por canal) y tu lista segments (la mayoría de los equipos corre diario sobre enterprise + mid-market, semanal aparte sobre SMB).
Afina los pesos. Edita references/1-risk-signal-weights.md para que coincida con la opinión de tu equipo sobre qué importa. Los pesos enviados son defaults razonables, no son tus defaults.
Programa el run. 7am hora local en días laborales vía cron, n8n, o una tarea programada de Claude. Postea a tu canal de CS.
Itera sobre signal-to-noise. Las primeras dos semanas serán ruidosas. Afina un umbral a la vez y observa dos días de output antes de volver a editar. No edites pesos y umbrales en el mismo run — nunca vas a saber qué cambio movió la aguja.
Lo que la skill realmente hace
La Skill toma una lista JSON de cuentas más una lista JSON de eventos de timeline en la ventana (los esquemas están documentados en SKILL.md bajo “Inputs”). Corre cinco pasos secuenciales: agregación de señal (suma de severity * weight por cuenta, con un cap por evento de 5 para evitar que una sola escalación domine); bucketing basado en umbrales en Red, Amber y Watch; narrativa por cuenta anclada en los resúmenes reales del evento (sin parafrasear — “los seats activos cayeron de 142 a 89 en 7 días”, no “el engagement está bajando”); priorización por ARR descendente luego fecha de renovación ascendente; y renderizado al layout literal en references/2-sample-digest.md.
La decisión de ingeniería que vale la pena marcar: los pesos son explícitos y editables en vez de dejar que el modelo decida qué es importante por run. Cuando un líder de CSM no esté de acuerdo con lo que se surface, puede editar un número en references/1-risk-signal-weights.md y ver el efecto sobre el digest del día siguiente. Un juicio del modelo por run no se puede editar; solo se puede re-promptear, lo cual es más difícil de auditar.
El campo Action tiene una guardia dura: si la acción sugerida contiene engage, reach out, touch base, align, o socialize sin nombrar a una persona o artefacto específico, se reemplaza con needs human review. Mejor silencio que ruido.
Realidad de costos
Un digest diario sobre 150 cuentas enterprise + mid-market con eventos de la ventana corre aproximadamente 18-25k tokens de input (JSON de cuentas + JSON de eventos + los tres archivos de referencia) y 1-3k tokens de output. Al precio de lista de Claude Sonnet 4.5 ($3 / MTok input, $15 / MTok output) eso es alrededor de $0,10-0,15 por run, o $2-4 al mes corriendo solo días laborales. Despreciable. El costo que sí importa son los 10-15 minutos de tiempo del líder de CSM por semana gastados afinando pesos y umbrales durante el primer mes.
Si tu lista de cuentas está en los miles en vez de los cientos, batchea por segmento y corre tres o cuatro digests acotados en vez de uno — el costo por token es el mismo pero la legibilidad por digest se mantiene intacta.
Métrica de éxito
Vigila el porcentaje de cuentas en el bucket Red que tienen una acción registrada por el CSM dentro de 48 horas del digest. Si está arriba del 70%, el digest está haciendo su trabajo: el bucket Red es lo suficientemente corto y confiable como para que los owners actúen sobre él. Si cae por debajo del 50%, o los umbrales están demasiado flojos (el bucket Red está desbordado y siendo ignorado) o las acciones sugeridas son demasiado genéricas (colapso de especificidad de Action — ver cuidados). No optimices por “más cuentas surface” — menos cuentas Red mejor evidenciadas es la meta.
vs alternativas
Gainsight Health Scorecards 2.0 + email de digest nativo. El digest nativo tiene los datos pero no la capa editorial — cada cuenta en riesgo recibe la misma plantilla, sin narrativa de drivers por cuenta ni próxima acción específica. Funciona como sistema de registro; falla como cosa que los CSMs efectivamente abren. Elige esto si tu equipo prefiere menos partes móviles y tienes headcount para leer la versión larga.
Dashboards de BI a medida sobre el warehouse de Gainsight (Looker, Mode, Hex). Mejor para preguntas transversales tipo “muéstrame retención por segmento”, peor para “qué debe hacer el equipo hoy”. Un dashboard que requiere un click es un dashboard que no se va a clickear a las 7am. Corre ambos — el dashboard para revisión mensual, la skill para acción diaria.
Revisión manual de CSM los lunes en la mañana. Lo que la mayoría de los equipos hacen hoy. Funciona a escala de cuatro CSMs, se rompe pasando eso porque cada CSM inventa su propio encuadre de “qué es riesgoso”. La skill existe para darle al equipo un encuadre compartido contra el que pueden discutir editando el archivo de pesos, en vez de discutir entre ellos en standup.
Cuidados
Alert fatigue. Un digest que consistentemente excede 15 cuentas se filtra a carpeta dentro de una semana. Guardia: cap duro en 15 con conteos de overflow honestos en el footer, y si Red excede el cap en tres runs consecutivos preponer una advertencia de que el umbral puede estar demasiado flojo. Implementado en references/3-escalation-criteria-thresholds.md bajo “Self-tuning trigger”.
Inundación de falsos positivos. Un peso mal calibrado de un tipo de evento puede producir un bucket Red dominado por, digamos, cada cuenta con una escalación reciente de soporte. Guardia: el footer del digest incluye una línea de porcentaje de mix de tipo de evento para que el equipo pueda detectar si una señal está dominando antes de que la confianza se erosione. Ejemplo trabajado en references/2-sample-digest.md (“Event-type mix this week:”).
Drift en la ponderación de señales. El archivo de pesos se vuelve obsoleto a medida que el producto y la base de clientes evolucionan. Guardia: la skill emite el SHA corto de references/1-risk-signal-weights.md en el footer del digest. Si el hash no ha cambiado en 90 días, el digest preponer un nudge de recalibración.
Owner desactualizado. Un digest que pingea al CSM equivocado es peor que no tener digest. Guardia: las cuentas cuyo owner_email no se puede resolver se surface bajo un bucket separado *Ownership broken (n)* con un link al editor de ownership de Gainsight — no se les permite caer silenciosamente en Red o Amber.
Stack
Gainsight — fuente de risk-score, contexto de cuenta, eventos de timeline
Claude (Sonnet 4.5) — síntesis, bucketing, redacción de acciones
Slack — canal destino; output mrkdwn, sin attachments
Cron / n8n / tareas programadas de Claude — trigger diario 7am
---
name: churn-risk-summarizer
description: Produce a daily (or weekly) digest of accounts that crossed a churn-risk threshold in the last N hours. Aggregates Gainsight risk-score deltas, recent timeline events, and ARR exposure into a tightly bucketed Slack-ready summary that names the change driver and one specific next action per account.
---
# Churn-risk summarizer
## When to invoke
Run on a schedule (typically 7am local, daily) or on demand to generate a prioritized list of accounts that crossed a churn-risk threshold in the trailing window. Input is a Gainsight account list with risk signals plus recent timeline activity; output is a bucketed digest sized for a CSM team to read in under three minutes.
Do NOT invoke this skill for:
- Triggering automated CSM actions (creating tasks, sending playbook emails, opening cases). The digest is read-only signal — humans decide the next action.
- Any customer-facing communication. Nothing this skill produces is cleared for sending to the customer; treat all output as internal.
- Backfilling historical churn analysis (the prompt is tuned for the trailing 24-168 hours). For longitudinal review, use BI on the Gainsight warehouse instead.
- Risk scoring itself. The skill summarizes scores it is given; it does not compute or reweight them.
## Inputs
- Required: `accounts` — JSON array of account records with at minimum `id`, `name`, `arr`, `risk_score_current`, `risk_score_prior`, `health_score_current`, `health_score_prior`, `owner_email`, `segment`, `renewal_date`.
- Required: `events` — JSON array of timeline events for the same accounts in the trailing window. Each event needs `account_id`, `type` (one of `usage_drop`, `support_escalation`, `sponsor_change`, `qbr_missed`, `nps_detractor`, `contract_renegotiation`, `exec_disengagement`), `severity` (1-5), `occurred_at`, `summary`.
- Optional: `window_hours` — lookback window. Defaults to 24.
- Optional: `min_arr` — drop accounts below this ARR floor. Defaults to 0 (no floor).
- Optional: `segments` — filter to a list of segments (e.g. `["enterprise", "mid-market"]`). Defaults to all.
- Optional: `cap` — maximum accounts to surface in the digest body. Defaults to 15. Overflow goes into a "+N more" link.
## Reference files
Read these from `references/` before generating the digest. They encode the team's risk-weighting opinion and the digest format. Without them, the output is generic.
- `references/1-risk-signal-weights.md` — per-event-type weighting config the skill applies when ranking accounts within a bucket.
- `references/2-sample-digest.md` — the literal Slack-ready digest format the skill emits, with a worked example.
- `references/3-escalation-criteria-thresholds.md` — the bucket thresholds (red / amber / watch) and the rules for when a single signal is enough to escalate by itself.
## Method
Run these five steps in order. Do not parallelize: bucketing depends on aggregation, narrative depends on bucketing.
### 1. Signal aggregation
For each account, collect the trailing-window events from `events`, sort by `occurred_at` descending, and compute a per-account `signal_score` as the sum of `severity * weight` per event using the weights in `references/1-risk-signal-weights.md`. Cap any single event's contribution at 5 — one escalation should not single-handedly dominate the score unless the weights file says so explicitly.
The reason for explicit weighting (rather than letting the model "decide what's important"): weights are auditable. When a CSM lead disagrees with what got surfaced, they can edit one number in the weights file. A per-run model judgment cannot be edited.
### 2. Threshold-based bucketing
Apply the thresholds in `references/3-escalation-criteria-thresholds.md` to assign each account to exactly one bucket:
- **Red** — risk_score crossed the explicit churn-risk line, OR signal_score >= the red threshold, OR a single event is on the always-escalate list (e.g. `exec_disengagement` at severity 5).
- **Amber** — health_score dropped by more than the amber delta, OR signal_score is between amber and red.
- **Watch** — any other accounts that crossed *into* the band but do not meet amber criteria.
If `min_arr` or `segments` filters drop an account below the floor, exclude it from all buckets — but record the count for the footer.
### 3. Per-account evidence-grounded narrative
For each account in Red and Amber (skip Watch — it gets a count-only line), compose:
- One-line change driver naming the dominant event, never paraphrased away from `events[].summary`. If the dominant event was a usage drop, say "active seats fell from 142 to 89 over 7 days," not "engagement is declining."
- One concrete suggested action, formatted as a verb plus a named artifact (a meeting, a person, a doc). Examples: "Call the CFO before Friday's renewal kickoff." "Open a case with support to triage the open P1." "Forward last week's QBR deck to the new VP of Eng."
- If no concrete action can be supported from the evidence, output `needs human review` rather than padding. Vague actions are the primary failure mode the digest exists to avoid.
### 4. Prioritization
Within each bucket, sort by ARR descending, breaking ties by `renewal_date` ascending (closer renewals first). Apply `cap` to the combined Red + Amber list. If the cap drops accounts, surface them only as a count and a link to the full Gainsight saved view.
### 5. Format and emit
Render to the layout in `references/2-sample-digest.md`. The output is a single Slack-mrkdwn block plus a fallback plaintext copy. Do not include tables, attachments, or threads — the digest must be scannable in the channel without expanding anything.
## Output format
```markdown
*Daily churn-risk digest — {YYYY-MM-DD}*
*Red ({n_red})* — act this week
- *{Account name}* — ${ARR}k ARR · owner @{owner_handle} · renewal {renewal_date}
Driver: {one-line driver from evidence}
Action: {verb + named artifact}
- ...
*Amber ({n_amber})* — review by Friday
- *{Account name}* — ${ARR}k ARR · owner @{owner_handle} · renewal {renewal_date}
Driver: {one-line driver}
Action: {verb + named artifact, or `needs human review`}
- ...
*Watch ({n_watch})* — no action required, tracking only.
{count summary, no per-account detail}
_Filtered out: {n_below_floor} below ${min_arr}k · {n_below_segment} outside segment._
_Capped at {cap} of {n_red + n_amber} qualifying. Full list: {gainsight_saved_view_url}_
```
## Watch-outs
- **Alert fatigue.** If the digest carries more than ~15 accounts day after day, owners stop opening it. Guard: enforce `cap` strictly, and if Red exceeds cap on three consecutive runs, prepend a `_Threshold may be too loose — last 3 runs averaged {n} Red. Consider raising the red threshold in references/3-escalation-criteria-thresholds.md._` warning. Do not silently truncate without flagging.
- **False-positive flooding.** Any single event type producing more than 30% of Red accounts in a week is a signal that its weight is miscalibrated. Guard: at the end of the digest, include a one-line diagnostic — `_Event-type mix this week: usage_drop 18%, support_escalation 22%, ..._` — so the team can spot one signal dominating before it erodes trust in the digest.
- **Signal weighting drift.** Weights in the references file go stale as the product and customer base change. Guard: include the SHA-256 (first 7 chars) of `references/1-risk-signal-weights.md` in the digest footer. If the footer hash hasn't changed in 90 days, the digest prepends `_Weights file last touched 90+ days ago. Time to recalibrate._`
- **Owner staleness.** If `owner_email` is empty or maps to a former employee, the ping goes to the wrong person and the action does not happen. Guard: any account whose owner handle cannot be resolved gets surfaced under `*Ownership broken ({n})*` instead of Red/Amber, with a link to the Gainsight account ownership editor.
- **Action specificity collapse.** Under load, the model defaults to generic "engage stakeholder" suggestions. Guard: post-process the Action field with a literal substring check — if the action contains any of `engage`, `reach out`, `touch base`, `align`, `socialize` without a named person or artifact, replace it with `needs human review`. Better silence than noise.
# Risk signal weights — TEMPLATE
> Replace these weights with values your CSM lead has signed off on.
> The skill multiplies `severity` (1-5) by the weight below to get
> per-event contribution to `signal_score`. Edit one number at a time
> and watch the next two digests before editing again.
## Per-event-type weights
| Event type | Weight | Notes |
|-------------------------|-------:|-----------------------------------------------------------------|
| `exec_disengagement` | 5.0 | Sponsor stops attending QBRs / unread emails for 30+ days |
| `sponsor_change` | 4.0 | Champion left or moved internally; new owner not yet onboarded |
| `contract_renegotiation`| 3.5 | Procurement opened a contract review outside the renewal window |
| `support_escalation` | 3.0 | P1 case open > 5 business days, or 3+ P2s in 14 days |
| `usage_drop` | 3.0 | Active seats / API calls / features-used down >25% over 14 days |
| `nps_detractor` | 2.0 | NPS <= 6 from any buying-committee role in the last 30 days |
| `qbr_missed` | 2.0 | Cancelled or no-show with no reschedule within 14 days |
## Always-escalate single signals
These trigger Red regardless of `signal_score`. The skill should treat them as a hard override, not a soft boost.
- `exec_disengagement` at severity 5
- `sponsor_change` at severity 4-5 when the renewal date is within 90 days
- `contract_renegotiation` at any severity when ARR > 250k
## Per-event contribution cap
A single event contributes at most 5.0 to `signal_score` regardless of `severity * weight`. This prevents one severity-5 sponsor change from single-handedly flooding the digest with one account at the expense of two genuinely declining ones.
## Weight calibration log
Append every change here so the next person editing this file can see why the numbers are what they are. Format: `YYYY-MM-DD — change — reason`.
- {YYYY-MM-DD} — initial weights — placeholder, replace with team-tuned values
## Last edited
{YYYY-MM-DD}
# Sample digest — worked example
> The skill emits this exact format, Slack-mrkdwn flavored. Treat this
> file as the contract: if you change the layout, change it here first
> and the skill follows. Do not let the model improvise structure.
## Worked example output
```
*Daily churn-risk digest — 2025-11-04*
*Red (3)* — act this week
- *Acme Robotics* — $480k ARR · owner @nadia · renewal 2025-12-18
Driver: VP Eng skipped two scheduled syncs and an automation pilot was paused on 10-29.
Action: Get Nadia a 30-min slot with the new VP Eng before Friday's renewal kickoff.
- *Northwind Logistics* — $310k ARR · owner @marcus · renewal 2026-01-09
Driver: Active seats fell from 142 to 89 over the last 7 days; finance opened a contract review.
Action: Open a discount-modeling thread with the deal desk before the procurement call on 11-07.
- *Globex Health* — $265k ARR · owner @priya · renewal 2026-02-22
Driver: P1 outage case open since 10-30 with no first-response SLA met.
Action: Escalate the open P1 to support leadership and brief Priya before her standing customer call.
*Amber (4)* — review by Friday
- *Initech* — $180k ARR · owner @marcus · renewal 2026-03-14
Driver: Sponsor moved to a new role last week; new owner has not been introduced.
Action: Send the QBR deck and offer a 15-min intro call with the new sponsor.
- *Vandelay Imports* — $140k ARR · owner @nadia · renewal 2026-01-30
Driver: Three P2 cases opened in the last 10 days, all on the reporting module.
Action: needs human review
- *Soylent Foods* — $115k ARR · owner @priya · renewal 2026-04-02
Driver: NPS dropped to 4 from the Director of Ops on 10-31.
Action: Forward the survey verbatim to Priya and request a follow-up 1:1 with the Director.
- *Pied Piper* — $95k ARR · owner @marcus · renewal 2026-02-11
Driver: QBR cancelled 10-28, no reschedule.
Action: Propose three slots for next week and copy the original sponsor.
*Watch (6)* — no action required, tracking only.
6 accounts crossed into the watch band; signal not strong enough for action this week.
_Filtered out: 2 below $50k · 0 outside segment._
_Capped at 13 of 13 qualifying. Full list: https://gainsight.example.com/views/churn-risk-trailing-24h_
_Event-type mix this week: usage_drop 24%, support_escalation 28%, sponsor_change 14%, qbr_missed 12%, nps_detractor 10%, exec_disengagement 6%, contract_renegotiation 6%._
_Weights file: 1-risk-signal-weights.md @ a3f9c12_
```
## Notes for the skill
- Account names are bolded with single asterisks (Slack-mrkdwn).
- The `Action:` line is the *only* place where a generic phrase (`engage`, `align`, `socialize`, `reach out`, `touch base`) is rejected and replaced with `needs human review`.
- The Watch bucket never emits per-account lines. Only the count.
- The footer carries three diagnostics — filter counts, event-type mix, and the weights-file hash — that exist to make miscalibration visible early. Do not drop them to save lines.
# Escalation criteria thresholds — TEMPLATE
> Replace these defaults with the values your CSM lead has signed off
> on. Aim for 5-15 total Red+Amber accounts per daily run; if you are
> consistently above or below, the thresholds are wrong, not the team.
## Bucket definitions
An account lands in exactly one bucket per run. The skill evaluates in this order and stops at the first match.
### Red — act this week
ANY of the following:
- `risk_score_current` crossed the explicit churn-risk line set in Gainsight (e.g. moved from "Medium" to "High", or numeric score crossed below 40), AND `risk_score_prior` was on the safe side of that line within the trailing window.
- `signal_score` >= **12.0** (sum of `severity * weight` across trailing-window events, per `1-risk-signal-weights.md`).
- A single event matches the always-escalate list in `1-risk-signal-weights.md` ("Always-escalate single signals").
### Amber — review by Friday
ANY of the following, and NOT already Red:
- `health_score_current - health_score_prior` <= **-15** in the trailing window.
- `signal_score` between **6.0** and **12.0**.
### Watch — count only
Crossed into the band (any negative movement on either score) but does not meet Amber criteria. Surfaced as a count only.
## Filters
Applied before bucketing. Filtered accounts are excluded from all buckets and reported in the footer.
- `min_arr` — drop accounts with `arr` < this value. Default **0**. Most teams that send to a channel set this to **50** (k$) to keep the digest scannable.
- `segments` — restrict to a list of `segment` values. Default: all segments. Most teams running a daily digest restrict to `["enterprise", "mid-market"]` and run a separate weekly digest for SMB to keep the daily list focused on accounts that justify a human-touch action.
## Cap and overflow
`cap` = **15** by default. After Red+Amber are sorted by ARR descending, anything beyond the cap goes into the footer count + a link to the saved Gainsight view. Do not silently drop accounts — the count must always be honest.
## Self-tuning trigger
If Red exceeds `cap` on three consecutive runs, the skill prepends a warning to the digest noting the threshold may be too loose. The skill does NOT auto-edit this file. Threshold edits are a human decision; the skill only surfaces the signal.
## Threshold change log
Append every change so the next person editing this file can see why the numbers are what they are. Format: `YYYY-MM-DD — change — reason`.
- {YYYY-MM-DD} — initial thresholds — placeholder, replace with team-tuned values
## Last edited
{YYYY-MM-DD}