Ein Claude Skill, der die letzten sieben Tage CSM-Calls, Nutzungsanomalien und Support-Tickets über Ihr Kunden-Portfolio scannt und einen per-CSM-geordneten Digest von Accounts ausgibt, die konkreten Expansions-Intent zeigen. Jeder aufgezeigte Account nennt das Upsell-SKU, die wörtliche Evidenz, die es stützt, und eine einzelne Next-Best-Action, die der CSM diese Woche unternehmen kann. Das Bundle wird unter apps/web/public/artifacts/expansion-signal-detection-claude/ geliefert und enthält SKILL.md sowie drei Referenzdateien, die das Team bearbeitet, um seine eigene SKU-Lineup, Segment-Baselines und CSM-Action-Playbook abzubilden.
Wann einsetzen
Verwenden Sie diesen Skill, wenn Ihr CS-Team mehr Accounts verwaltet, als ein einzelner Mensch jede Woche manuell scannen kann, und Sie mindestens zwei überlappende Datenquellen zur Fusion haben — typischerweise Gong-aufgezeichnete CSM-Calls plus Gainsight- (oder Warehouse-emittierte) Nutzungsanomalien. Der Skill ist für Teams von drei oder mehr CSMs über ein Portfolio von mindestens 100 Accounts konzipiert; darunter übertrifft ein CSM-Lead, der jeden Call manuell liest, jeden automatisierten Digest, weil der Mensch Kontext sieht, den die Taxonomie-Datei nicht kodiert.
Die richtige Kadenz ist wöchentlich — typischerweise Montagmorgen, vor dem Account-Review-Meeting des Teams — und der richtige Output ist ein persönlicher Slack-DM pro CSM, begrenzt auf drei starke Signale. Die Begrenzung ist wichtig: In Pilotprojekten wird ein CSM-Digest von 10 oder mehr „engagierten Accounts” zwei Wochen lang gelesen und dann dauerhaft ignoriert. Drei konkrete Anfragen pro Woche, jeden Montag wiederholt, ist die Kadenz, die das Team tatsächlich internalisiert.
Wann NICHT einsetzen
Sie wollen Echtzeit-Alerting bei einzelnen Events. Per-Event-Pings überfluten CSMs und erodieren das Vertrauen in den Kanal innerhalb von zwei Wochen. Die wöchentliche Kadenz ist bewusst. Wenn Ihr CRO auf Echtzeit besteht, erwarten Sie, dass der Digest bis Q2 stummgeschaltet wird.
Sie haben keine Nutzungsanomalien in einem strukturierten Feed. Der Skill verbraucht vorab-emittierte Anomalie-Events; er erkennt sie nicht aus rohen Event-Streams. Wenn Gainsight nicht bereits seat_count_spike, feature_first_use und tier_gated_feature_attempt-Events feuert, beheben Sie zuerst diese Pipeline — der Skill auf einem leeren Feed produziert einen Digest nur mit Calls, was alle Signale auf schwach kollabieren lässt.
CSMs loggen keine Calls. Wenn weniger als 60 Prozent der Accounts einen geloggten Call im Trailing-Window haben, ist die Gesprächshälfte jedes Signal-Sets leer und die meisten Signale kollabieren auf schwach. Prüfen Sie die Gong-Adoption, bevor Sie sich darauf verlassen. Der Skill bricht den Run mit einem Coverage-Fehler ab, wenn die Rate unter 40 Prozent fällt, statt einen Halb-Signal-Digest auszugeben.
Sie wollen Gainsight-CTAs automatisch erstellen oder Kunden automatisch anmailen. Dieser Skill ist nur lesend in Bezug auf Signale. Der Output ist als CSM-Pre-Meeting-Vorbereitung konzipiert, nicht als Workflow-Trigger. Eine Auto-Action-Schicht nachgelagert zu verdrahten ist der schnellste Weg, einem CFO eine „wir haben festgestellt, dass Sie von unserem Enterprise-Tier profitieren würden”-E-Mail in der Woche zu senden, nachdem sein Champion gerade gegangen ist.
Sie wollen eine Expansions-ARR-Prognose. Der Output ist ein Per-Account-Intent-Signal, keine Zahl für eine Finanzprognose. Expansions-ARR-Prognose erfordert Close-Rate-Kalibrierung, die der Skill nicht hat.
Einrichtung
Das Artefakt-Bundle wird unter apps/web/public/artifacts/expansion-signal-detection-claude/ geliefert. Laden Sie es herunter, bearbeiten Sie die drei Referenzdateien, um Ihre Realität abzubilden, und installieren Sie dann den Skill.
Bundle herunterladen und entpacken. Legen Sie expansion-signal-detection-claude/ unter ~/.claude/skills/ ab. Das Layout ist SKILL.md plus references/1-expansion-signal-taxonomy.md, references/2-segment-baseline-config.md und references/3-action-library.md.
Signal-Taxonomie aufbauen. Bearbeiten Sie references/1-expansion-signal-taxonomy.md mit Ihren tatsächlichen Upsell-SKUs und den Call-Trigger-Phrasen, Nutzungs-Event-Typen und Support-Ticket-Tags, die jedem zugeordnet sind. Seien Sie spezifisch: nicht „mehr Nutzer”, sondern „fragte nach Preisgestaltung für 50 oder mehr Seats” oder „nannte Compliance-Anforderungen.” Der Negativbeispiel-Abschnitt fängt bedingte Phrasen ab („wenn Sie X unterstützen würden”), die wie Intent wirken, aber tatsächlich Feature-Gap-Berichte sind — halten Sie ihn gepflegt, denn eine veraltete Negativbeispiel-Liste ist die häufigste Ursache für False-Positive-Flooding.
Segment-Baselines kalibrieren. Bearbeiten Sie references/2-segment-baseline-config.md mit Werten, die aus einem 90-Tage-Rolling-Window über Ihr Nutzungs-Warehouse berechnet wurden. Pro Segment listen Sie das wöchentliche Median-Delta und das Zwei-Sigma-Rauschband für jede Metrik auf. Der Skill lehnt Events ab, deren delta_pct innerhalb des Rauschabands liegt, auch wenn sie den globalen Emitter-Schwellenwert überschritten haben — das ist es, was verhindert, dass SMB-Seat-Count-Rauschen echte Enterprise-Expansion ertränkt.
Action-Library befüllen. Bearbeiten Sie references/3-action-library.md mit einer oder mehreren Next-Best-Actions pro SKU. Jeder Eintrag muss der Form Verb plus benanntes Artefakt (ein Meeting, eine Person, ein Dokument, ein Ticket) folgen — der Skill erzwingt das mit einem Literal-Substring-Filter auf dem emittierten Action-Feld und ersetzt alles Vages durch needs human review.
Datenquellen verdrahten. Setzen Sie GONG_API_KEY für Transkript-Ziehung, GAINSIGHT_TOKEN für den Nutzungs-Event- und Account-Feed und Ihren Support-Ticket-API-Token (Zendesk, Intercom oder Helpscout, je nach Ihrem Stack). Der Skill liest vorab berechnete Anomalien aus dem Nutzungs-Feed; er führt selbst keine Anomalieerkennung durch.
Wöchentlich ausführen. Rufen Sie expansion_signal_detection(window_days=7) aus einer geplanten Claude Code-Session auf (Cron oder GitHub Actions workflow_dispatch auf einem wöchentlichen Trigger). Output ist eine Markdown-Datei pro CSM-Owner, gepostet als Slack-DM statt in einem öffentlichen Kanal — das Ziel ist Per-CSM-Verantwortlichkeit, kein öffentliches Leaderboard, an dem das Team vorbei scrollt.
Was der Skill tatsächlich macht
Die Arbeit besteht aus sechs sequenziellen Schritten, die im Detail in der SKILL.md des Bundles dokumentiert sind. Die Form:
Per-Account-Evidenzsammlung. Jeden Call, jedes Nutzungs-Event und jedes Ticket im Window sammeln. Accounts mit null Datensätzen löschen, damit Stille die Rankingliste nicht verdünnt.
Per-Segment-Baseline-Filterung. Für jedes Nutzungs-Event das Rauschband des Segments in references/2-segment-baseline-config.md nachschlagen und Events innerhalb des Bands verwerfen. Der Grund für Per-Segment-Baselines statt eines einzelnen globalen Schwellenwerts: Ein 30-prozentiger Wochenzuwachs bei der Seat-Anzahl bedeutet etwas anderes für ein 5-Seat-SMB als für ein 500-Seat-Enterprise. Ein einzelner globaler Schwellenwert garantiert, dass das SMB-Band das Enterprise-Band ertränkt.
Signal-Extraktion aus Calls und Tickets. Einen Extraktions-Prompt gegen jedes Transkript und Ticket ausführen, unter Verwendung der Trigger-Phrasen in references/1-expansion-signal-taxonomy.md, mit der Negativbeispiel-Schicht, die bedingte Phrasen explizit als not_signal klassifiziert.
Stark-vs.-Schwach-Klassifikation. Ein Signal ist nur stark, wenn mindestens eine Call-Erwähnung UND mindestens ein Nutzungs-Event dasselbe SKU innerhalb des Windows treffen. Alles andere ist schwach. Der Grund für die Aufteilung statt eines einzigen Score-and-Rank: Das Routing unterscheidet sich. Starke Signale rechtfertigen, dass ein CSM diese Woche eine Meeting-Einladung sendet; schwache Signale rechtfertigen einen Blick während der normalen Account-Überprüfung. Schwache Signale in die Rankingliste zu setzen, trainiert den CSM, die Rankingliste zu ignorieren.
Per-CSM-Routing und Priorisierung. Starke Signale nach owner_email gruppieren, nach ARR absteigend dann renewal_date aufsteigend sortieren, cap_per_csm (Standard drei) anwenden.
Action-Mapping und Ausgabe. Jedes aufgezeigte Signal in references/3-action-library.md nachschlagen und die passende Next-Best-Action anhängen. Wenn kein Eintrag passt, needs human review ausgeben statt eine zu synthetisieren — vage Actions sind der Fehlermodus, der das Vertrauen am schnellsten erodiert.
Kostenrealität
Die dominanten Token-Kosten sind der Call-Extraktionsschritt. Ein typischer wöchentlicher Run für ein 200-Account-Portfolio mit einem CSM-Call pro Account pro Woche läuft ungefähr:
200 Transkripte bei durchschnittlich 6.000 Token jeweils = 1,2M Input-Token für die Extraktion.
200 Ticket-Body-Zusammenfassungen bei ungefähr 800 Token jeweils = 0,16M Input-Token.
Gesamt pro wöchentlichem Run: ungefähr 1,76M Input-Token, 0,1M Output-Token.
Zu Claude Sonnet-Preisen (rund 3 $ pro Million Input, 15 $ pro Million Output als von 2026-Q1) sind das etwa 5,30 $ + 1,50 $ = unter 7 $ pro wöchentlichem Run. Jährlich: unter 400 $ pro Jahr pro 200-Account-Portfolio. Bei einem 1.000-Account-Portfolio mit ähnlicher Call-Abdeckung linear auf unter 2.000 $ pro Jahr skalieren. Der Kostenboden ist der Call-Extraktionsschritt; wenn Ihre CSMs wenige Calls loggen, sinkt die Rechnung proportional und so auch die Signalqualität.
Die versteckte Kosten sind die Taxonomie-Wartung. Erwarten Sie, dass ein CSM-Lead ungefähr 30 Minuten pro Quartal damit verbringt, references/1-expansion-signal-taxonomy.md und die Action-Library zu bearbeiten, und eine längere Ad-hoc-Session, wann immer ein neues SKU startet. Das Überspringen dieser Wartung ist es, was den Digest veralten lässt — der Skill gibt weiterhin zuversichtlichen Output gegen eine SKU-Lineup aus, die nicht mehr existiert.
Erfolgsmetrik
Die zu beobachtende Metrik ist die CSM-bestätigte Konversionsrate starker Signale zu Expansionsgesprächen innerhalb von 14 Tagen. Verfolgen Sie sie auf einem Trailing-30-Tage-Window. Frühe Baselines von Pilot-Teams landen im Bereich von 25–40 Prozent — was bedeutet, dass ungefähr eines von drei starken Signalen zu einem echten Gespräch führt, das der CSM in diesem Monat sonst nicht gehabt hätte. Unter 20 Prozent für zwei aufeinanderfolgende Monate bedeutet, dass der Stark-vs.-Schwach-Cutoff zu locker ist oder die Action-Library zu vage ist; straffen Sie die Taxonomie oder schreiben Sie die Hälfte der Actions um, bevor Sie fortfahren.
Nachlaufende Metrik: Expansions-ARR-Beitrag, der dem Digest zugeschrieben wird, beim vierteljährlichen Abschluss verfolgt. Das ist schwieriger sauber zu messen, weil Expansionsgespräche viele Ursachen haben, aber ein CSM-Umfragefeld bei jeder gewonnenen Expansion („hat der Digest diesen Account aufgezeigt, bevor Sie das Gespräch eröffnet haben?”) ist ein ausreichend guter Proxy.
Vergleich mit Alternativen
vs. Gainsight Expansion Management. Das native Modul von Gainsight rankt Accounts auf einem einzelnen zusammengesetzten Score und routet über CTAs. Es funktioniert, aber es ist undurchsichtig — wenn ein CSM mit dem Ranking nicht einverstanden ist, kann er keine Konfigurationsdatei bearbeiten, sondern nur ein Ticket beim Admin einreichen. Dieser Skill hält die Ranking-Logik in drei Klartextdateien, die der CSM-Lead direkt besitzt und bearbeitet. Wählen Sie Gainsight, wenn Ihr CS-Ops-Team ein geschlossenes System möchte; wählen Sie diesen, wenn das Team die Regeln besitzen soll.
vs. manuelle CSM-geführte QBRs. Ein erfahrener CSM, der eine persönliche Notion-Überprüfung seines Buchbestands durchführt, übertrifft jeden Digest bei der Unter-50-Account-Skala, weil er Kontext hält, den die Taxonomie nicht kodieren kann. Bei 100+ Accounts pro CSM dreht sich die Mathematik: Niemand kann wöchentlich so viele Transkripte scannen. Der Digest ist ein Kraft-Multiplikator, kein Ersatz, und die Action-Library ist absichtlich so geformt, dass der CSM das Gespräch führt, nicht der Skill.
vs. generische BI-Dashboards. Ein Looker-Dashboard mit „Accounts mit Nutzungs-Spikes” produziert jede Woche eine Liste, auf der niemand handelt, weil es kein benanntes SKU, keine wörtliche Call-Evidenz und keine nächste Action gibt. Der Digest-Wert liegt in der Fusion plus der Action, nicht im Ranking — ohne SKU-Map und Action-Library haben Sie eine langsamere Version des Dashboards.
Watch-outs
False-Positive-Flooding. Wenn der Call-Extraktions-Prompt locker ist, schwillt die Stark-Signal-Liste auf 10 oder mehr pro CSM pro Woche an. Guard: cap_per_csm streng durchsetzen, und wenn die Stark-Liste eines einzelnen CSMs auf drei aufeinanderfolgenden Runs die Obergrenze überschreitet, eine Warnung voranstellen, dass der Stark-vs.-Schwach-Cutoff zu locker ist und auf references/1-expansion-signal-taxonomy.md zum Straffen verlinken. Nicht still abschneiden.
Signal-Fehlinterpretation — Champion-Departure-Falle. Ein Nutzungs-Spike direkt nachdem der benannte Champion gegangen ist, ist ein Expansions-Risiko-Signal, kein Expansions-Intent-Signal — der neue Owner erkundet, bevor er entscheidet, ob er den Vertrag überhaupt behält. Guard: Jedes starke Signal gegen stakeholder_changes kreuzen. Wenn ein Champion auf dem Account in den letzten 30 Tagen gegangen ist, auf schwach herabstufen und mit champion-departure suppressed: investigate before pursuing taggen. Der Skill darf niemals eine Expansions-Anfrage an einen Account routen, der gerade seinen Champion verloren hat.
Threshold-Drift. Trigger-Phrasen und SKU-Mappings veralten, wenn sich das Produkt ändert. Ein neues SKU, das vor zwei Monaten gestartet ist, hat null Einträge in der Taxonomie, bis jemand sie hinzufügt, und jedes Signal dafür wird still fehl-geroutet. Guard: Den SHA-256 (erste sieben Zeichen) von references/1-expansion-signal-taxonomy.md in der Diagnose-Fußzeile einschließen. Wenn die Datei seit 90 Tagen nicht berührt wurde, eine Warnung voranstellen, dass die Taxonomie veraltet ist, und zur Datei zur Rekalibrierung verlinken.
Bedingte-Erwähnung-Fehlklassifikation. „Wir würden eine Expansion in Betracht ziehen, wenn Sie X unterstützen würden” liest sich oberflächlich als Expansions-Intent, ist aber tatsächlich ein Feature-Gap-Bericht. Guard: Die Negativbeispiel-Schicht im Extraktionsschritt klassifiziert bedingte Phrasen („wenn”, „würde”, „erwägen”, „denken darüber nach”) explizit als not_signal. Diagnosen zeigen, wie oft das feuert — wenn es nie feuert, ist die Schicht defekt; wenn es ständig feuert, muss das SKU-Mapping neu formuliert werden.
Action-Specifizitäts-Kollaps. Unter Last fällt das Modell auf „follow up on the opportunity”-Vorschläge zurück. Guard: Der Post-Process-Filter in Schritt 6 lehnt jedes Action-Feld ab, das vage Verben enthält (follow up, reach out, touch base, align, socialize, engage) ohne eine benannte Person, ein Meeting oder ein Dokument, und ersetzt es durch needs human review. Besser Stille als Rauschen.
Stack
Gong — CSM-Call-Korpus und Transkript-API
Gainsight — Nutzungsanomalien-Quelle und Account-Feed
Zendesk / Intercom / Helpscout — Support-Ticket-Quelle für Integrations-Fragen-Signale
Claude — Signal-Extraktion, Segment-Baseline-Filterung, Stark-vs.-Schwach-Klassifikation, Action-Mapping
---
name: expansion-signal-detection
description: Weekly account-portfolio scan that fuses CSM-call mentions with usage anomalies, classifies expansion intent into weak vs strong signals, and emits a per-CSM ranked digest mapping each signal to a likely upsell SKU and a next-best action. Read-only — never contacts customers, never auto-creates Gainsight CTAs.
---
# Expansion-signal detection
## When to invoke
Run once a week (typically Monday morning, before the CSM team's weekly account review) to scan the trailing 7 days of CSM calls and usage events across the customer portfolio. Output is a ranked digest per CSM owner, sized for a 5-minute pre-meeting read.
Do NOT invoke this skill for:
- Auto-emailing customers, auto-creating Gainsight CTAs, or any outbound action. The skill is read-only signal — humans decide which account to actually approach.
- Real-time alerting on individual events. Per-event pings flood CSMs and erode trust in the channel within two weeks. The weekly cadence is deliberate.
- Sales-call analysis (new logos, prospecting). The signal taxonomy here assumes existing customers with a baseline of usage and a named CSM. Use the AE call-coach skill instead.
- Replacing a usage-anomaly detection system. The skill consumes pre-computed anomalies; it does not detect them. If Gainsight isn't already firing usage-spike events, fix that first.
- Forecasting expansion ARR. The output is per-account intent signal, not a number a finance team should plug into a forecast.
## Inputs
- Required: `accounts` — JSON array with `id`, `name`, `arr`, `segment` (e.g. `enterprise` / `mid-market` / `smb`), `tier` (current SKU tier), `owner_email`, `renewal_date`.
- Required: `calls` — JSON array of CSM call records for the trailing window. Each record needs `account_id`, `call_id`, `occurred_at`, `transcript_url` or `transcript_text`, `attendees` (with `is_customer` flag and role/title where known).
- Required: `usage_events` — JSON array of usage anomalies emitted by Gainsight (or your usage-warehouse equivalent) for the same window. Each event needs `account_id`, `event_type` (e.g. `feature_first_use`, `seat_count_spike`, `api_call_spike`, `tier_gated_feature_attempt`), `metric_name`, `value_current`, `value_baseline`, `delta_pct`, `occurred_at`.
- Required: `support_tickets` — JSON array of recent tickets with `account_id`, `subject`, `body_summary`, `tags`, `opened_at`. Used to spot integration / capability questions tied to premium SKUs.
- Optional: `stakeholder_changes` — JSON array of org-chart events (`account_id`, `change_type` of `new_hire` / `promotion` / `departure`, `role`, `is_champion`, `occurred_at`). Used to suppress signals contaminated by champion churn (see watch-outs).
- Optional: `window_days` — lookback window. Defaults to 7. Going shorter than 7 typically yields too few signals per account to classify; going longer than 14 stale-dates the next-best action.
- Optional: `cap_per_csm` — maximum signals surfaced per CSM in the digest body. Defaults to 3. Overflow is summarized as a count.
## Reference files
Read these from `references/` before running. They encode the team's taxonomy and per-segment baselines — without them the output is generic "this account is engaged" filler.
- `references/1-expansion-signal-taxonomy.md` — the SKU-to-trigger mapping. Each upsell SKU lists the call phrases, usage patterns, and ticket topics that count as evidence, plus weak-signal vs strong-signal cutoffs.
- `references/2-segment-baseline-config.md` — per-segment baselines for usage anomalies (a 30 percent week-over-week jump means something different for an SMB on 5 seats than an enterprise on 500). The skill rejects anomalies that exceed the absolute threshold but fall inside the segment's noise band.
- `references/3-action-library.md` — the next-best-action library the skill maps signals to. Each action is a verb plus a named artifact (a meeting, a doc, a person), not a vague "follow up."
## Method
Run these six steps in order. Do not parallelize: classification depends on aggregation, routing depends on classification.
### 1. Per-account evidence collection
For each account in `accounts`, gather every record from `calls`, `usage_events`, and `support_tickets` within `window_days`. Drop accounts with zero records — silence is not a signal here, and an empty entry in the digest dilutes the ranked list. Record the count of dropped accounts for the footer so the team can see coverage.
### 2. Per-segment baseline filtering
For each `usage_event`, look up the account's `segment` in `references/2-segment-baseline-config.md` and fetch the baseline noise band (typically expressed as a two-sigma range around the segment median for that metric). Discard events whose `delta_pct` falls inside the noise band even if the absolute value crossed the emitter's threshold.
The reason for per-segment baselines (rather than a single global threshold): a 30 percent week-over-week seat jump is meaningful noise for an SMB account that adds 1-2 seats normally, and meaningful signal for an enterprise account on a flat 500-seat plan. A single global threshold guarantees the SMB band drowns out the enterprise band. Per-segment baselines are auditable — when a CSM lead disagrees with the cutoff, they edit one row in the config rather than tuning a hidden constant.
### 3. Signal extraction from calls and tickets
For each call transcript and ticket body in scope, run an extraction prompt that scans for the trigger phrases listed in `references/1-expansion-signal-taxonomy.md`. Each match is logged with the SKU it maps to, the verbatim quote, the speaker (with `is_customer` filter — coach mentions don't count), and the `call_id` or `ticket_id` it came from.
Negative-example guard: the prompt explicitly enumerates phrases that look adjacent but mean the opposite ("we're thinking about leaving," "your enterprise tier is too expensive," "we'd consider expanding if X were true" — conditional, not committed). These are classified as `not_signal` rather than dropped silently, so the diagnostics in step 6 can show how often the negative-example layer fired.
### 4. Weak-signal vs strong-signal classification
For each per-account candidate signal, classify into one of three buckets using the cutoffs in `references/1-expansion-signal-taxonomy.md`:
- **Strong** — at least one corroborating call mention plus at least one corroborating usage event for the same SKU within the window. These get routed to the per-CSM digest as ranked entries.
- **Weak** — call mention OR usage event alone, OR both but for different SKUs. These get aggregated into a per-CSM "weak signals worth a glance" footer with a count and a link, never as ranked entries.
- **Insufficient** — fewer than the cutoff above. Recorded for the diagnostics footer; not surfaced per-CSM.
The reason for weak-vs-strong split rather than a single score-and-rank: routing differs. A strong signal warrants a CSM sending a meeting invite this week. A weak signal warrants the CSM glancing during their normal account review. Putting weak signals in the ranked list trains the CSM to ignore the ranked list.
### 5. Per-CSM routing and prioritization
Group strong signals by `owner_email`. Within each owner's list, sort by ARR descending, breaking ties by `renewal_date` ascending (closer renewals first — expansion plus a near-term renewal is more actionable than expansion in month 11 of a 24-month deal). Apply `cap_per_csm` to the strong list. If the cap drops signals, surface them only as a count in the weak-signals footer for that CSM.
### 6. Action mapping and emit
For each surfaced strong signal, look up the SKU and signal pattern in `references/3-action-library.md` and attach the matching next-best action. If no action is found, output `needs human review` rather than synthesizing one. Vague suggested actions are the failure mode that erodes trust fastest — better silence than noise.
Render to the layout in the Output format section below. Emit one file per CSM owner (not one combined file) so the digest can be delivered as a personal Slack DM rather than a public channel post that creates implicit social pressure.
## Output format
```markdown
# Expansion-signal digest — {YYYY-MM-DD} — {CSM name}
Window: trailing {window_days} days · Strong signals: {n_strong} · Weak signals: {n_weak}
## Strong signals — act this week
### 1. {Account name} — ${ARR}k ARR · renewal {renewal_date}
SKU: {target_sku}
Call evidence:
> "{verbatim quote}" — {speaker_name}, {role}, {call_date} ({call_id})
Usage evidence: {metric_name} went from {value_baseline} to {value_current} ({delta_pct} over {n} days, segment-baseline-adjusted)
Action: {verb + named artifact, from action library}
### 2. {Account name} — ...
## Weak signals — worth a glance ({n_weak})
- *{Account name}* — {SKU}: {one-line summary, e.g. "call mention only, no usage corroboration"}
- *{Account name}* — {SKU}: {one-line summary}
- (+{n_overflow} more capped from strong list — see footer)
## Diagnostics
- Accounts in scope: {n_total}
- Accounts with zero records (dropped): {n_silent}
- Negative-example matches (suppressed): {n_negative}
- Champion-departure suppressions: {n_champion_suppressed}
- Taxonomy file hash: {first_7_chars_of_sha256}
```
## Watch-outs
- **False-positive flooding.** When the call-extraction prompt is loose, it surfaces "showed interest" mentions that don't actually predict expansion, and the CSM's strong-signal list bloats to 10+ per week. Guard: enforce `cap_per_csm` strictly, and if any single CSM's strong list exceeds the cap on three consecutive runs, prepend a `_Strong-signal threshold may be too loose — last 3 runs averaged {n} per week. Consider tightening the strong-vs-weak cutoff in references/1-expansion-signal-taxonomy.md._` warning. Do not silently truncate without flagging.
- **Signal-weighting drift.** Trigger phrases and SKU mappings go stale as the product changes. A new SKU that launched two months ago has zero entries in the taxonomy until someone adds them, and every signal for it is silently mis-routed. Guard: include the SHA-256 (first 7 chars) of `references/1-expansion-signal-taxonomy.md` in the diagnostics footer. If the file hasn't been touched in 90 days, prepend `_Taxonomy last edited 90+ days ago. Time to recalibrate against the current SKU lineup._`
- **Champion-departure misclassification.** A spike in usage right after the named champion leaves is an expansion-risk signal, not an expansion-intent signal — the new owner is exploring before deciding whether to keep the contract. Guard: cross-reference every strong signal against `stakeholder_changes`. If a champion on the account departed within the trailing 30 days, downgrade to weak and tag with `_champion-departure suppressed: investigate before pursuing._` The skill must NOT route an expansion ask to an account that just lost its champion.
- **Conditional-mention misclassification.** "We'd consider expanding if you supported X" reads as expansion intent on its face but is in fact a feature-gap report. Guard: the negative- example layer in step 3 explicitly classifies conditional phrases ("if," "would," "considering," "thinking about") as `not_signal`. Diagnostics expose how often this fires — if it never fires the layer is broken; if it fires constantly the SKU mapping needs rephrasing.
- **CSM call-coverage gap.** If CSMs aren't actually logging calls in Gong (or the equivalent), the call half of the signal set is empty and every signal collapses to weak. Guard: at the start of every run, compute `% of accounts with at least one logged call in the window` and prepend the digest with `_CSM call coverage: {pct}% of accounts had at least one logged call. Below 60% means most signals are usage-only._` Below 40%, abort the run with a coverage-error message rather than emit a half-signal digest.
- **Action specificity collapse.** Under load, the model defaults to generic "follow up on opportunity" suggestions. Guard: post- process the Action field with a literal substring check — if the action contains `follow up`, `reach out`, `touch base`, `align`, `socialize`, `engage` without a named person, meeting, or doc, replace with `needs human review`. Action library entries that pass this filter are the only acceptable shape.
# Expansion-signal taxonomy — TEMPLATE
> Replace these mappings with your actual SKU lineup and the trigger
> phrases / usage patterns your team has observed precede an upsell.
> The skill reads this file on every run; without your real taxonomy
> the digest output is generic and CSMs ignore it within two weeks.
## Strong-signal cutoff
A signal is classified **strong** only when at least one call mention AND at least one usage-event corroboration land on the same SKU within the run window. Anything else is **weak**. Edit this cutoff only after you have three weeks of digests showing repeated cases of genuine expansion that the strong-only filter missed.
## SKU map
For each SKU, list:
- **Call triggers** — verbatim phrase patterns the extraction prompt searches transcripts for. Be specific: "asked about pricing for more than 50 seats" not "asked about pricing."
- **Usage triggers** — pre-emitted anomaly types (from your usage warehouse) that count as evidence for this SKU.
- **Ticket triggers** — support-ticket subject / tag patterns that count as evidence (typically integration questions about premium features).
- **Negative-example phrases** — phrases that look adjacent but mean the opposite. The skill classifies these as `not_signal` rather than dropping silently.
### SKU: enterprise-tier (example)
- **Call triggers**:
- "do you support SSO" / "SAML" / "SCIM"
- "compliance requirements" / "SOC 2" / "HIPAA" / "FedRAMP"
- "asked about pricing for {N}+ seats" where N is at least 2x current seat count
- "our security team needs"
- **Usage triggers**:
- `tier_gated_feature_attempt` for SSO, audit-log, or RBAC features
- `seat_count_spike` over the segment baseline (see config)
- **Ticket triggers**:
- tags include `sso`, `compliance`, `security-review`
- subject matches `audit log`, `enterprise`, `compliance`
- **Negative-example phrases**:
- "we're going to need to drop down a tier"
- "your enterprise tier is too expensive"
- "we'd consider {feature} if it were on a lower tier"
### SKU: additional-team-seats (example)
- **Call triggers**:
- "the {team_name} team is also starting to use this"
- "rolling out to {N} more people"
- "our {team} would benefit from access"
- **Usage triggers**:
- `seat_count_spike` over baseline
- `feature_first_use` from a previously-inactive department (requires department tagging in usage events)
- **Ticket triggers**:
- subject contains `add users`, `new team`, `provisioning`
- **Negative-example phrases**:
- "we're consolidating teams onto fewer seats"
- "trying to figure out who actually uses this"
### SKU: premium-feature-pack (example)
- **Call triggers**:
- "does {premium_feature} support {use_case}"
- "we're trying to do {use_case} — is that on the roadmap"
- **Usage triggers**:
- `tier_gated_feature_attempt` for premium-pack features
- `api_call_spike` on premium-only endpoints
- **Ticket triggers**:
- tags include `premium-feature`, `api-limits`, `advanced-{feature}`
- **Negative-example phrases**:
- "we tried {premium_feature} and it didn't fit our use case"
- "we're using {competitor} for {use_case} instead"
### SKU: {your_next_sku}
(Add a section per SKU. The skill only routes to SKUs listed here.)
## Conditional-mention guard
The negative-example layer specifically catches conditional expansion mentions — phrases that sound like intent but are in fact feature-gap reports. The extraction prompt classifies any match containing both an expansion-shaped verb and one of the following conditional markers as `not_signal`:
- "if you {supported, added, built, shipped}"
- "would {consider, think about, look at} {expanding, upgrading}"
- "thinking about {upgrading, expanding, the enterprise tier}"
These are valuable product-feedback signals, but they belong in a roadmap-feedback channel, not a CSM expansion digest. Route them elsewhere if you want to capture them.
## Last edited
{YYYY-MM-DD}
# Segment baseline config — TEMPLATE
> Replace these baselines with values computed from your actual usage
> warehouse. The skill rejects usage anomalies whose `delta_pct` falls
> inside the segment's noise band even when the absolute value
> crossed the emitter's threshold. Without per-segment baselines,
> SMB noise drowns out enterprise signal.
## How baselines are used
For each `usage_event` ingested, the skill:
1. Looks up `account.segment` in this file.
2. Fetches the noise band (typically two-sigma around the segment median) for the event's `metric_name`.
3. If `delta_pct` falls inside the noise band, the event is discarded as noise even if it crossed the global emitter threshold.
4. If outside the band, the event is kept as a signal candidate and proceeds to the SKU mapping in step 3 of the method.
Edit one row at a time. Watch the next two digests before editing again — baselines that move every week train the team to ignore the output.
## Per-segment baseline table
Replace these placeholder values with values from a 90-day rolling window over your actual usage data.
### Segment: enterprise (example)
Typical: 200-1000+ seats, multi-year contract, dedicated CSM.
| Metric | Median weekly delta | Noise band (2σ) | Notes |
|-----------------------------|--------------------:|-----------------|---------------------------------------------|
| `seat_count` | +0.5% | ±3% | Enterprise plans tend to be flat-by-design |
| `daily_active_users` | +1.0% | ±8% | Vacation-week dips are normal |
| `api_calls` | +2.0% | ±15% | Spiky on integration release days |
| `tier_gated_feature_attempts` | 0 | ±0 (any > 0 is signal) | Crossing into a tier-gate is signal regardless of band |
### Segment: mid-market (example)
Typical: 50-200 seats, annual contract, shared CSM coverage.
| Metric | Median weekly delta | Noise band (2σ) | Notes |
|-----------------------------|--------------------:|-----------------|---------------------------------------------|
| `seat_count` | +1.5% | ±7% | Quarterly rollouts can produce one-off jumps |
| `daily_active_users` | +2.0% | ±12% | |
| `api_calls` | +3.5% | ±20% | |
| `tier_gated_feature_attempts` | 0 | ±0 (any > 0 is signal) | |
### Segment: smb (example)
Typical: 1-50 seats, monthly or annual contract, pooled CSM coverage.
| Metric | Median weekly delta | Noise band (2σ) | Notes |
|-----------------------------|--------------------:|-----------------|---------------------------------------------|
| `seat_count` | +5.0% | ±25% | Adding 1-2 seats is week-on-week normal |
| `daily_active_users` | +6.0% | ±30% | Highly variable |
| `api_calls` | +8.0% | ±40% | Often noisy due to integration tinkering |
| `tier_gated_feature_attempts` | 0 | ±0 (any > 0 is signal) | |
### Segment: {your_next_segment}
(Add a section per segment in your customer base.)
## Recompute cadence
Recompute the medians and noise bands from your usage warehouse on a quarterly basis. Append to the calibration log below so the next person editing this file can see why the numbers are what they are.
## Calibration log
Format: `YYYY-MM-DD — change — reason`.
- {YYYY-MM-DD} — initial baselines — placeholder, replace with values computed from a 90-day rolling window
## Last edited
{YYYY-MM-DD}
# Action library — TEMPLATE
> Replace these actions with the next-best actions your CSM team
> actually runs. The skill maps each strong signal to one entry in
> this library; entries that are vague ("follow up", "engage
> stakeholder") are rejected by the post-process filter described in
> the SKILL.md watch-outs section.
## Action shape
Every entry MUST follow the shape:
```
verb + named artifact (a meeting, a person, a doc, or a ticket)
```
Acceptable:
- "Send the SSO setup checklist to the security contact and propose a 30-min walkthrough this week."
- "Forward the Q3 roadmap deck to the new VP of Eng and ask for a 15-min reaction call."
- "Open a Gainsight CTA tagged `enterprise-tier-evaluation` and ping the renewal owner in the linked thread."
Not acceptable:
- "Follow up on the opportunity" (no named artifact)
- "Reach out about expansion" (no verb-and-artifact)
- "Engage the buying committee" (vague)
The skill enforces this with a literal substring check on the emitted Action field. Anything not from this library — or matching the vague-language denylist — is replaced with `needs human review`.
## SKU: enterprise-tier
| Trigger pattern | Next-best action |
|----------------------------------------------|------------------|
| Call mention of SSO/SAML/SCIM + tier-gated attempt | "Send the SSO setup checklist {link} to the security contact and propose a 30-min walkthrough this week." |
| Compliance language + ticket tagged `compliance` | "Forward the SOC 2 report {link} and the compliance one-pager {link} to the named compliance contact within 48 hours." |
| Seat-count spike at 2x baseline + pricing call mention | "Schedule a 30-min commercial conversation with the EB this week. Bring the enterprise-tier pricing sheet {link}." |
## SKU: additional-team-seats
| Trigger pattern | Next-best action |
|----------------------------------------------|------------------|
| Call mention of new team + seat-count spike | "Open a provisioning thread with the named admin and offer a 15-min onboarding for the new team this week." |
| `feature_first_use` from new department | "Send the {department} onboarding playbook {link} to the named admin and CC the new department's manager." |
## SKU: premium-feature-pack
| Trigger pattern | Next-best action |
|----------------------------------------------|------------------|
| Use-case question + tier-gated attempt | "Send the premium-feature one-pager {link} and book a 30-min product walkthrough with the asking persona this week." |
| `api_call_spike` on premium endpoints | "Open a Gainsight CTA tagged `premium-pack-evaluation` and ping the technical evaluator in the linked thread." |
## SKU: {your_next_sku}
(Add a section per SKU. Every SKU listed in the taxonomy file MUST have at least one matching trigger-action row here, or the skill will emit `needs human review` for every signal that maps to it.)
## Vague-language denylist
The post-process filter rejects any Action field containing the following substrings without an accompanying named artifact:
- `follow up`
- `reach out`
- `touch base`
- `align`
- `socialize`
- `engage`
- `circle back`
- `loop in`
- `start a conversation`
If a legitimate action needs one of these verbs, write the action with a named artifact attached (e.g. "Loop in the Solutions Engineer {name} on the next call to demo {feature}.").
## Last edited
{YYYY-MM-DD}