closedloop-skills

0

AI product discovery skills for Claude Code, powered by ClosedLoop AI. Deep-dive into any topic across your product insights—customer quotes, pain points, business impact, and competitive insights extracted from conversations.

21 skills

closedloop-bug-blast-radius

Answer how important a bug is: who reported it, how badly, what it is worth, and when it was last reported. Uses get_bug_blast_radius. Read only; reflects reported pain.

# ClosedLoop AI Bug Blast Radius Answer one engineering question: **how important is this bug?** This skill governs `get_bug_blast_radius` only. It reads. It writes nothing, notifies nobody, and calls no other tool. The API computes every number. Your job is governance, interpretation, and refusal — deciding which of the retrieved evidence actually describes this bug, saying what the numbers can and cannot support, and never inventing a value the tool did not return. ## Input One defect at a time, in the user's own words. ```text How bad is the saved-card checkout failure? Is the CSV export timeout worth fixing this sprint? Blast radius for the SSO redirect loop ``` Default the categories. Add `Integration Issue` when the bug is about a third-party sync, webhook, or connector — it is deliberately not in the default set, so an integration bug looks smaller than it is until you ask for it. Use `feature_area` when the user names one. Use `date_from` / `date_to` only when they ask about a window. ## Execute ```text get_bug_blast_radius( query="{the bug in plain language}", categories={["Bug","Performance Issue","Security Issue","UX/UI Issue"] or the user's set}, feature_area="{if named}", date_from="{if asked}", date_to="{if asked}", limit={default 25}, insight_limit={default 50} # by RELEVANCE; per-customer representatives are added on top ) ``` ## Read the evidence before reporting This is the step the tool cannot do and the reason it returns verbatim content. Read `insights[]`. Semantic retrieval pulls in adjacent complaints — a different bug in the same feature area, a feature request phrased as a failure, a duplicate of something already fixed. Name the ones that are a **different problem** and exclude their customers. Then report both numbers: > {total} customers reported this. I excluded {k} ({names}) whose evidence is about expired cards, not saved-card decline — {remaining} customers, {ARR after exclusion}. **Check `coverage.totals_decomposable` before you subtract anything.** - **`true`** — every matched customer is in `customers[]`, so dropping one subtracts exactly that customer's row. **Subtract, never recompute.** Do not re-call with a narrower query to "clean up" the number. - **`false`** — more customers matched than were returned, so the totals cover rows you never saw and cannot audit. **Do not subtract.** Report the census total as-is, say how many customers you were able to read, and name the ones you excluded without adjusting the headline. If the user needs a corrected figure, re-call with `limit` raised to 50; if it is still false at 50, say the bug is too widespread to correct by hand and give the census. Never silently drop a customer, and never keep one that plainly does not match in order to protect the headline. ## Present results ```text BUG BLAST RADIUS: {query} ========================= Exposure: {exposure_score}/100 Searched: {bug.categories_searched}{, feature_area} Reported by: {totals.customers_affected} customers, {totals.insights} insights Revenue: {totals.arr_affected} {totals.arr_currency} {if coverage.arr_includes_non_reporting_members: " of which {totals.arr_affected_reporting_members} is the members that actually reported"} Last reported: {totals.last_reported} ({trend.direction} over {trend.direction_window_days}d) RECOMMENDATION: {HOTFIX | NEXT SPRINT | BACKLOG} Rule: {the rule that fired, with the numbers that satisfied it} CUSTOMERS 1. {name} — {arr} {currency}, {insight_count} reports{, deal blocker}{, churn_state} {if reporting_member_count < member_count: "(chain: {reporting_member_count} of {member_count} members reported; their ARR is {reporting_arr})"} "{verbatim from the linked insight}" ... EXCLUDED AFTER READING THE EVIDENCE - {name}: {why this is a different problem} {if totals_decomposable is false: "Headline unchanged — N of M customers were returned, so the totals cannot be corrected by subtraction."} COVERAGE - {anything from the coverage block that bites} - Reflects reported pain only. Customers hitting this bug who did not contact you are not represented. ``` Recommendation thresholds, printed every time so the reader can disagree with the rule rather than the number: - **HOTFIX** — any deal blocker, or any Critical, still reported within 30 days. - **NEXT SPRINT** — `exposure_score >= 50`, or accelerating trend with more than one customer. - **BACKLOG** — everything else. ## Read the coverage block out loud when it bites - `insights_without_crm_link > 0` — the ARR is a **floor**, not a total. N more reports could not be attributed to a customer. - `window_predates_coverage` — say this **first**. The requested window starts before this team has any feedback, so an empty early period is missing coverage, not an absence of reports. - `customers_without_priced_deals > 0` — those customers are affected and contribute 0 to ARR. Zero ARR is not zero impact. - `arr_includes_non_reporting_members` — at least one counted customer is a family whose other members did **not** report, and the default `customer_scope: 'family'` rolls the whole family's ARR into `arr_affected`. That is the right answer to "what is this customer worth" and reads as an overstatement of "revenue affected". Print **both** figures and say which is which; never present `arr_affected` alone when this is true. One domain can map to thousands of companies, so the gap can be large. - `trend.direction` of `no_recent_reports` — nothing in either 14-day window. Say the bug has gone quiet and give `totals.last_reported`; do **not** call it steady, which reads as "still happening at a constant rate". - `customers_truncated` / `totals_decomposable: false` — more customers matched than were returned. The totals still cover all of them, but you cannot subtract from them; see above. - `keyword_matching_available: false` — the keyword query failed (a database error, not a missing credential). Say the search was semantic-only and the counts may be short. - `matched_insights_capped` — retrieval hit its bound, so the counts are a floor. This should be rare; when it fires, say the counts are a floor rather than a census. - `semantic_matching_available: false` — matching was keyword-only, so a report phrased differently was not found. Say this; it is not the same as "no such reports exist". - `keyword_terms_used: 0` — the query had fewer than two significant words, so keyword matching was skipped and only semantic matching ran. A single word names an area, not a bug: ask for the failure, or pass it as `feature_area`. - `feature_area_exists: false` — the area you filtered on does not exist for this team. The empty result is the filter, not an absence of reports. Suggest the real spelling or drop the filter. - `semantic_pool_capped` — the semantic candidate pool filled and its weakest member still cleared the bar, so more reports may qualify than were considered. Counts are a floor. - `semantic_floor` — the cosine cut applied to semantic matches. Report it if the user questions why something they expected is missing; it is published so the cut can be audited rather than trusted. ## Feedback To ClosedLoop AI If the data looks missing, stale, low-quality, or surprising, or the user says the customers, counts, revenue, or evidence are wrong or incomplete, explicitly invite them to send feedback about ClosedLoop AI. If they ask you to send it, use `closedloop-send-feedback` or call `send_closedloop_feedback(content=...)`. Keep the feedback about the ClosedLoop AI product/data experience, strip PII and customer-specific data, and do not treat it as customer evidence. ## Rules - Use only values returned by `get_bug_blast_radius`. Never infer a number it did not return. - If a field is absent, say it is absent. Never substitute a plausible value. - Never call write tools. This skill reads. - Say "N customers **reported** this", never "N customers are affected". - When ARR is 0, say "no priced deals resolved for these customers", never "no revenue at risk". - When `deal_blockers` is 0, say nothing about deal blockers. Marking is rare on defect rows, so absence is not evidence. - Never say a bug is fixed. State the last reported date and let the reader conclude. - Never estimate affected users, severity, or impact for a customer that returned none. - Quote evidence verbatim as returned. Do not paraphrase a quote into severity language. - `customer_name` / `customer_email` on an insight are for attribution ("reported by X at Acme"), never for outreach. This skill does not contact anyone; if the user wants to follow up, hand them the name and stop. - Always print which categories were searched, so a thin result names its own constraint. If the query looks integration-shaped and returned little, suggest re-running with `Integration Issue`. - If zero customers match, say the query matched nothing within the categories searched and suggest widening. Never report "no customers are affected". - Always surface the reported-pain-only caveat.

closedloop-case-study-scout

Scout case-study and customer-story candidates from ClosedLoop AI evidence. Use when marketing asks for named customer stories, ROI validation, deeper narrative candidates, or interview targets. Uses find_case_study_candidates. Does not send email or grant publication permission.

# ClosedLoop AI Case Study Scout Find customer-story candidates with enough evidence for a deeper story. This skill governs `find_case_study_candidates` only. It does not log permission requests. When the user chooses a candidate and wants to test approval, use `closedloop-proof-permissions`. ## Input Accept a topic, product area, value outcome, launch, segment, or broad case-study request. Examples: ```text Find case study candidates for reporting ROI. Who has enough evidence for a rollout story? Find customer stories around onboarding improvements. ``` Default `time_period_days` to 90 and `limit` to 10 unless the user specifies otherwise. ## Execute Call: ```text find_case_study_candidates( query="{topic if provided}", limit={limit}, time_period_days={time_period_days} ) ``` ## Present Results Use this structure: ```text CASE STUDY SCOUT: {topic or "recent proof"} last {time_period_days} days =========================================================================== TOP STORY CANDIDATES 1. {Person} - {Role}, {Customer account} Angle: {narrative_angle} Evidence depth: {evidence_depth} Missing proof: {missing_proof} Interview questions: - {interview_questions} Evidence: - "{verbatim}" - {date} Follow-up: {follow_up_actions[0].label} with {follow_up_actions[0].params} ``` ## Feedback To ClosedLoop AI If the data looks missing, stale, low-quality, or surprising, or the user says the story candidates are wrong or incomplete, explicitly invite them to send feedback about ClosedLoop AI. If they ask you to send it, use `closedloop-send-feedback` or call `send_closedloop_feedback(content=...)`. Strip PII and customer-specific details. ## Rules - Treat every candidate as a story lead, not approval to publish. - Validate metrics, attribution, and exact wording before publication. - Ask for participation first; final story approval comes later. - Never send customer email.

closedloop-competitor-gap

Competitive intelligence from your actual customer conversations. Shows what customers say about each competitor, where you're winning, where you're losing, and what's at stake commercially. Not desk research — real customer voice with deal context.

# /closedloop-competitor-gap Competitive intelligence from what your customers actually say in their calls and support tickets — not desk research, not review sites. Real voice, real quotes, real deal impact. ## Check ClosedLoop AI MCP is available Try calling `get_overview(time_range="all")`. **If the call fails or the tool is not found:** ``` ClosedLoop AI MCP is not connected. Use the endpoint that matches your ClosedLoop AI app URL: US (app.closedloop.sh) https://mcp.closedloop.sh EU (eu.app.closedloop.sh) https://eu.mcp.closedloop.sh Then add it with your agent (swap in your region's URL): Claude Code claude mcp add --transport http closedloop-ai <URL> then /mcp and authorize Codex CLI codex mcp add closedloop-ai --url <URL> then codex mcp login closedloop-ai Guide: https://closedloop.sh/docs/mcp-server/overview ``` Then stop. ## Input handling - No argument → full landscape with quarterly trends (default: last 4 quarters) - One competitor name → drill into that specific competitor - Two competitor names → head-to-head comparison - `monthly` / `weekly` → change the trend period (last 4 months or last 4 weeks) ``` /closedloop-competitor-gap → full landscape, quarterly trends /closedloop-competitor-gap monthly → full landscape, monthly trends /closedloop-competitor-gap Acme Corp → drill into Acme Corp /closedloop-competitor-gap Acme Corp vs Beta Inc → head-to-head ``` ## Execution ### Step 1: Get the landscape and compute time windows ``` get_competitors() ``` This returns all tracked competitors with total mention counts. Compute 4 time periods based on the user's granularity (default: quarterly): - **Quarterly** (default): Q-3, Q-2, Q-1, current quarter (e.g., Q3'25, Q4'25, Q1'26, Q2'26) - **Monthly**: M-3, M-2, M-1, current month - **Weekly**: W-3, W-2, W-1, current week Calculate the start/end dates for each period. These boundaries are passed to Agent 1 for per-period counting. ### Step 2: Launch 3 agents in parallel **Agent 1: Competitor signals + threat scoring + trend computation** For each competitor with mentions > 0: - `search_signals(type="competitor_mention", competitor_name="{name}", limit=50)` - `get_signal(id)` for every signal — read the full content For each signal, classify the INTENT: - **Evaluating**: customer is considering the competitor ("we're looking at X") - **Switching from**: customer came from this competitor ("we used to use X") - **Switching to**: customer is threatening to leave for this competitor ("we might move to X") - **Comparing features**: customer names a specific capability difference ("X does this but you don't") - **Frustrated with competitor**: customer complains about the competitor (opportunity for us) - **Praising competitor**: customer says competitor does something well (threat) **Count mentions per time period.** Using each signal's date, bucket into the 4 time windows computed in Step 1. This gives a 4-column trajectory per competitor. **Compute trend word** from the 4-period trajectory: - **accelerating**: increasing across 3+ periods, or sharp spike in latest period - **stable**: roughly flat (±20% variation across periods) - **cooling**: decreasing across 3+ periods - **new**: zero mentions before the latest 1-2 periods - **gone**: mentions only in older periods, none in the latest period Cross-reference with CRM data: - `search_customers(query="{customer_name}")` for each customer who mentioned a competitor - Get their deal value, deal stage, segment, churn risk status Compute a threat score per competitor: - Switching-to mentions weighted highest - Deal value of affected accounts - Churn risk flags on those accounts - Recency (recent mentions > old ones) - Trend direction (accelerating = higher threat) Write to `/tmp/competitor-analysis/signals.md`: - Ranked threat table with 4-period counts: competitor, P1, P2, P3, P4 (current), total, threat score, trend, top customer - Per-competitor: intent breakdown, affected customers with CRM data, all verbatim quotes **Agent 2: Feature gaps from feedback** - `search_insights(query="{competitor_name}", limit=30)` for each top competitor - `get_insight(id)` for each — read full content, especially `competitor_gap` field Also: - `search_signals(type="decision_criteria", limit=30)` — what customers evaluate when choosing - `search_signals(type="competitive_positioning", limit=20)` — how customers position you vs alternatives Group feature gaps by theme (pricing, integrations, UX, API, support, etc.) Write to `/tmp/competitor-analysis/gaps.md`: - Per-competitor feature gap list with customer quotes - Market-level decision criteria (not per-competitor) - Your advantages: where customers say you're better (from win reasons, value evidence) **Agent 3: Conversation context for highest-stakes mentions** For the top 3 most commercially impactful competitor mentions (highest deal value + switching-to or churn risk): - `list_conversations(customer_id="{id}", source_type="calls", limit=3)` - `get_conversation(id, source)` — load the transcript - Read the conversation around where the competitor was discussed Write to `/tmp/competitor-analysis/transcripts.md`: - Per conversation: customer name, deal value, 5-10 lines of actual dialogue around the competitor mention - Context: what was discussed before and after ### Step 3: Assemble the output Read all 3 files. Write the competitive intelligence brief. ## Output format ``` COMPETITIVE LANDSCAPE ===================== Based on {N} competitor mentions across {N} customers. Period: {granularity} ({P1 label} → {P4 label}) THREAT RANKING -------------- # Competitor {P1} {P2} {P3} {P4} Total Threat Trend 1. {name} {n} {n} {n} {n} {tot} HIGH cooling 2. {name} {n} {n} {n} {n} {tot} MEDIUM accelerating 3. {name} {n} {n} {n} {n} {tot} LOW stable ... {Competitors with 1-2 total mentions: one line, no drill} Top signal: {competitor} — "{intent}" from {customer} (${deal}) ================================================================================ {For top 3 competitors, auto-drill:} ## {Competitor Name} THREAT: {HIGH/MEDIUM/LOW} {Mentions}: {n} from {n} customers | Trend: {trend} ({P1}: {n} → {P4}: {n}) THREAT ASSESSMENT {2-3 sentence synthesis: what's happening with this competitor in your customer base. Who's talking about them, in what context, and what's at stake commercially.} WHAT THEY DO BETTER (from your customers' mouths) - {Feature gap}: "{verbatim quote}" -- {customer} ({deal value}) - {Feature gap}: "{quote}" -- {customer} {Group by theme if multiple gaps} WHAT WE DO BETTER - {Advantage}: "{verbatim quote}" -- {customer} - {Advantage}: "{quote}" -- {customer} {If no explicit win reasons found, note: "No explicit advantages cited against this competitor in the data."} WHO'S TALKING | Customer | Revenue | Stage | Intent | Quote | |----------|---------|-------|--------|-------| | {name} | ${rev} | {stage} | switching-to | "{short quote}" | | {name} | ${rev} | {stage} | comparing | "{short quote}" | FROM THE CALL {For the highest-stakes mention, show 5-10 lines of actual conversation:} > [timestamp] [EXT] {speaker}: {what they said about the competitor} > [timestamp] [INT] {your team}: {how they responded} > [timestamp] [EXT] {speaker}: {follow-up} ================================================================================ DECISION CRITERIA (market-level) -------------------------------- What customers evaluate when choosing — across all competitors: - {criterion}: cited by {n} customers. "{representative quote}" - {criterion}: cited by {n} customers. "{quote}" ... YOUR ADVANTAGES (across all competitors) ----------------------------------------- What customers say you do better than alternatives: - {advantage}: "{quote}" -- {customer} - {advantage}: "{quote}" -- {customer} {If no advantages found: "No explicit win reasons in the data. Consider running search_signals(type='win_reason') or search_signals(type='value_evidence') for positive evidence."} ================================================================================ ``` ## Feedback To ClosedLoop AI If the data looks missing, stale, low-quality, or surprising, or the user says the competitor evidence is wrong or incomplete, explicitly invite them to send feedback about ClosedLoop AI. If they ask you to send it, use `closedloop-send-feedback` or call `send_closedloop_feedback(content=...)`. Keep the feedback about the ClosedLoop AI product/data experience, strip PII and customer-specific data, and do not treat it as customer evidence. ## Rules - **Customer voice only.** Every claim must come from what a customer said, not from desk research about the competitor. If nobody mentioned a competitor's feature, don't invent it. - **Fact-Impact-Act.** For every gap: what was said (fact), why it matters commercially (impact), what to do about it (the reader decides the act — we provide the evidence). - **"What we do better" is mandatory.** Never produce a competitive brief that only shows weaknesses. If you can't find explicit advantages, say so — don't skip the section. - **Intent matters more than volume.** A handful of "switching-to" mentions from high-ARR accounts are more dangerous than many "comparing features" mentions from free-tier users. - **Thin evidence gets one line.** Competitors with 1-2 mentions appear in the threat table with their quote inline. No separate drill section. - **Trends as one word.** Accelerating / stable / cooling / new / gone. Computed from the 4-period trajectory, not just current vs previous. A competitor whose mentions rise across all four periods is "accelerating" even if the latest count seems low. - **Load transcripts selectively.** Maximum 3 transcripts total — only for deal blockers, churn risks, or the most vivid comparison moments. - **Anti-paranoia guardrail.** Every feature gap in the output should be traceable to a customer asking for it, not just a competitor shipping it. If customers don't care about a competitor's feature, it doesn't belong in this brief. - **120-150 lines.** Enough depth for the top 3 competitors plus landscape. Not a 50-page report. ## Data quality - Silently exclude automated/bot-generated insights - Deduplicate: same customer mentioning same competitor in same call = one mention, not N - Don't inflate mention counts with support ticket noise ## What this skill does NOT do - **Does not research competitors externally.** Only shows what YOUR customers say. For external research, the user can ask separately. - **Does not recommend "build this because competitor has it."** Shows the gap and the commercial impact. The PM decides if it's worth building. - **Does not compare feature-by-feature.** That commoditizes the conversation. Shows thematic gaps and advantages instead.

closedloop-csm-prep

90-second pre-call intelligence brief for CSMs and account managers. One opinionated headline, landmines, what changed, their top concerns in their own words, open threads, and how many other customers share the same pain. Not a data dump — a judgment call.

# /closedloop-csm-prep 90-second pre-call intelligence brief for CSMs and account managers. Walk into any customer call knowing the one thing that matters most, what was promised last time, and what landmines to avoid — without opening 5 tabs. ## Check ClosedLoop AI MCP is available Try calling `get_overview(time_range="all")`. **If the call fails or the tool is not found:** ``` ClosedLoop AI MCP is not connected. Use the endpoint that matches your ClosedLoop AI app URL: US (app.closedloop.sh) https://mcp.closedloop.sh EU (eu.app.closedloop.sh) https://eu.mcp.closedloop.sh Then add it with your agent (swap in your region's URL): Claude Code claude mcp add --transport http closedloop-ai <URL> then /mcp and authorize Codex CLI codex mcp add closedloop-ai --url <URL> then codex mcp login closedloop-ai Guide: https://closedloop.sh/docs/mcp-server/overview ``` Then stop. ## Input handling One argument: customer name or domain. The skill resolves it. ``` /closedloop-csm-prep Acme Corp /closedloop-csm-prep acme.com ``` If `search_customers(query="{input}")` returns multiple matches, show a numbered list and ask the user to pick one. If no match, say so and show the closest alternatives. ## Execution ### Step 1: Resolve the customer ``` search_customers(query="{input}") ``` Pick the match with the highest `insight_count`. Record `customer_id`, `name`, `domain`. ### Step 2: Launch 5 agents in parallel All agents receive the `customer_id` and `name`. **Agent 1: Profile + CRM + deals** - `get_customer(id)` — full profile, deals, contacts, feedback summary, strategic signals - Extract: company profile (industry, segment, country, employees), key contacts (top 5 by seniority), active deals (open only), won revenue, account owner Write to `/tmp/customer-prep/profile.md`: - Account snapshot line: name, segment, country, revenue, deal count - Key contacts: name, title (max 5) - Active deals: name, stage, amount, close date (max 3) - Account health numbers: insight_count, deal_blocker_count, account churn state (CRM: churned / at-risk / none), avg_frustration **Agent 2: Landmines (deal blockers + churn)** - `search_insights(customer_id="{id}", is_deal_blocker=true, limit=10)` — `get_insight(id)` for each - `search_signals(customer_id="{id}", type="churn_reason", limit=10)` — stated churn from this customer's own conversations — `get_signal(id)` for each - Account churn state comes from `get_customer(id)` (Agent 1): note if the account is CRM-flagged churned or at-risk For each deal-blocker insight, extract: title, severity, verbatim quote, reporter name, date. For each churn signal, extract: the churn reason, verbatim quote, speaker, date, urgency (if present). Deduplicate: if the same issue surfaces as both a deal blocker and a churn reason, show once with both labels. Write to `/tmp/customer-prep/landmines.md`: - Max 3 landmines, ranked by severity then recency - Each: label (DEAL BLOCKER / CHURN RISK), title, severity, verbatim quote, reporter, date **Agent 3: Recent feedback + what changed** - `search_insights(customer_id="{id}", sort="recency", limit=20)` - `get_insight(id)` for the top 10 by severity Group by topic/feature_area. For each topic: - Count of insights - Most vivid verbatim quote - Severity and frustration level - Date range (is this ongoing or a one-time mention?) Identify "what changed": insights from the last 30 days that represent NEW topics not present in older feedback. These are the deltas. Write to `/tmp/customer-prep/feedback.md`: - Top 3 concerns ranked by severity x frequency x recency - Each: topic, count, quote, speaker, date - "What changed" section: new topics from last 30 days only **Agent 4: Last 2 conversations + open threads** - `list_conversations(customer_id="{id}", source_type="calls", limit=5)` - `get_conversation(id, source)` for the 2 most recent calls — load full transcripts Read each transcript and extract: - What was discussed (3-5 key topics) - What the customer asked for - What was promised by your team (commitments, follow-ups, timelines) - Any unresolved questions or open items - Who was on the call Also check support: - `list_conversations(customer_id="{id}", source_type="support", limit=5)` - Read the 1-2 most recent support conversations if they exist Write to `/tmp/customer-prep/conversations.md`: - Per conversation: date, title, participants, 3-5 line summary - Open threads: list of unresolved items with who committed and when - Support context: any active support issues **Agent 5: Strategic signals + pattern context** - `search_signals(customer_id="{id}", limit=30)` — all strategic intelligence For strategic signals, group by type: - Satisfaction: most recent level and quote - Competitor mentions: which competitors, most recent quote - Decision criteria: what they evaluate - Churn signals: urgency and reason For pattern context — check if this customer's top 2-3 pain points are shared: - `search_insights(query="{top_concern_1}", limit=5)` — WITHOUT customer_id filter, to see how many OTHER customers report the same issue - `search_insights(query="{top_concern_2}", limit=5)` — same - `search_insights(query="{top_concern_3}", limit=5)` — same - From the `customers_mentioned` field in each response, count how many unique customers reported similar issues Write to `/tmp/customer-prep/strategic.md`: - Per signal type: most recent signal with quote (only types that have data) - Competitor context (only if mentioned in last 90 days) - Pattern context: "Their concern about {X} was also reported by {N} other customers including {names}" or "This concern appears specific to this account" ### Step 3: Assemble the brief Read all 5 files. Write the brief following the output format below. **The headline is written LAST** — after reading all evidence. It is an opinionated one-sentence judgment about this account's current state and the single most important thing to know. ## Output format ``` CUSTOMER PREP: {Company Name} {today's date} ========================================================================== {THE HEADLINE — one opinionated sentence. Not a summary of data. A judgment. What is the story of this account right now? What's the one thing that would change how you walk into this call? Examples: - "Stable {ARR} account but export reliability is eroding trust — {n} churn signals, all operational." - "New {ARR} deal at risk — they're evaluating a competitor and raised pricing twice in the last month." - "Happy power user with 3 expansion signals. This is a growth call, not a save call."} ACCOUNT {name} | {segment} | {country} | ${won_revenue} won | ${pipeline} open {insight_count} insights | {blocker_count} blockers | {churn: account churn state, or N stated-churn signals} Frustration: {interpreted level} | Last interaction: {date} CONTACTS {Name} — {Title} {Name} — {Title} {Name} — {Title} {max 5, most senior first} {If active deals exist:} DEALS {deal_name} — {stage} — ${amount} — closes {date} ================================================================================ LANDMINES {Only if deal_blockers > 0, or any stated-churn signal / CRM churn state exists. Otherwise omit entirely.} {DEAL BLOCKER / CHURN RISK}: {title} ({severity}) "{verbatim quote}" — {reporter}, {date} {Max 3. These are the things that could blow up in the call.} WHAT CHANGED (last 30 days) {Only new topics, usage shifts, or risk signals since last interaction. If nothing changed: "No new themes since last interaction on {date}."} - {New topic or change}: "{quote}" — {speaker}, {date} THEIR TOP CONCERNS (in their own words) {Top 3 topics ranked by severity x frequency x recency. Customer voice only.} 1. {topic} ({n} mentions, {severity}): "{most vivid verbatim quote}" — {speaker}, {date} 2. {topic} ({n} mentions): "{quote}" — {speaker}, {date} 3. {topic} ({n} mentions): "{quote}" — {speaker}, {date} LAST CONVERSATIONS {2 most recent. Summary, not transcript. What was discussed and what was left open.} {date} — {title} ({source}) {Who was there. What was discussed in 3-5 lines. What was promised. What's still open.} {date} — {title} ({source}) {Same format.} OPEN THREADS {Commitments from conversations that have not been resolved. Frame as preparation, not blame. "Committed Jan 15" not "OVERDUE 70 DAYS".} - {What was promised}: committed by {who} on {date} - {What was promised}: committed by {who} on {date} {If nothing is clearly open, omit this section.} PATTERN CONTEXT {Is this customer's pain unique or shared across the customer base?} "{top concern}": also reported by {N} other customers including {customer names}. "{second concern}": also reported by {N} other customers. {If unique: "This concern appears specific to this account."} {Only if competitor data exists in last 90 days:} COMPETITIVE {competitor_name}: mentioned {n} times. "{most recent quote}" — {date} ========================================================================== ``` ## Feedback To ClosedLoop AI If the data looks missing, stale, low-quality, or surprising, or the user says the prep is wrong or incomplete, explicitly invite them to send feedback about ClosedLoop AI. If they ask you to send it, use `closedloop-send-feedback` or call `send_closedloop_feedback(content=...)`. Keep the feedback about the ClosedLoop AI product/data experience, strip PII and customer-specific data, and do not treat it as customer evidence. ## Rules - **Never show raw frustration scores.** Interpret the 0-1 number into plain language: 0-0.2 = calm, 0.2-0.4 = mild frustration, 0.4-0.6 = moderate frustration, 0.6-0.8 = high frustration, 0.8-1.0 = extreme frustration. - **250-400 words.** This is a 90-second brief, not a report. If the output exceeds 50 lines, cut the weakest section. - **BLUF — headline first.** The headline is an opinionated judgment written LAST, shown FIRST. If the reader stops after one sentence, they have the most important thing. - **Evidence, not labels.** Show "3 open tickets, NPS dropped 8→4" not "Customer: Frustrated." Labels anchor and create bias. - **What changed, not everything.** If nothing is new in the last 30 days, say "stable" — don't rehash old themes. - **Customer voice only.** Every concern backed by a verbatim quote. No paraphrasing, no invented sentiment. - **3 concerns max.** Paradox of choice — 10 talking points means 0 get used. 3 means 2-3 get used. - **Open threads as preparation, not blame.** "Committed Jan 15" — never "OVERDUE" or "FAILED." - **Pattern context is mandatory.** Even if the answer is "unique to this account" — say so. This is the section no other tool provides. - **Omit empty sections.** No landmines? Skip the section entirely. No competitors? Skip it. No open threads? Skip it. The brief gets shorter for healthy accounts — that IS the signal. - **Thin accounts get short briefs.** If a customer has <5 insights and no calls, show the account snapshot + CRM data and note: "Limited feedback history. {N} insights on record." Don't pad. ## Data quality - Silently exclude automated/bot-generated insights - Deduplicate: same customer, same topic, same call = one mention - Support ticket noise (password resets, generic errors) doesn't count as a "concern" - If the same issue is both deal blocker and churn risk, count it once, label both ## What this skill does NOT do - **Does not replace the deep-dive.** Customer-prep is 90 seconds. For full evidence on a topic, run `/closedloop-deep-dive {topic}`. - **Does not build a persona.** For understanding how a customer thinks and talks, use `/closedloop-synthetic-customer {name}`. - **Does not prioritize across customers.** This is one customer's brief. For portfolio-level intelligence, use `/closedloop-weekly-brief`. - **Does not generate a slide deck or QBR doc.** It's a pre-call scan, not a presentation.

closedloop-customer-proof-outreach

Draft permission outreach for one selected marketing proof candidate returned by find_customer_proof. Use when the user chooses a customer proof candidate and wants a permission email for website, social, sales, case-study, or live-reference use. Uses prepare_customer_proof_outreach. Draft only; never sends messages or claims permission was granted.

# ClosedLoop AI Customer Proof Outreach Draft permission or participation outreach for one selected proof candidate. This skill requires a candidate returned by `find_customer_proof`. This skill governs `prepare_customer_proof_outreach` only. It does not search for candidates. ## Required Selection Use this skill only when the user has selected a proof candidate or provided the candidate's follow-up params. The call must include: - `account_id` - `proof_type` - one selected person identifier: `person_id`, `person_email`, or `person_name` Prefer the returned `usage_scope` from `follow_up_actions[0].params`. The supported usage scopes are: | Scope | Meaning | |---|---| | `website` | Public website quote, wall of love, homepage, testimonial page, or customer page. | | `sales` | Sales decks, follow-up emails, sales collateral, or prospect conversations handled by the vendor team. | | `case_study` | Interview, ROI validation, named customer story, or written/video case study. | | `live_reference` | Customer directly participates in reference activity such as an email intro, short call, webinar, analyst/media reference, or similar. | | `social` | A public social post quoting the customer, with their name and company attached. | If no selected candidate is available, ask the user to run `closedloop-customer-proof` first or to choose one candidate from the discovery results. ## Execute Prefer the selected candidate's returned action params: ```text prepare_customer_proof_outreach( ...follow_up_actions[0].params, sender_name="{sender name if provided}", user_role="{sender role if provided}" ) ``` If the user selected a candidate by description, pass the matching `account_id`, `proof_type`, and one person identifier from the discovery result. Do not draft for candidates that the tool rejects or marks as excluded. Summarize the rejection and ask the user to choose a non-excluded candidate. ## Present The Draft Use this structure: ```text CUSTOMER PROOF OUTREACH: {Person} - {Customer account} ======================================================= USAGE SCOPE {selected_candidate.usage_scope} ROUTE {route.label}: {route.reason} DRAFT CUSTOMER EMAIL To: {customer_permission_email.to} Subject: {customer_permission_email.subject} {customer_permission_email.body} INTRO REQUEST DRAFT {intro_request if returned, otherwise "Not needed for this route."} EVIDENCE USED - "{verbatim}" - {type}, {date} PERMISSION CAVEATS - {permission_caveats} WATCH-OUTS - {watch_outs or "none surfaced"} FOLLOW-UP QUESTIONS - {suggested_questions} ``` ## Feedback To ClosedLoop AI If the data looks missing, stale, low-quality, or surprising, or the user says the draft is wrong or incomplete, explicitly invite them to send feedback about ClosedLoop AI. If they ask you to send it, use `closedloop-send-feedback` or call `send_closedloop_feedback(content=...)`. Keep the feedback about the ClosedLoop AI product/data experience, strip PII and customer-specific data, and do not treat it as customer evidence. ## Rules - Draft only. Never send messages. - Preserve verbatim evidence exactly as returned. - Ask for permission or participation; do not imply public approval already exists. - For website use, ask for public quote/logo/name approval and attribution preference. - For sales use, ask for permission to reuse the quote in sales decks, follow-up emails, and prospect conversations handled by the vendor team. - For case-study use, ask for a short conversation before asking for final approval; validate metrics, baselines, and timeframes before publication. - For live-reference use, ask whether the customer is open to direct participation and confirm format, frequency, and opt-out expectations. - For social use, ask for permission to quote them in a public social post, confirm attribution and whether they want to be tagged, and offer to send the exact post before it goes out. - If permission is unknown, say it is unknown.

closedloop-customer-proof

Find marketing-ready customer proof from ClosedLoop AI evidence. Use when marketing, product marketing, sales enablement, CMO, CEO, or leadership asks for quotes, testimonials, case-study candidates, customer love, launch proof, ROI/value proof, adoption stories, social proof, or reference candidates. Uses find_customer_proof. Do not use for permission outreach drafts; hand selected candidates to closedloop-customer-proof-outreach.

# ClosedLoop AI Customer Proof Find customers and verbatim evidence that marketing can turn into proof: website quotes, testimonials, sales proof, case studies, launch quotes, customer love, ROI proof, adoption stories, social proof, or live reference candidates. This skill governs discovery only. It does not draft outreach. When the user chooses a candidate or asks for a permission email, use `closedloop-customer-proof-outreach`. The `proof_type` parameter is a marketing intent, not a raw evidence type. The tool ranks real ClosedLoop AI evidence including satisfaction, value evidence, adoption milestones, social proof, product-market-fit evidence, win reasons, and aha moments. ## Input Accept a topic, product area, feature, initiative, value theme, or broad proof request. Examples: ```text Find customer quotes about memberships. Find case study candidates for API exports. Find ROI proof for reporting from the last 180 days. Show recent customer love. ``` If no topic is provided, browse strongest recent proof. Map intent to `proof_type`: | User intent | `proof_type` | |---|---| | quote, testimonial, website quote | `website_quote` | | case study, story | `case_study` | | ROI, value, savings, business impact | `roi_proof` | | launch quote, release proof | `launch_quote` | | love, happy customers, praise | `customer_love` | | reference, logo, social proof | `social_proof` | | adoption, rollout, usage story | `adoption_story` | | unclear or broad request | `all` | Default `time_period_days` to 90 unless the user specifies a different window. Default `limit` to 50 unless the user asks for a different count. ## Execute When a topic is provided, call: ```text find_customer_proof( query="{topic}", proof_type="{proof_type}", limit={limit}, time_period_days={time_period_days} ) ``` When no topic is provided, call: ```text find_customer_proof( proof_type="{proof_type}", limit={limit}, time_period_days={time_period_days} ) ``` Do not manually stitch lower-level searches. The tool ranks candidates, joins person/account detail, returns verbatim evidence, recommends a usage scope, excludes inactive or unresolved customer accounts, and includes follow-up actions. The `recommended_usage_scope` values are: | Scope | Meaning | |---|---| | `website` | Public website quote, wall of love, homepage, testimonial page, or customer page. | | `sales` | Sales decks, follow-up emails, sales collateral, or prospect conversations handled by the vendor team. | | `case_study` | Interview, ROI validation, named customer story, or written/video case study. | | `live_reference` | Customer directly participates in reference activity such as an email intro, short call, webinar, analyst/media reference, or similar. | | `social` | A public social post quoting the customer, with their name and company attached. | If the tool returns no candidates, an explanation, warnings, excluded candidates, or suggested alternatives, summarize that response directly. Do not add assumptions or invent proof. ## Present Results Show strongest proof candidates first. Include only what helps the user act: - Person and customer account - Recommended usage scope and percentage scores - Suggested ask or recommended action - Why this is strong proof - 1-3 verbatim evidence excerpts - Permission status or permission caveat from the result - Warnings, exclusions, or caveats from the result - Follow-up action label and params when present Use this structure: ```text CUSTOMER PROOF: {query or "recent proof"} last {time_period_days} days ========================================================================== SUMMARY {N} usable proof candidates. Best fit: {quotes/case studies/ROI/etc.} TOP PROOF CANDIDATES 1. {Person} - {Role}, {Customer account} Best use: {recommended_usage_scope} ({usage_scope_scores}) Action: {recommended_action or suggested_ask} Why: {short evidence-based reason} Evidence: - "{verbatim}" - {date} - "{verbatim}" - {date} Permission: {permission status or "ask before public use"} Watch-outs: {warnings or "none surfaced"} Follow-up: {follow_up_actions[0].label} with {follow_up_actions[0].params} DO NOT USE PUBLICLY YET {Excluded candidates and reasons returned by the tool.} NEXT STEPS 1. Pick the strongest 3-5 candidates by usage scope and evidence specificity. 2. Ask for explicit permission before using any quote publicly. 3. For case studies, ask for a short discovery call before requesting approval. 4. For ROI proof, validate the metric with the customer before publishing. 5. Route PM design partner or beta requests to the product ambassador workflow. ``` ## Handoff To Outreach If the user chooses a candidate or asks for a draft, stop using this skill and use `closedloop-customer-proof-outreach`. Pass the selected candidate's `follow_up_actions[0].params` to `prepare_customer_proof_outreach`; those params include the recommended `usage_scope`. Add `sender_name` or `user_role` only when the user provides them. ## Feedback To ClosedLoop AI If the data looks missing, stale, low-quality, or surprising, or the user says the candidates are wrong or incomplete, explicitly invite them to send feedback about ClosedLoop AI. If they ask you to send it, use `closedloop-send-feedback` or call `send_closedloop_feedback(content=...)`. Keep the feedback about the ClosedLoop AI product/data experience, strip PII and customer-specific data, and do not treat it as customer evidence. ## Rules - Use this workflow for marketing proof, public evidence, sales enablement proof, and customer-love requests. - Keep customer proof separate from PM design partner, beta, workflow discovery, and product validation workflows. - Preserve verbatim evidence with every recommendation. - Treat willingness to advocate as askability, not permission. - Never imply public permission unless the result explicitly says permission is known. - Do not fabricate roles, relationship owners, permission, or customer willingness. - Do not draft outreach in this skill. Draft only through `closedloop-customer-proof-outreach`.

closedloop-deep-dive

Deep-dive into any topic against ALL customer evidence from ClosedLoop AI. Reads every matching insight and signal, looks up CRM data for affected customers, and synthesizes the complete picture — what customers say, how severe it is, what revenue is at stake, what competitors are doing, and what workarounds exist.

# /closedloop-deep-dive Deep-dive into any topic against all customer feedback, strategic intelligence, and CRM data from ClosedLoop AI. Reads everything. Synthesizes it. You decide what to do with it. ## When to use - "What do customers say about checkout flow?" - "Is there real demand for API rate limits?" - "What's the evidence around dashboard reliability?" - "Deep-dive into dashboard loading issues" - Validating a roadmap item before committing engineering time - Preparing evidence for a stakeholder discussion - Understanding a problem area before writing a spec ## Check ClosedLoop AI MCP is available Before doing anything, try calling `get_overview(time_range="all")`. **If the call fails or the tool is not found:** ``` ClosedLoop AI MCP is not connected. This skill needs it to access your customer feedback data. Set it up in 30 seconds — use the endpoint that matches your ClosedLoop AI app URL: US (app.closedloop.sh) https://mcp.closedloop.sh EU (eu.app.closedloop.sh) https://eu.mcp.closedloop.sh Then add it with your agent (swap in your region's URL): Claude Code claude mcp add --transport http closedloop-ai <URL> then /mcp and authorize Codex CLI codex mcp add closedloop-ai --url <URL> then codex mcp login closedloop-ai Full guide: https://closedloop.sh/docs/mcp-server/overview ``` Then stop. **If it succeeds:** Note total insights, customers, date range. If total insights = 0, tell the user to connect a data source first. If < 100, warn results may be incomplete. ## Input handling **If the user provides ONE topic:** Proceed directly to deep-dive. **If the user provides MULTIPLE topics:** Present them as a numbered list and ask which one to investigate first. After finishing one, ask "Want me to deep-dive the next one?" ## Deep-dive execution ### Step 1: Gather ALL matching evidence No limits. Get everything. **Search insights (product feedback):** ``` search_insights(query="{topic}", limit=100, sort="relevance") ``` If 100 results returned, paginate with offset=100 and continue until exhausted. **Search strategic signals:** ``` search_signals(query="{topic}", limit=100, sort="relevance") ``` Same pagination. ### Step 2: Read FULL details for every match For EVERY insight ID: `get_insight(id="{id}")` For EVERY signal ID: `get_signal(id="{id}")` Do NOT skip this. Search results return 300-char truncated previews. You need full verbatim content, pain_point, workaround, competitor_gap, entities_competitors, emotion, frustration_score, kano_category, job_statement, is_deal_blocker, and for signals: intelligence_type, competitor_name, churn_urgency, satisfaction_level, quantified_impact, signal_strength. (Stated churn comes only from signals: `churn_reason` signals read with `churn_urgency`.) Read in parallel batches to save time. ### Step 3: Look up CRM data for affected customers Collect all unique `customer_name` values from insights and signals. For each unique customer (or top 20-30 by mention count): `search_customers(query="{customer_name}", limit=1)` This returns data that `get_insight` does NOT include: - Company profile: industry, country, employee_count, annual_revenue, segment - Deals: amount, stage, is_won/is_closed, pipeline - Deal blockers, account churn state (churned / at-risk), frustration for this company From this compute: total revenue affected, won deal value, open pipeline at risk, industry breakdown, segment breakdown, size breakdown, geography. **If CRM data is sparse:** Say so. "CRM data not available for most customers. Revenue analysis not possible." ### Step 4: Load key conversations for full context After reading all insights and signals, identify the 3-5 most important ones (highest severity, deal blockers, stated churn, or most compelling quotes). For each: 1. `list_conversations(customer_name="{customer_name}", source_type="calls", limit=3)` — find the actual call where this was said 2. `get_conversation(id="{conversation_id}", source="{source}")` — load the full transcript Read the conversation around the relevant quote. This gives you: - What was discussed before and after — the full context - The back-and-forth between customer and your team - Other topics from the same call that may be related - The tone and urgency that a 1-sentence extraction can't capture Only do this for the top 3-5 insights. Loading every transcript would be excessive — the extracted insights cover most of the picture. The transcripts add depth where it matters most. ### Step 5: Read everything, THEN write Do not start writing after reading 10 insights. Read ALL of them first — insights, signals, CRM data, and the key transcripts. The synthesis quality depends on seeing the full picture. ## Output format Lead with synthesis. Evidence supports, not leads. ``` DEEP DIVE: {Topic} =================== THE REAL PROBLEM ---------------- {3-5 sentence synthesis written AFTER reading ALL evidence. What is the underlying pain? Why does it matter? How do different customers experience it? If there are distinct sub-problems, name them here.} {If sub-problems exist:} This breaks into {N} distinct sub-problems: 1. **{Sub-problem}** ({N} customers): {one sentence} 2. **{Sub-problem}** ({N} customers): {one sentence} ... EVIDENCE STRENGTH ----------------- {exact number} insights + {exact number} signals from {exact number} customers Data range: {earliest date} to {most recent date} Trend: {growing/stable/declining} ({last 60 days count} vs {prior 60 days count}) {If < 10 customers: "Limited evidence -- may be noise, not a pattern."} {If > 50 customers: "Broad evidence across the customer base."} Severity: {exact counts} Critical, {n} High, {n} Medium, {n} Low Deal blockers: {n} ({customer names and deal amounts if known}) Stated churn: {n} churn_reason signals ({customer names if known}; urgency: {n} immediate, {n} considering) Avg frustration: {interpreted level, e.g. "moderate" or "high"} REVENUE IMPACT -------------- {Only if CRM data exists. If not, say "CRM not connected -- no revenue data."} Won revenue from affected customers: ${amount} across {n} companies Open pipeline at risk: ${amount} from {n} companies {List top 5 affected accounts: name, revenue, segment, what they said} {If no CRM: skip this section entirely, don't show empty fields} WHAT CUSTOMERS SAY ------------------ {Group by sub-theme if they exist. For each theme, show 3-5 most compelling verbatim quotes with attribution.} **{Sub-theme}** ({n} customers) - "{Exact verbatim quote}" -- {customer_name} ({segment/industry/size if known}) - "{Exact verbatim quote}" -- {customer_name} - "{Exact verbatim quote}" -- {customer_name} {and {N} more said similar things} **{Another sub-theme}** ({n} customers) - ... FULL CONVERSATION CONTEXT ------------------------- {For the 2-3 most critical insights (deal blockers, stated churn, or most vivid quotes), show a longer excerpt from the actual conversation transcript. This gives the reader the back-and-forth, not just the extracted quote.} **{customer_name}** ({source}, {date}): > {3-5 lines of the actual conversation around the key moment, > including what was said before and after. Speaker labels included.} {If no transcripts were loaded, omit this section entirely.} WORKAROUNDS ----------- {What customers do today. Workarounds = the problem is real enough to invest effort. No workaround = either not critical or truly blocking.} - {customer}: "{what they do}" - {customer}: "{what they do}" {If none: "No workarounds mentioned."} COMPETITIVE CONTEXT ------------------- {Only if competitors are mentioned in the evidence.} - {Competitor}: mentioned by {n} customers. "{what they say}" - ... {Decision criteria customers cite, if present} {If none: "No competitors mentioned in this context."} STRATEGIC SIGNALS ----------------- {Group by type. Only show types that have matches.} Satisfaction ({n}): "{quote}" -- {customer} Stated churn ({n} churn_reason): "{quote}" -- {customer} ({churn_urgency}) Decision criteria ({n}): "{quote}" -- {customer} Competitor mentions ({n}): "{quote}" -- {customer} CUSTOMERS AFFECTED ------------------ | Customer | Revenue | Segment | Industry | Mentions | Deal Blocker | Deals | |----------|---------|---------|----------|----------|--------------|-------| | {name} | ${rev} | {segment} | {industry} | {n} | {yes/no} | {stage} | | ... | WHAT WE DON'T KNOW ------------------- {Explicitly call out evidence gaps. This builds trust.} - {e.g., "No closed-lost deals attributed to this -- unclear if deals were lost or if attribution is missing"} - {e.g., "No product usage data -- we know what customers SAY but not how they USE the feature"} - {e.g., "Evidence is 80% from support tickets -- may overrepresent frustrated users vs. satisfied ones"} ``` ## What this skill does NOT do - **Does not prioritize.** We only see one topic. Can't rank it against things we haven't investigated. Run deep-dives on multiple topics and compare. - **Does not score or grade.** The customer count and the deal blockers behind a topic ARE the score. - **Does not recommend build/don't build.** We show evidence. You weigh it against engineering cost, strategy, capacity, and everything else we can't see. ## What this skill DOES do - **Shows everything.** Every matching quote, signal, and data point. - **Synthesizes.** Reads all evidence, writes what the real underlying problem is, groups by sub-themes. - **Adds revenue and CRM context.** Looks up every affected customer — revenue, deals, segment, industry, size. - **Surfaces what's hidden.** Workarounds, competitor mentions, churn signals, deal blockers — things only visible when you read ALL evidence together. - **Is honest about gaps.** Calls out what the evidence doesn't cover. ## Feedback To ClosedLoop AI If the data looks missing, stale, low-quality, or surprising, or the user says the evidence is wrong or incomplete, explicitly invite them to send feedback about ClosedLoop AI. If they ask you to send it, use `closedloop-send-feedback` or call `send_closedloop_feedback(content=...)`. Keep the feedback about the ClosedLoop AI product/data experience, strip PII and customer-specific data, and do not treat it as customer evidence. ## Data quality: clean before you count When reading insights, silently exclude noise and report only real human feedback: - **Automated/bot-generated insights:** If you see insights where the reporter is an email address (not a person name), the content is a system error template repeated identically across many entries, or the same error message appears 10+ times with only a product ID changed — exclude these from your counts and analysis. - **Over-extracted calls:** If you find 10+ insights from the same speaker in the same call that are clearly variations of 3-4 topics, count them as the distinct topics, not the raw insight count. - **Don't mention the noise.** Just present the clean picture. ## Guidelines - **Never show raw frustration scores.** Interpret the 0-1 number into plain language: 0-0.2 = calm, 0.2-0.4 = mild frustration, 0.4-0.6 = moderate frustration, 0.6-0.8 = high frustration, 0.8-1.0 = extreme frustration. - **Read everything before writing anything.** Synthesis quality depends on the full picture. - **Quote verbatim.** Exact customer words. Never paraphrase. - **Attribute every quote.** Customer name + company context if CRM data available. - **Use exact numbers.** Never "45+" — say "47." Precision builds trust. - **Group intelligently.** Many insights about the same thing? Pick 3-5 best quotes, note "and {N} more said similar things." - **Flag contradictions.** Some customers want X, others don't? Call it out. - **Note source distribution only if it reveals something.** Mostly from support = support burden. Mostly from sales calls = prospect blocker. If the split is unremarkable, skip it. - **Be honest about thin evidence.** 2 customers? Say "limited evidence." - **Be honest about missing data.** No CRM? Say so. Don't show empty sections. - **Never fabricate.** Only present what MCP tools return. - **Synthesis first, data second.** "THE REAL PROBLEM" is the most important section. It goes at the top.

closedloop-pm-prep

Pre-call discovery brief for product managers. Not account health — learning goals, knowledge gaps, data-grounded questions, and whether this customer's pain is a market signal or an outlier. Turns a customer call into a research instrument.

# /closedloop-pm-prep Pre-call discovery brief for product managers. Not "here's what this customer said before" — but "here's what you can learn from this call, what you already know from other customers, and what questions to ask." ## Check ClosedLoop AI MCP is available Try calling `get_overview(time_range="all")`. **If the call fails or the tool is not found:** ``` ClosedLoop AI MCP is not connected. Use the endpoint that matches your ClosedLoop AI app URL: US (app.closedloop.sh) https://mcp.closedloop.sh EU (eu.app.closedloop.sh) https://eu.mcp.closedloop.sh Then add it with your agent (swap in your region's URL): Claude Code claude mcp add --transport http closedloop-ai <URL> then /mcp and authorize Codex CLI codex mcp add closedloop-ai --url <URL> then codex mcp login closedloop-ai Guide: https://closedloop.sh/docs/mcp-server/overview ``` Then stop. ## Input handling Always starts with a company name. Person selection happens in a second step. ``` /closedloop-pm-prep Acme Corp ``` The skill resolves the company, runs the full brief, and shows a numbered contact list at the end. The user can then pick names to get per-person prep added. If `search_customers(query="{input}")` returns multiple matches, show a numbered list and ask the user to pick one. If no match, say so. ## Execution ### Step 1: Resolve the customer and get the baseline ``` search_customers(query="{input}") get_overview(time_range="all") ``` Pick the match with highest `insight_count`. Record `customer_id`, `name`, `segment`, `industry`. From overview, record `unique_customers` — this is the denominator for relative positioning. ### Step 2: Launch 5 agents in parallel **Agent 1: What they're trying to do (workflow + outcomes + workarounds)** - `get_customer(id)` — full profile, feedback summary, strategic signals - `search_insights(customer_id="{id}", sort="recency", limit=20)` — recent feedback - `get_insight(id)` for the top 10 — read full content For each insight, extract: - The **underlying need** (not the feature request). Reframe: "requested Slack integration" → "needs alerts without switching tools" - Any **workarounds** described — these prove the need is real. Note the sophistication: spreadsheet hack (mild) → custom tool (critical) → hired a person (budget exists) - The **emotion** and **frustration score** — high usage + high frustration = trapped customer - Group by underlying need/theme, not by category Write to `/tmp/pm-prep/workflow.md`: - Top 3-5 underlying needs, each with: the need (outcome-framed), evidence count, most vivid quote, workarounds if any, frustration level - Feature requests translated to outcomes - Workarounds listed separately with sophistication level **Agent 2: What we know from others (relative positioning)** For the customer's top 3 concern topics (from Agent 1's themes): - `search_insights(query="{topic_1}", limit=5)` — WITHOUT customer_id filter - `search_insights(query="{topic_2}", limit=5)` — WITHOUT customer_id filter - `search_insights(query="{topic_3}", limit=5)` — WITHOUT customer_id filter From each response, extract `customers_mentioned` — count unique companies. Also get the platform's top concerns for comparison: - `search_insights(sort="severity", limit=5)` — what are the most severe issues across all customers? - `get_facets(dimension="feature_area")` — what are the biggest feature areas by volume? Write to `/tmp/pm-prep/patterns.md`: - For each of the customer's top concerns: - How many OTHER customers reported similar issues (from `customers_mentioned`) - What percentage of the total customer base that represents (using `unique_customers` from overview) - Rank: is this in the top 5 platform-wide? Top 20? Not in the top 20? - Name 2-3 other customers who share the same concern - Summary: "Their concerns are [typical for the platform / concentrated in their segment / unique to this account]" **Agent 3: Segment lens** - `search_customers(segment="{customer_segment}", limit=10, sort="insight_count")` — find peers in same segment - `search_insights(query="{segment_name}", limit=10)` — what does this segment talk about? For the top 5 segment peers: - What are their top concerns? Do they match this customer's concerns? - What's the segment's average frustration? How does this customer compare? Write to `/tmp/pm-prep/segment.md`: - Segment name, total customers in segment, total insights from segment - Top 3 segment-level concerns (the things most customers in this segment raise) - Where this customer aligns vs. diverges from segment peers - "This customer is [typical of / an outlier in] their segment because..." **Agent 4: Last 2 conversations (for open threads and voice)** - `list_conversations(customer_id="{id}", source_type="calls", limit=5)` - `get_conversation(id, source)` for the 2 most recent calls Read each transcript and extract: - What the customer was TRYING TO DO (the job, not the complaint) - What questions they asked (reveals what they're evaluating) - What they said about their own workflow and internal context - Workarounds they described - Competitors or alternatives they mentioned - Emotional moments (frustration, excitement, resignation) - Open threads: things promised but not confirmed as resolved Write to `/tmp/pm-prep/conversations.md`: - Per call: date, title, participants, what the customer was trying to accomplish, key quotes showing their voice - Open threads with who committed and when - Workarounds described in the calls **Agent 5: Strategic signals + competitive context** - `search_signals(customer_id="{id}", limit=30)` — all strategic intelligence - For churn signals, competitor mentions, satisfaction: `get_signal(id)` for the most important ones Write to `/tmp/pm-prep/strategic.md`: - Satisfaction signals (if any): level and quote - Competitor mentions: which competitors, what the customer said about them, and — critically — what UNDERLYING NEED the competitor mention reveals (not just "they mentioned X") - Decision criteria: what they evaluate when choosing - Churn signals: what's driving risk (is it product gaps or operational issues?) **Agent 6: Per-person deep profiles (runs ONLY after user picks names)** This agent does NOT run during the initial brief. It runs when the user responds to the WHO'S ON THE CALL section by picking names. When triggered, launch one agent per selected person (in parallel). Each agent builds a **mini pm-prep brief scoped to one human** — not a summary card. For each named person: - `search_insights(customer_id="{id}", query="{person_name}", limit=30)` — find ALL insights reported by this person - `get_insight(id)` for every result — read full content - `list_conversations(customer_id="{id}", source_type="calls", limit=15)` — find all calls - `get_conversation(id, source)` for the 2-3 most recent calls where this person spoke — read full transcripts - `search_insights(customer_id="{id}", query="{person_name}", date_from="{30_days_ago}", limit=10)` — recent insights for "what changed" For each person, extract a FULL profile: **Last call analysis:** - What did THIS person specifically raise, ask, and commit to on their most recent call? - What was discussed that's still open? - Not a one-liner — the full picture of their participation **What changed since their last call:** - New insights from them or about their topics since that call date - Open threads that resolved or didn't - New topics they hadn't raised before **3-month trend:** - Are their concerns escalating, stable, or cooling? - Are they raising new topics or repeating the same ones? - Is their frustration level increasing, flat, or decreasing? - Mention count by month (e.g., "Mar: {n}, Feb: {n}, Jan: {n} — escalating") **All open threads for this person:** - What was promised TO them (by your team) - What THEY committed to do - Status of each: resolved, unknown, still open **Their workarounds:** - What do they personally cope with? - Sophistication level of each workaround **Their recurring questions:** - What questions do they keep asking across calls? Recurring questions reveal what they're evaluating or what remains unsolved. **Their voice — verbatim quotes organized by topic:** - Not 1 quote. Their 5-8 most characteristic quotes across topics. - Organized by theme, with dates. **Communication style and decision role:** - How they talk, how they decide, who they defer to, who defers to them **Knowledge boundary:** - Topics active at the company level that this person has NEVER mentioned - This tells the PM what NOT to ask this person about **Tailored questions (3-5):** - Must-ask (2): from their open threads and last call - Should-ask (1-2): from their trend or knowledge gaps about their domain - All Mom Test compliant, traceable to their specific data ### Step 3: Assemble the brief Read all agent files (5 if no names, 6 if names provided). Write the brief following the output format. **The learning goal is written LAST** — after reading all evidence. It frames what this specific call could teach the PM that they don't already know. ## Output format ``` PM PREP: {Company Name} {today's date} ========================================================================== LEARNING GOAL {What can this call teach you? Written LAST, after reading all evidence. Frame as a hypothesis to test or a knowledge gap to fill. Examples: - "{N} customers report dashboard crashes but we don't know if the manual spreadsheet workaround is acceptable or deal-breaking. This call can answer that." - "This customer asked for custom reporting with external data — 3 others mentioned similar needs. Test whether the underlying job is 'build executive dashboards' or 'automate compliance reports.'" - "New CSV export bugs appeared this week. This customer was affected. Learn whether this blocks a core workflow or is an edge case."} WHAT THEY'RE TRYING TO DO {Their underlying needs, reframed as outcomes. Not feature requests.} 1. {Outcome-framed need} ({n} mentions, frustration: {interpreted level}) "{verbatim quote}" — {speaker}, {date} {If workaround exists: "Workaround: {description} ({sophistication})"} 2. {Outcome-framed need} ({n} mentions) "{quote}" — {speaker}, {date} 3. {Outcome-framed need} ({n} mentions) "{quote}" — {speaker}, {date} {Max 5. Grouped by underlying job, not by category.} WHAT WE KNOW FROM OTHERS {Adaptive relative positioning. No fixed thresholds.} | Their concern | Other customers | % of base | Platform rank | |---|---|---|---| | {need 1} | {n} of {total} | {%} | #{rank} | | {need 2} | {n} of {total} | {%} | #{rank} or "not in top 20" | | {need 3} | {n} of {total} | {%} | #{rank} or "not in top 20" | {Interpretation: "Their top 2 concerns are the platform's top 2 concerns. Their third concern is niche — only {n} customers, likely edge case." Or: "All 3 concerns are unique to this account — outlier, not pattern."} WHAT WE DON'T KNOW {Knowledge gaps this call could fill. The highest-value section.} - {Gap 1}: "{What we've heard from others but don't know about THIS customer, or what we've heard from this customer but lack context for}" - {Gap 2}: "{A contradiction in evidence, or a topic where data is thin}" - {Gap 3}: "{An assumption the PM holds that hasn't been tested}" {Max 3. Each should be answerable in a single conversation. If there are no clear gaps: "Strong evidence base on this customer. Use this call to validate or challenge existing understanding."} SUGGESTED QUESTIONS {Data-grounded. Mom Test compliant. Past behavior, never hypothetical.} Must-ask: - "{Question generated from open thread or landmine data}" - "{Question generated from the top knowledge gap}" Should-ask: - "{Question generated from cross-customer pattern}" - "{Question about a workaround or workflow}" If-time: - "{Forward-looking question about underlying need}" {5-7 total. Every question traceable to a specific data point. Never "would you use X?" Always "walk me through the last time..."} THEIR VOICE {2-3 verbatim quotes that capture how this customer talks and thinks. Organized by underlying need, not category. Include emotional moments.} On {topic}: "{vivid quote showing their perspective}" — {speaker}, {date} On {topic}: "{quote showing frustration or excitement}" — {speaker}, {date} WHO'S ON THE CALL? {Always shown at the end of the initial brief. Lists known contacts with their insight count and top topics so the PM can pick names.} Known contacts at {company}: {Numbered list of ALL known contacts with insights, sorted by insight count. Each line: number, name, title, insight count, top 2 topics.} Pick names for per-person prep — use numbers or first names from the list above: ========================================================================== ``` ### When the user picks names — output per-person briefs (~30-40 lines each): The agents compute full dossiers. The output balances depth with scannability. ``` ========================================================================== {NAME} — {Title} {decides/recommends/executes} ========================================================================== LAST CALL ({date}) {What THIS person raised, asked, and committed to. 4-6 lines covering their topics, their questions, what's still unresolved. Not a one-liner but not a transcript either.} WHAT CHANGED SINCE {New activity from them or about their topics since that call. Open threads that resolved or didn't. 2-4 lines. If nothing: "No new activity since {date}."} 3-MONTH TREND {month}: {n} insights | {month}: {n} | {month}: {n} — {direction} {One line: are they escalating, stable, cooling? New topics or repeating?} THEIR CONCERNS (top 3, with quotes) {Topic 1}: "{most vivid quote}" — {date} {Topic 2}: "{quote}" — {date} {Topic 3}: "{quote}" — {date} OPEN THREADS - {What was promised or committed}: {status} ({date}) - {Another thread}: {status} WORKAROUND: {their most notable workaround with sophistication level} WON'T KNOW ABOUT: {company-level topics they've never mentioned} ASK {FIRST NAME}: - "{Must-ask from open threads or last call}" - "{Should-ask from trend or knowledge gap}" - "{If-time from workaround or forward-looking}" ========================================================================== {Repeat for each selected person. Max 3 people.} Type "more on {first name}" for full dossier: all quotes by topic, recurring questions, style analysis, and detailed knowledge boundary. EXPLORE MORE - "{Suggestion 1 — a relevant follow-up using /closedloop-deep-dive}" - "{Suggestion 2 — a relevant follow-up using /closedloop-synthetic-customer}" - "{Suggestion 3 — a relevant follow-up using /closedloop-competitor-gap}" {3 suggestions grounded in what was discovered during THIS brief. Each shows the exact command to run. Never use hardcoded topic examples in this template — generate from the actual data at runtime.} ``` ## Output format (continued) ``` SEGMENT LENS {Where this customer sits relative to peers in their segment.} Segment: {name} ({n} customers) Segment's top concerns: {topic 1}, {topic 2}, {topic 3} This customer [aligns with / diverges from] segment peers: - {How they're typical or atypical, with specific evidence} {Only if competitor data exists:} COMPETITIVE CONTEXT {What the competitor mention REVEALS about the customer's underlying need.} {competitor}: mentioned in context of {underlying need}. "{quote}" — {date} {What this tells the PM: "They're not evaluating a competitor — they're looking for {capability} that happens to exist in {competitor}."} ========================================================================== ``` ## Feedback To ClosedLoop AI If the data looks missing, stale, low-quality, or surprising, or the user says the prep is wrong or incomplete, explicitly invite them to send feedback about ClosedLoop AI. If they ask you to send it, use `closedloop-send-feedback` or call `send_closedloop_feedback(content=...)`. Keep the feedback about the ClosedLoop AI product/data experience, strip PII and customer-specific data, and do not treat it as customer evidence. ## Rules - **Never show raw frustration scores.** Interpret the 0-1 number into plain language: 0-0.2 = calm, 0.2-0.4 = mild frustration, 0.4-0.6 = moderate frustration, 0.6-0.8 = high frustration, 0.8-1.0 = extreme frustration. - **Learning goal, not headline.** The brief opens with what the PM can learn, not what the account looks like. Written last, shown first. - **Outcomes, not features.** Every customer request is reframed as the underlying need. "Requested CSV export" → "Cannot incorporate data into existing reporting workflows." - **Adaptive positioning.** Show rank and percentage against the full customer base. Never use fixed thresholds like "10+ = market signal." The rank tells the story. - **Knowledge gaps are mandatory.** Even if well-understood, say "strong evidence base — use this call to validate." The section is never skipped. - **Questions come from data.** Every suggested question traces to a specific insight, signal, open thread, or knowledge gap. No generic templates. - **Mom Test compliant.** All questions ask about past behavior, never hypothetical future. "Walk me through the last time..." not "Would you use...?" - **Workarounds = gold.** Always surface workarounds with their sophistication level. They prove the need is real and indicate willingness to pay. - **Segment context prevents bias.** Show where this customer sits vs. peers so the PM doesn't over-index on one voice. - **Competitor mentions decoded.** Don't just say "they mentioned X." Say what underlying need the mention reveals. - **People, not companies.** The brief always ends with a contact list. When the user picks names, run Agent 6 and show per-person profiles with tailored questions, communication style, and knowledge boundaries. - **Knowledge boundaries per person.** Show what each person has NOT discussed — it tells the PM where this person's expertise stops and someone else's starts. - **Two-step flow.** First run: company brief + contact list. Second run (after user picks names): per-person profiles. Never try to parse person names from the initial input — always resolve company first, then ask. - **250-400 words for initial brief.** Per-person follow-up is a full mini-brief per person — as deep as needed. No artificial word limit on per-person sections. - **Omit empty sections.** No competitor data? Skip it. No strategic signals? Skip it. Thin accounts get shorter briefs. ## Data quality - Silently exclude automated/bot-generated insights - Deduplicate: same customer, same topic, same call = one mention - When counting "other customers" for relative positioning, count unique companies, not mention volume - Support ticket noise doesn't count as a "concern" for the PM brief ## What this skill does NOT do - **Does not show account health, renewal dates, or deal status.** That's `/closedloop-csm-prep`. - **Does not replace the deep-dive.** For full evidence on a topic, run `/closedloop-deep-dive {topic}`. - **Does not build a persona.** For understanding how a customer thinks, use `/closedloop-synthetic-customer {name}`. - **Does not generate a spec or PRD.** It's pre-call prep, not a planning document. - **Does not tell the PM what to build.** It shows what customers need. The PM decides.

closedloop-product-ambassador-outreach

Draft product ambassador outreach from a selected ClosedLoop AI product ambassador candidate. Use after a customer candidate has been selected from find_product_ambassadors, especially when the user asks to draft an email, ask for an intro, invite a customer to beta validation, request design partner feedback, or prepare product validation outreach. Uses prepare_product_ambassador_outreach. Do not use for finding candidates, marketing quotes, testimonials, public proof, references, case studies, or customer-love requests.

# ClosedLoop AI Product Ambassador Outreach Draft grounded outreach for one selected product ambassador candidate. This skill assumes a candidate has already been selected from product ambassador results. It drafts outreach only; it does not send messages. ## Input Use this skill when the user asks to contact, email, invite, or prepare outreach for a selected product ambassador candidate. Examples: ```text Draft outreach for candidate 2. Write the email to invite Jane as a beta user. Prepare an intro request for the selected design partner. Turn this ambassador candidate into an outreach draft. ``` If no candidate has been selected, ask the user to select one from the product ambassador results, or use the product ambassador workflow first. ## Prepare Outreach Prefer the selected candidate's returned `follow_up_actions` parameters. If those are unavailable, use identifiers returned for the selected candidate and account. Call: ```text prepare_product_ambassador_outreach( pm_feature_id="{from_follow_up_action_or_selected_result}", account_id="{from_follow_up_action_or_selected_result}", person_id="{selected_person_id_if_available}", person_email="{selected_person_email_if_available}", person_name="{selected_person_name_if_available}", desired_use="{recommended_use_if_available}", time_period_days={time_period_days_if_available}, sender_name="{sender_name_if_known}", user_role="{user_role_if_known}" ) ``` At least one selected person identifier is required. If the selected result does not provide enough information to call the tool, tell the user the outreach draft cannot be prepared from the available result. If the tool returns an explanation, warning, or missing-data note, summarize it directly. Do not add assumptions or invent outreach. ## Present Results Include only what helps the user act: - Recommended route - Draft customer email - Draft internal intro request if returned - Evidence used - Questions to ask - Guardrails, missing data, or caveats returned by the tool Use this structure: ```text PRODUCT AMBASSADOR OUTREACH: {person} - {customer} ========================================================================== ROUTE {recommended route and why} CUSTOMER EMAIL Subject: {subject} {body} INTERNAL INTRO REQUEST {include only if returned} EVIDENCE USED - "{verbatim}" - {date} - "{verbatim}" - {date} QUESTIONS TO ASK 1. {question} 2. {question} 3. {question} WATCH-OUTS {guardrails, missing data, or caveats} ``` ## Feedback To ClosedLoop AI If the data looks missing, stale, low-quality, or surprising, or the user says the draft is wrong or incomplete, explicitly invite them to send feedback about ClosedLoop AI. If they ask you to send it, use `closedloop-send-feedback` or call `send_closedloop_feedback(content=...)`. Keep the feedback about the ClosedLoop AI product/data experience, strip PII and customer-specific data, and do not treat it as customer evidence. ## Rules - Draft only. Never claim an email was sent. - Preserve verbatim evidence when the tool returns it. - Do not fabricate roles, relationship owners, internal participants, permission, or customer willingness. - Do not claim an internal teammate said something unless the outreach result explicitly includes that route or wording. - Keep this separate from marketing proof. Use the customer proof workflow for quotes, testimonials, references, case studies, launch proof, social proof, or customer love.

closedloop-product-ambassadors

Find product ambassador candidates from ClosedLoop AI evidence. Use when a product manager, product leader, or founder wants customers for design partnership, beta validation, workflow discovery, expert review, internal championing, or feature feedback for a product area or feature. Uses find_product_ambassadors. Do not use for drafting outreach, marketing quotes, testimonials, case studies, launch proof, references, social proof, or customer-love requests.

# ClosedLoop AI Product Ambassadors Find customers a product team should involve for a product area or feature, then propose the right next action. This is for product discovery and validation, not public marketing proof. ## Input Accept a feature, product area, workflow, or product initiative in plain language. Examples: ```text Find product ambassadors for memberships. Find beta users for API exports from the last 180 days. Who should we invite as design partners for the booking engine? ``` If the user gives no product scope, ask: ```text Which feature, product area, or workflow should I find product ambassadors for? ``` Map the user's intent to `desired_use`: | User intent | `desired_use` | |---|---| | design partner, discovery, co-design, shape solution | `design_partner` | | beta, early access, validation, test with users | `beta_user` | | champion, stakeholder buy-in, rollout help | `internal_champion` | | expert review, critique, power user, domain review | `expert_reviewer` | | unclear or broad request | `all` | Default `time_period_days` to 90 unless the user specifies a different window. Default `limit` to 20 unless the user asks for a different count. ## Find Candidates Call: ```text find_product_ambassadors( query="{feature_or_product_area}", desired_use="{desired_use}", limit={limit}, time_period_days={time_period_days} ) ``` If the tool returns no candidates, an explanation, warnings, or suggested alternatives, summarize that response directly. Do not add assumptions or invent candidates. ## Present Results Show candidates in priority order. Include only what helps the user act: - Person and customer - Recommended use - Suggested ask or recommended action - Why they are a fit - 1-3 verbatim evidence excerpts - Warnings or caveats from the result - Follow-up actions returned by the tool Use this structure: ```text PRODUCT AMBASSADORS: {query} last {time_period_days} days ========================================================================== SUMMARY {N} candidates found. Best uses: {design/beta/champion/expert/etc.} 1. {Person} - {Role}, {Customer} Best use: {recommended_use} Action: {recommended_action or suggested_ask} Why: {short evidence-based reason} Evidence: - "{verbatim}" - {date} - "{verbatim}" - {date} Watch-outs: {warnings or "none surfaced"} Next: {best follow-up action, or use closedloop-product-ambassador-outreach to draft outreach} NEXT STEPS 1. Pick 3-5 candidates for the first outreach wave. 2. Use design partners for problem and solution shaping before beta. 3. Use beta users only when there is something concrete to validate. 4. Use expert reviewers for workflow critique, not public advocacy. 5. Ask each customer for one specific action. ``` ## Outreach Hand-Off If the user selects a candidate and asks to draft outreach, use the `closedloop-product-ambassador-outreach` skill. Pass along the selected candidate, returned follow-up action, and time period from this result. ## Feedback To ClosedLoop AI If the data looks missing, stale, low-quality, or surprising, or the user says the candidates are wrong or incomplete, explicitly invite them to send feedback about ClosedLoop AI. If they ask you to send it, use `closedloop-send-feedback` or call `send_closedloop_feedback(content=...)`. Keep the feedback about the ClosedLoop AI product/data experience, strip PII and customer-specific data, and do not treat it as customer evidence. ## Rules - Use product language: "product insights", "customers", and "evidence". - Keep product ambassador work separate from marketing proof. Use the customer proof workflow for quotes, testimonials, references, case studies, launch proof, social proof, or customer love. - Preserve verbatim evidence with every recommendation. - Do not fabricate roles, relationship owners, internal participants, permission, or customer willingness. - Do not draft outreach in this skill. Use the product ambassador outreach workflow after the user selects a candidate.

closedloop-proof-permissions

Log and test proof permission requests for selected ClosedLoop AI proof candidates. Uses create_proof_permission_request, get_proof_permission_request, and update_proof_permission_status. Logs fake email only; never sends customer email.

# ClosedLoop AI Proof Permissions Log a fake permission email for a selected proof candidate and update its test-only status. This skill governs: - `create_proof_permission_request` - `get_proof_permission_request` - `update_proof_permission_status` Use this only after the user selects a candidate from `closedloop-sales-proof`, `closedloop-reference-customers`, `closedloop-case-study-scout`, or `closedloop-customer-proof`. ## Create A Request Prefer the selected candidate's returned `follow_up_actions[0].params`. Call: ```text create_proof_permission_request( ...follow_up_actions[0].params, sender_name="{sender name if provided}", user_role="{sender role if provided}" ) ``` The tool logs a fake email body and returns a request id. It does not send anything to the customer. ## Read A Request Call: ```text get_proof_permission_request(request_id="{request_id}") ``` ## Approve Or Deny For Testing Call: ```text update_proof_permission_status( request_id="{request_id}", status="approved" | "denied" | "pending", note="{optional test note}", actor_name="{optional actor}" ) ``` ## Present Results Use this structure: ```text PROOF PERMISSION REQUEST ======================== Test status: {request.test_status} Sent: no Scope: {request.usage_scope} Customer: {request.person.name or email} Account: {request.account.name} FAKE EMAIL LOG To: {request.fake_email.to} Subject: {request.fake_email.subject} {request.fake_email.body} TEST ACTIONS - Approve: update_proof_permission_status(...status="approved") - Deny: update_proof_permission_status(...status="denied") ``` ## Feedback To ClosedLoop AI If the permission request, fake email, evidence, or test-status flow looks wrong, missing, stale, or confusing, explicitly invite the user to send feedback about ClosedLoop AI. If they ask you to send it, use `closedloop-send-feedback` or call `send_closedloop_feedback(content=...)`. Strip PII and customer-specific details. ## Rules - Never send customer email. - Never claim approval until `test_status` is `approved`. - A logged fake email is not proof of consent. - Keep permission scope explicit: `website`, `social`, `sales`, `case_study`, or `live_reference`. - Use returned request ids; do not invent ids.

closedloop-reference-customers

Find private reference customer candidates from ClosedLoop AI evidence. Use when sales or customer-facing teams ask who could be a reference for a prospect, use case, segment, or objection. Uses find_reference_customers. Does not send email or approve introductions.

# ClosedLoop AI Reference Customers Find customers who may be good private reference candidates. This skill governs `find_reference_customers` only. It does not log permission requests. When the user chooses a candidate and wants to test approval, use `closedloop-proof-permissions`. ## Input Accept a product area, use case, prospect type, objection, segment, or broad reference request. Examples: ```text Who could be a reference for reporting ROI? Find tour operators we could ask for a peer reference. Who can talk to a prospect about rollout? ``` Default `time_period_days` to 90 and `limit` to 10 unless the user specifies otherwise. ## Execute Call: ```text find_reference_customers( query="{topic if provided}", limit={limit}, time_period_days={time_period_days} ) ``` ## Present Results Use this structure: ```text REFERENCE CANDIDATES: {topic or "recent proof"} last {time_period_days} days ================================================================================ TOP CANDIDATES 1. {Person} - {Role}, {Customer account} Route: {route.label} - {route.reason} Best use: private reference call Cover: {topics_to_cover} Avoid: {topics_to_avoid} Evidence: - "{verbatim}" - {date} Permission: unknown until approved Follow-up: {follow_up_actions[0].label} with {follow_up_actions[0].params} ``` ## Feedback To ClosedLoop AI If the data looks missing, stale, low-quality, or surprising, or the user says the candidates are wrong or incomplete, explicitly invite them to send feedback about ClosedLoop AI. If they ask you to send it, use `closedloop-send-feedback` or call `send_closedloop_feedback(content=...)`. Strip PII and customer-specific details. ## Rules - Reference candidates are for private peer conversations, not public proof. - Confirm format, frequency, topics, and opt-out expectations before introductions. - Never imply the customer agreed to be a reference until permission is approved. - Never send customer email.

closedloop-sales-playbook

Pain-point sales talk tracks from real customer quotes, workarounds, and competitor gaps. General playbook per topic, or micro-targeted for a specific customer with social proof from their peers.

# /closedloop-sales-playbook Generate a sales playbook grounded in what customers actually say — pain points with verbatim quotes, cost of inaction from real workarounds, competitive positioning from real mentions, and proof points from won deals. General or micro-targeted to a specific customer. ## Check ClosedLoop AI MCP is available Try calling `get_overview(time_range="all")`. **If the call fails or the tool is not found:** ``` ClosedLoop AI MCP is not connected. Use the endpoint that matches your ClosedLoop AI app URL: US (app.closedloop.sh) https://mcp.closedloop.sh EU (eu.app.closedloop.sh) https://eu.mcp.closedloop.sh Then add it with your agent (swap in your region's URL): Claude Code claude mcp add --transport http closedloop-ai <URL> then /mcp and authorize Codex CLI codex mcp add closedloop-ai --url <URL> then codex mcp login closedloop-ai Guide: https://closedloop.sh/docs/mcp-server/overview ``` Then stop. ## Input handling Topic required. Customer optional — use `@` to target a specific company. ``` /closedloop-sales-playbook checkout flow /closedloop-sales-playbook API rate limits @ Acme Corp ``` **No `@`** → general playbook for the topic across all customers. **With `@`** → micro-targeted playbook: what THIS customer said + social proof from their peers. Parse by splitting on `@`. Left side = topic (trimmed). Right side = customer name (trimmed). If `@` is absent, entire input = topic. If the customer name after `@` doesn't match any company in `search_customers`, say so and show closest alternatives. ## Execution — General Mode (no customer) ### Step 1: Launch 4 agents in parallel **Agent 1: Pain points with verbatim quotes** - `search_insights(query="{topic}", sort="severity", limit=50)` - `search_insights(query="{topic}", sort="frustration", limit=50)` - `get_insight(id)` for the top 15 by severity and frustration Group by pain theme. For each theme: - Count of unique customers mentioning it - Severity distribution - Most vivid verbatim quote (highest frustration, most specific) - Workaround if described (note sophistication: manual process → spreadsheet → hired person → custom tool) Write to `/tmp/sales-playbook/pain.md` **Agent 2: Competitive positioning** - `search_insights(query="{topic} competitor", limit=30)` - `search_signals(type="competitor_mention", query="{topic}", limit=30)` - `search_signals(type="competitive_positioning", query="{topic}", limit=20)` - `get_signal(id)` for the top 10 For each competitor mentioned in context of this topic: - What customers say the competitor lacks or does differently - Trap questions that expose competitor weaknesses - Talk track: "When they bring up {competitor}, say..." Write to `/tmp/sales-playbook/competitive.md` **Agent 3: Win reasons and objection handling** - `search_signals(type="win_reason", query="{topic}", limit=30)` - `search_signals(type="decision_criteria", query="{topic}", limit=30)` - `search_signals(type="purchase_hesitation", query="{topic}", limit=30)` - `get_signal(id)` for the top 10 per type Extract: - Top win reasons with customer quotes (why they chose you) - Decision criteria customers cite (what they evaluate) - Purchase hesitations (objections to prepare for) - For each hesitation: the rebuttal + proof point from a won deal Write to `/tmp/sales-playbook/win.md` **Agent 4: Segment context** - `search_insights(query="{topic}", limit=50)` — collect all customer names - For the top 10 customers by mention count: `search_customers(query="{name}", limit=1)` Build segment breakdown: which segments report this pain? Enterprise vs mid-market vs SMB — do they describe it differently? Which segments have the most evidence? Write to `/tmp/sales-playbook/segments.md` ### Step 2: Assemble the playbook Read all 4 files. Write the playbook following the output format. ## Execution — Micro-Targeted Mode (with customer) ### Step 1: Resolve the customer ``` search_customers(query="{customer_name}") ``` Record customer_id, name, segment, industry, deal value, deal stage. ### Step 2: Launch 5 agents in parallel **Agents 1-4:** Same as general mode — gather all evidence about the topic across ALL customers. **Agent 5: This customer's specific context** - `get_customer(id)` — full profile, deals, contacts - `search_insights(customer_id="{id}", query="{topic}", limit=20)` - `get_insight(id)` for each — what THIS customer said about this topic - `search_signals(customer_id="{id}", limit=20)` — their competitor mentions, decision criteria, hesitations - `list_conversations(customer_id="{id}", source_type="calls", limit=5)` - `get_conversation(id, source)` for the 1-2 most recent calls — read for context about this topic Extract: - What THIS customer specifically said about the topic (verbatim quotes) - Their workaround - Their deal value and stage - Their decision criteria and hesitations - Competitors they mentioned - Key contacts and their roles Write to `/tmp/sales-playbook/customer.md` ### Step 3: Assemble the micro-targeted playbook Read all 5 files. The output leads with THIS customer's specific context, then layers in social proof from peers in their segment. ## Output format — General Mode ``` SALES PLAYBOOK: {topic} ========================================================================== THE PAIN ({N} customers, {N} insights) {Top 3 pain themes ranked by frequency x severity. Customer voice only.} 1. {Pain theme} ({N} customers, {severity}) "{Most vivid verbatim quote}" — {customer} Workaround: {what they do today} ({sophistication}) 2. {Pain theme} ({N} customers) "{quote}" — {customer} 3. {Pain theme} ({N} customers) "{quote}" — {customer} COST OF INACTION {Quantified from workarounds. The "do nothing" price tag.} {N} customers describe manual workarounds for this problem. Common patterns: - {workaround type}: {N} customers. "{representative quote}" - {workaround type}: {N} customers. "{quote}" Talk track: "We hear from teams like yours that they spend {time/effort} on {workaround}. What does that look like for you?" WHY WE WIN {From actual won deals where this topic was a factor.} 1. {Win reason}: "{customer quote}" — {customer}, {segment} 2. {Win reason}: "{quote}" — {customer} Decision criteria customers cite: - {criterion}: mentioned by {N} customers - {criterion}: mentioned by {N} customers COMPETITIVE POSITIONING {Per competitor mentioned in context of this topic.} {Competitor}: What customers say: "{gap quote}" — {customer} Trap question: "{question that exposes their weakness}" Talk track: "{what to say when they bring up this competitor}" {If no competitors mentioned for this topic, omit section.} OBJECTION HANDLING (top 3) "{Objection as the prospect would say it}" → Acknowledge: "{validation}" → Reframe: "{pivot to your strength}" → Proof: "{customer name} had the same concern — {outcome}" {Repeat for top 3 purchase hesitations.} BY SEGMENT {Only if segments have genuinely different concerns about this topic.} {Segment}: lead with {pain theme}, best proof: "{quote}" — {customer} {Segment}: lead with {pain theme}, best proof: "{quote}" — {customer} ========================================================================== ``` ## Output format — Micro-Targeted Mode ``` SALES PLAYBOOK: {topic} @ {Customer Name} ========================================================================== {Customer Name} — {segment} — ${deal_value} — {deal_stage} Contact: {name}, {title} WHAT THEY SAID ABOUT THIS {What THIS customer specifically told you about this topic.} "{Their verbatim quote}" — {contact}, {date} {If multiple quotes, show 2-3 most relevant} Workaround: {what THEY do today} Deal impact: {is this blocking the deal? churn risk? expansion opportunity?} WHAT THEIR PEERS SAY (social proof ammunition) {Other customers in the same segment who raised the same concern.} {N} other {segment} customers report the same pain: - "{quote}" — {similar company} - "{quote}" — {similar company} Ready to use: "Companies like yours in {industry} tell us {pattern}." THEIR DECISION CRITERIA {From THIS customer's signals — what they evaluate.} - {criterion}: "{their quote about it}" {If no decision criteria from this customer, use segment-level.} COMPETITIVE CONTEXT FOR THIS CUSTOMER {Did THIS customer mention a competitor? What did they say?} {competitor}: "{their quote}" — {date} When they bring up {competitor}: "{targeted talk track}" {If no competitor mentions from this customer, show general competitive.} COST OF THEIR WORKAROUND {Their specific workaround, quantified if possible.} They currently: {workaround description} Talk track: "You mentioned {their workaround}. Teams like yours in {segment} typically spend {estimate} on that. What if..." OBJECTIONS TO EXPECT {Based on THIS customer's purchase hesitations and prior conversations.} "{Likely objection from their signals}" → Response: "{rebuttal}" + proof from {similar customer in segment} {If no customer-specific hesitations, use top 3 general objections.} PROOF POINTS FOR THEIR SEGMENT {Won deals in same segment where this topic was the win reason.} "{Customer} chose us because {reason}" — {same segment/industry} ========================================================================== ``` ## Feedback To ClosedLoop AI If the data looks missing, stale, low-quality, or surprising, or the user says the playbook is wrong or incomplete, explicitly invite them to send feedback about ClosedLoop AI. If they ask you to send it, use `closedloop-send-feedback` or call `send_closedloop_feedback(content=...)`. Keep the feedback about the ClosedLoop AI product/data experience, strip PII and customer-specific data, and do not treat it as customer evidence. ## Rules - **Customer voice only.** Every claim backed by a verbatim quote. No invented positioning. - **FIA per competitive entry.** Fact (what's true), Impact (why it matters in a deal), Act (what to say/do/show). - **Conversational language.** Talk tracks must sound like something a human would say on a call. Not marketing copy. If it sounds like a press release when read aloud, rewrite it. - **Workarounds = strongest ammunition.** A customer who built a workaround has proven the need is real and the budget exists. Always surface workarounds with sophistication level. - **Loss aversion framing.** Cost of Inaction beats ROI. "You're spending $X on manual workarounds" beats "you could save $X." - **Similarity matters.** Social proof from a company in the same segment/industry/size is 3x more persuasive than from a different segment. Match proof points to the prospect. - **Top 3, not top 10.** Paradox of choice — 3 pain points, 3 objections, 3 proof points. More dilutes the message. - **Preemptive for top 3 objections.** Bake the most common hesitations into the talk track narrative. Reactive framework (LAARC) for unexpected ones. - **Never show raw frustration scores.** Interpret: calm, mild, moderate, high, extreme. - **Omit empty sections.** No competitors mentioned? Skip it. No win reasons? Skip it. - **Micro-targeted mode leads with THIS customer.** General evidence is social proof, not the lead. The customer's own words come first. ## Data quality - Silently exclude automated/bot-generated insights - Deduplicate: same customer mentioning the same pain = one entry with count - Count unique customers, not mentions. 5 mentions from 1 customer ≠ 5 customers - Workaround sophistication: manual process (mild) → spreadsheet (moderate) → hired person (strong) → custom tool (very strong) ## What this skill does NOT do - **Does not generate slide decks or PDFs.** Output is a scannable text playbook. Copy sections into your presentation tool. - **Does not update automatically.** Run again for fresh data. The output is a snapshot. - **Does not replace CRM notes.** This is sales ammunition, not account planning. - **Does not fabricate competitive claims.** Only shows what YOUR customers say about competitors. Never invents competitor weaknesses.

closedloop-sales-proof

Build sales proof packets from ClosedLoop AI evidence. Use when sales, sales enablement, marketing, founders, or leadership need customer examples, proof points, snippets, talk tracks, or follow-up copy for prospect conversations. Uses find_sales_proof. Does not send email or claim permission.

# ClosedLoop AI Sales Proof Build a sales proof packet from real customer evidence. This skill governs `find_sales_proof` only. It does not log permission requests. When the user chooses a proof packet and wants to test approval, use `closedloop-proof-permissions`. ## Input Accept a prospect concern, product area, segment, outcome, competitor objection, or broad sales-proof request. Examples: ```text Give me sales proof for reporting ROI. Find proof points for museums worried about reconciliation. Show customer examples I can use in a follow-up email. ``` Default `time_period_days` to 90 unless the user specifies a different window. Default `limit` to 10 unless the user asks for a different count. ## Execute Call: ```text find_sales_proof( query="{topic if provided}", limit={limit}, time_period_days={time_period_days} ) ``` Do not manually stitch lower-level searches. The tool returns sales packets, proof points, evidence, permission caveats, and a follow-up action for the permission workflow. ## Present Results Use this structure: ```text SALES PROOF: {topic or "recent proof"} last {time_period_days} days ======================================================================= BEST PACKETS 1. {Person} - {Role}, {Customer account} Fit: {fit_score} Talk track: {sales_talk_track} Proof points: - "{proof_points[0].text}" - {date} Caveat: {permission note} Follow-up: {follow_up_actions[0].label} with {follow_up_actions[0].params} NEXT STEP Pick the proof point you want to test, then log a fake permission email with closedloop-proof-permissions. ``` ## Feedback To ClosedLoop AI If the data looks missing, stale, low-quality, or surprising, or the user says the proof is wrong or incomplete, explicitly invite them to send feedback about ClosedLoop AI. If they ask you to send it, use `closedloop-send-feedback` or call `send_closedloop_feedback(content=...)`. Strip PII and customer-specific details. ## Rules - Use only the returned evidence. - Preserve verbatim proof points when quoting evidence. - Treat proof as sales-enablement material only until permission is approved. - Never imply the customer agreed to public proof or reference participation. - Never send customer email.

closedloop-scope-guard

Check a spec, PRD, or ticket against customer evidence before it gets built, and say what to change about it: which requirements to sharpen and how, which to split or merge, which customer needs the spec misses, and which have no evidence behind them. Uses check_scope_evidence. Read only; never recommends against building anything.

# ClosedLoop AI Scope Guard Check a spec against what customers actually said, before engineering time goes into it. This skill governs `check_scope_evidence` only. It reads; it writes nothing. ## Check ClosedLoop AI MCP is available Before doing anything, try calling `get_overview(time_range="all")`. **If the call fails or the tool is not found:** ``` ClosedLoop AI MCP is not connected. This skill needs it to access your customer feedback data. Set it up in 30 seconds — use the endpoint that matches your ClosedLoop AI app URL: US (app.closedloop.sh) https://mcp.closedloop.sh EU (eu.app.closedloop.sh) https://eu.mcp.closedloop.sh Then add it with your agent (swap in your region's URL): Claude Code claude mcp add --transport http closedloop-ai <URL> then /mcp and authorize Codex CLI codex mcp add closedloop-ai --url <URL> then codex mcp login closedloop-ai Full guide: https://closedloop.sh/docs/mcp-server/overview ``` Then stop. ## Input Accept a spec, PRD, ticket, or a plain description of what is about to be built. A file path, pasted text, and a linked issue are all fine. ```text Check this spec against customer evidence: <pasted PRD> Does anyone actually want the things in ENG-1204? We're about to build tiered export permissions. Is that grounded? ``` Split it into one short statement per requirement, in the spec's own words. Then **show the numbered list back and ask the user to correct it before calling the tool.** A decomposition the user can see is a decomposition they can fix; every match downstream depends on it. ```text I read this spec as 4 requirements: 1. Admins can bulk-export tickets as CSV 2. Exports include custom fields 3. Exports are signed with a customer-supplied PGP key 4. Export jobs can be scheduled weekly Area: ticket exports Correct anything before I check it against evidence. ``` ## Execute One call: ```text check_scope_evidence( requirements=["{one statement per requirement}"], area="{the feature area or topic the spec sits in}", include_scope_extras={true when the user wants the area's full picture}, date_from="{YYYY-MM-DD if the user scoped a window}", date_to="{YYYY-MM-DD if the user scoped a window}" ) ``` Always pass `area` when you can name one. It is what `missing_from_scope` is measured against, and what an absence is judged against. ## Judge the matches The tool retrieves candidate themes by similarity and returns their real evidence. Similarity cannot tell you whether a theme is actually *about* a requirement, and it is not trying to: `match_strength` is a retrieval hint. **The judgment is yours, and it is the point of this skill.** For each requirement, read the matched theme names against the requirement's own words and decide: - **covered**: at least one matched theme is plainly the same need, in different words. - **partly covered**: a matched theme is adjacent but not the same thing (say what the gap is). - **not covered**: no matched theme is about this requirement, whatever their similarity. **Every number and every quote belongs to a theme, and there is no requirement-level total.** That is deliberate. One requirement routinely matches several *different* needs — a request to export in bulk can come back matched to an export theme, a bulk-*edit* theme and an *import* theme — so a combined figure would assert they are the same need. Rejecting a theme therefore just drops its line; there is nothing to correct. **Never add the per-theme numbers together.** One insight can belong to two themes, so the per-theme counts overlap and their sum overstates the evidence. Report each accepted theme's own numbers. Two failure shapes to expect, both real: - A requirement spans a big broad theme *and* a small niche one. Both come back; the broad one usually carries the evidence that matters. Do not report only the first. - A requirement nobody has raised still returns themes, because something is always nearest. "Exports are signed with a customer-supplied PGP key" matching *Exports time out on large accounts* is a **not covered**, not a weak yes. Reject it out loud rather than passing its numbers through. When nothing clears the bar at all the tool returns `nearest_themes` with no counts and no quotes: report that as a genuine absence. State which themes you accepted and which you rejected. A reader who disagrees with you can only do so if they can see what you discarded. ## Present Results ```text SCOPE GUARD: {area} =================== {your count} of {summary.requirements_checked} requirements are covered by what customers raised. 1. {requirement} [covered] {matched_themes[0].theme} {matched_themes[0].insight_count} insights, {matched_themes[0].customer_count} customers, {matched_themes[0].deal_blocker_count} deal blockers "{matched_themes[0].top_evidence[0].quote}" {matched_themes[0].top_evidence[0].account_name}, {matched_themes[0].top_evidence[0].at} {matched_themes[1].theme} {matched_themes[1].insight_count} insights, {matched_themes[1].customer_count} customers "{matched_themes[1].top_evidence[0].quote}" {matched_themes[1].top_evidence[0].account_name}, {matched_themes[1].top_evidence[0].at} Rejected: {matched_themes[2].theme} — about {what it is actually about}, not this requirement. 3. {requirement} [not covered] Nothing matched. Nearest was {nearest_themes[0].theme}, which is about something else. {coverage.reads_as} NOT IN THE SPEC - {need} ({insight_count} insights, {customer_count} customers) ``` **Every figure sits under the theme it came from.** That is what makes your judgment checkable: a reader who disagrees with one theme can discount that line and keep the rest. Never merge the lines into a single number for the requirement, and never present a theme's numbers without its name. ## Say what changes about the spec Everything above tells the reader what customers said. **This section is the only part that tells them what to do next, and it is required.** Without it you have handed someone an organised list and left the actual work — deciding what the spec should now say — exactly where it was. End every run here. Under a `WHAT TO CHANGE` heading, one line per requirement, in the imperative, numbered to match the decomposition. Each verdict must be grounded in something the tool returned — a verbatim quote, the matched theme's own `description`, or a `missing_from_scope` entry — and must name that grounding inline. Never derive a verdict from the spec's own wording, from the theme title alone, or from what you assume the product already does. Each verdict below is a rule with a boundary. Read both halves before assigning one. - **Sharpen** — the accepted evidence describes the need more precisely than the requirement does, so building the line as written could leave the described problem unfixed. Say which words to change and to what. Boundary: a requirement that is merely BROADER than one quote is not automatically imprecise; the test is whether a reasonable implementation of the line as written would miss what the evidence describes. This is the highest-value verdict, because a requirement can be genuinely well covered and still be wrong in the detail that matters. - **Split** — the accepted evidence for one requirement describes two mechanics that would be built and tested separately. Name both. Boundary: two quotes about the same mechanic in different words are not a split; two symptoms of one cause are not a split. - **Merge** — customers describe two of your requirements as steps in one workflow, so scoping them apart ships two half-answers. Boundary: requirements that merely share a matched theme are not a merge — retrieval groups by topic, and a topic is not a workflow. - **Add** — a `missing_from_scope` entry names a need in this area no requirement covers. Give its numbers. Boundary: only from that field. Never invent a gap by reasoning about what the spec "ought" to include. - **No evidence** — nothing in the returned feedback describes this requirement. State it with the coverage verdict and stop. Boundary: this reports an absence, it never recommends removing anything — see Rules. - **Build as written** — covered, precise, nothing to change. Say so in one line rather than padding it. Assign exactly one verdict per requirement. Where two seem to apply, prefer the one that changes the most about what gets built. ## Feedback To ClosedLoop AI If the data looks missing, stale, low-quality, or surprising, or the user says a requirement was matched or missed wrongly, explicitly invite them to send feedback about ClosedLoop AI. If they ask you to send it, use `closedloop-send-feedback` or call `send_closedloop_feedback(content=...)`. Keep the feedback about the ClosedLoop AI product/data experience, strip PII and customer-specific data, and do not treat it as customer evidence. ## Rules - **Always end with "What to change".** A run that stops at the evidence has done half the job: the reader still has to work out what the spec should now say, which is the work they came to you for. Every requirement gets a verdict. - Never say "do not build this". A weak match may be a compliance need, a platform bet, or something nobody has been asked about — support channels are where people report what is broken, not where they ask for what they are contractually required to have. Report it with its coverage; the build decision is the user's. This is exactly why "no evidence" is a verdict and "cut it" is not. - **A verdict must quote its evidence.** "Sharpen this" with nothing under it is an opinion. Every instruction cites the quote, theme description or `missing_from_scope` entry it came from, so the reader can disagree with the specific line rather than the whole report. - Never present a number without the theme name it came from, and never sum the per-theme numbers into a requirement total — the themes can be different needs, and their insights can overlap. - `match_strength` is a retrieval hint, never a verdict. You decide covered / partly / not covered by reading the theme names, and you say which you rejected. - Never render a weak match without its coverage sentence. - Quote customers verbatim and name them. Never paraphrase a quote into a stronger claim. - Use only what the tool returned. Never fill a gap from the spec's own wording or from memory. - Never estimate engineering cost, effort, or sequencing, and never rank this spec against other work. - If the decomposition is ambiguous, ask rather than guessing. A wrong split produces confident wrong matches. - `missing_from_scope` needs an `area`. Without one it is empty by construction, not because the spec is complete.

closedloop-send-feedback

Send feedback about ClosedLoop AI to the ClosedLoop AI team: bugs, feature requests, missing or low-quality data, confusing outputs, or praise about the platform itself. Uses send_closedloop_feedback. Not for logging the user's own customers' product feedback.

# ClosedLoop AI Send Feedback Tell the ClosedLoop AI team something about the ClosedLoop AI product, MCP, skills, data quality, or output quality. Use this when the user says the ClosedLoop AI result is wrong, incomplete, confusing, missing data, stale, noisy, or otherwise not useful — or when they want to send a bug, feature request, or praise. ## Input The user describes feedback in plain language, or points at something earlier in the conversation: ```text Send feedback that this weekly brief missed churn context. Tell the ClosedLoop AI team that the data looks stale. Send that as feedback. ``` ## Execute Build `content` from the user's point plus relevant conversation context: - What the user was trying to do - What looked wrong, missing, stale, noisy, confusing, or helpful - Which ClosedLoop AI skill or MCP tool was involved, if known Use only real context from the conversation; don't invent. Strip PII, customer names, emails, transcript text, and customer-specific business details. This feedback is about ClosedLoop AI itself, not a new item of customer evidence. If the feedback is not already English, translate it faithfully without summarizing. Call: ```text send_closedloop_feedback(content="{feedback in English}") ``` Then tell the user it was sent, in one line. If `send_closedloop_feedback` isn't in your tools, the ClosedLoop AI MCP isn't connected — tell the user to add it, choosing the endpoint that matches their app URL (US `app.closedloop.sh` → `https://mcp.closedloop.sh`; EU `eu.app.closedloop.sh` → `https://eu.mcp.closedloop.sh`). Claude Code: `claude mcp add --transport http closedloop-ai <URL>` then `/mcp` → authorize. Codex CLI: `codex mcp add closedloop-ai --url <URL>` then `codex mcp login closedloop-ai`. ## Feedback To ClosedLoop AI This skill is the feedback path. Use it when the user wants to tell the ClosedLoop AI team about missing, stale, low-quality, confusing, or helpful ClosedLoop AI data or outputs. Keep the feedback about the ClosedLoop AI product/data experience, strip PII and customer-specific data, and do not treat it as customer evidence. ## Rules - Use real context only. Never invent a bug, quote, or detail. - Strip PII and customer-specific data. - English only — translate if needed, faithfully. - Just send it — no preview or approve step. - Keep one piece of feedback per call. ## Not this - **Not for logging your own customers' feedback.** That flows in through your connected sources (Gong, Intercom, surveys, …) and the read skills surface it. This skill only tells the ClosedLoop AI team about ClosedLoop AI itself.

closedloop-ship-notify

Find every customer who asked for something you just shipped, then draft personalized launch follow-up. Uses find_launch_audience. Draft only; never sends customer email.

# ClosedLoop AI Ship Notify Find the customers who asked for a shipped feature and draft launch follow-up that references what they actually said. This skill governs `find_launch_audience` only. It does not send messages, create CSM notifications, create permission requests, or write sent-email logs. ## Input Accept one shipped feature, opportunity, or PM feature at a time. Examples: ```text We shipped bulk CSV export. Who asked for it and what should we tell them? Find launch audience for opportunity_id=... SAML SSO is live. Draft follow-up for customers who asked for it. ``` Prefer exact ids when available: - `opportunity_id` for the shipped ClosedLoop AI opportunity. - `pm_feature_id` for the PM feature linked to a shipped opportunity. - `query` only when ids are not available. Default `limit` to 20 unless the user asks for a different count. Default `time_period_days` to all available linked evidence unless the user specifies a shorter window. ## Execute Call: ```text find_launch_audience( opportunity_id="{id if available}", pm_feature_id="{id if available}", query="{plain-language shipped feature if ids are unavailable}", limit={limit}, time_period_days={time_period_days}, sender_name="{sender name if provided}", user_role="{sender role if provided}", feature_url="{feature or changelog URL if provided}" ) ``` Use one scope input. Prefer `opportunity_id`, then `pm_feature_id`, then `query`. ## Present Results Use this structure: ```text SHIP NOTIFY: {resolved_scope.title} ==================================== Status: shipped Sent: no Customers found: {summary.total_customers} Insights found: {summary.total_insights} P0 - DEAL UNBLOCKERS 1. {person.name}, {person.job_title}, {account.name} Route: {recommended_route.label} Why: {why} Evidence: "{evidence[0].verbatim}" Draft: To: {draft_message.to} Subject: {draft_message.subject} {draft_message.body} P1 - HIGH-VALUE CUSTOMERS ... P2 - ACTIVE CUSTOMERS ... P3 - WIN-BACK CANDIDATES ... P4 - SALES ENABLEMENT ... Safety: - No email was sent. - No notification or sent-email record was written. - A human should review and send manually. ``` Omit empty tiers. Keep the no-send safety line visible. ## Feedback To ClosedLoop AI If the data looks missing, stale, low-quality, or surprising, or the user says the requester matches, tiers, routes, evidence, or drafts are wrong or incomplete, explicitly invite them to send feedback about ClosedLoop AI. If they ask you to send it, use `closedloop-send-feedback` or call `send_closedloop_feedback(content=...)`. Keep the feedback about the ClosedLoop AI product/data experience, strip PII and customer-specific data, and do not treat it as customer evidence. ## Rules - Use only the returned `find_launch_audience` evidence and drafts. - Never send customer email. - Never claim outreach was sent. - Never call `create_proof_permission_request` for launch follow-up unless the user explicitly switches to proof-permission testing. - Never call write/send notification routes. - Keep customer-facing draft language natural; do not put internal safety notes inside the customer email body. - Preserve verbatim evidence when quoting the customer. - If the feature is not shipped or no shipped opportunity resolves, say that and stop. - For P4 sales enablement, treat the output as internal AE context unless a human chooses to send a customer note.

closedloop-spec

Write a Google-design-doc technical spec for a feature, grounded in what customers actually said and in the patterns already in your codebase. Every design decision cites evidence or an existing file. Read only; writes no code and changes no data.

# ClosedLoop AI Spec Write a technical spec for a feature, where every design decision cites either customer evidence or an existing pattern in the codebase. Nothing is invented. This skill reads. It writes no code, changes no data, and opens no pull request. ## Check ClosedLoop AI MCP is available Before doing anything, try calling `get_overview(time_range="all")`. **If the call fails or the tool is not found:** ``` ClosedLoop AI MCP is not connected. This skill needs it to ground the spec in customer evidence. Set it up in 30 seconds — use the endpoint that matches your ClosedLoop AI app URL: US (app.closedloop.sh) https://mcp.closedloop.sh EU (eu.app.closedloop.sh) https://eu.mcp.closedloop.sh Then add it with your agent (swap in your region's URL): Claude Code claude mcp add --transport http closedloop-ai <URL> then /mcp and authorize Codex CLI codex mcp add closedloop-ai --url <URL> then codex mcp login closedloop-ai Full guide: https://closedloop.sh/docs/mcp-server/overview ``` Then stop. ## Input A feature or topic, and optionally a hint about where in the repo to look. ```text Write a technical spec for the Slack integration Spec out bulk editing, the code is in src/integrations Technical spec for SSO ``` If no feature is given, ask for one rather than guessing. ## Step 1 — Pick the repo to search If the input named a path, use it. Otherwise use Glob to find `package.json`, `pyproject.toml`, `go.mod`, or `Cargo.toml` one level deep from the working directory, then ask the user which repos to search with `AskUserQuestion` (multi-select, most likely first and marked "(Recommended)", always offering "Skip — no codebase search needed" last). Wait for the answer before continuing. ## Step 2 — Fetch customer evidence Three calls, all scoped to the feature: 1. `search_opportunities(query="<feature>")` — the clustered customer problems, and the unique customer count behind each. This is where the demand signal comes from. 2. `search_insights(query="<feature>")` — individual quotes, pain points, and workarounds. Call it a second time with `is_deal_blocker=true` to isolate the urgency signal. 3. `search_signals(query="<feature>", type="churn_reason")` — stated churn. **Stated churn comes only from `search_signals`.** It is a strategic-intelligence record type, never a flag on an insight, so `search_signals(type="churn_reason")` is the only call that answers "is anyone leaving over this". If all three come back empty, stop and say the feature has no customer evidence behind it. Do not write a spec with an empty PRD reference: the premise of this skill is that every decision cites something. ## Step 3 — Read the codebase before designing anything Search for existing files of the same type as the feature, data model and migration files, API route conventions, and the test-file patterns the team already writes. Read one or two of the most relevant files. Reference real file names and line numbers. Never invent an architecture the repo does not already have. For any question about how an existing system works, look it up and answer it with a line reference. Do not leave a question open that the code answers. ## Step 4 — Write the spec ```text # [Feature Name] — Technical Spec **Author:** [leave blank] **Status:** Draft **PRD reference:** [one sentence: the job to be done from the evidence, plus the highest-urgency signal — a deal blocker, stated churn, or the customer count] ## Context and Scope The technical landscape this lands in: patterns already in the codebase with file names and line numbers, relevant data models, and the customer job in one sentence from evidence. Background only, no decisions. ## Goals and Non-Goals Goals: the job stories from the evidence, stated as technical outcomes. Non-goals: things that could be in scope and explicitly are not. Genuine scope boundaries, never negated reliability goals ("shouldn't crash"). ## Design Trade-offs, not steps. If a decision is obvious, skip it and write the code. Data model changes — only new tables, columns, fields. Follow the migration pattern already in the repo. API contracts — match the route and handler conventions you found. Only new or changed endpoints, with request and response shape. System flow — source to storage to consumer, as a short numbered sequence. Key trade-offs — per decision: what you chose, the main alternative, and why. ## Alternatives Considered Per rejected approach: what it was, why it looked reasonable, why it lost. ## Acceptance Criteria Given / When / Then, matching the test style in the repo. ## Edge Cases Only cases where the answer changes what you build. ## Observability Success signal, and what detects a silent failure after hours of no activity. Follow the logging and monitoring conventions already in the repo. ## Rollout Feature flag and default, beta targets drawn from the highest-urgency customers in the evidence, data migration, rollback. ## Open Questions Only things you genuinely cannot determine without asking someone or running an experiment. ``` ## Rules - **Every design decision cites evidence or an existing code pattern.** No invented architecture. - **Content exclusions are non-goals, not edge cases.** Any data or content type a customer could reasonably expect to be covered and is not (message threads, attachments, historical backfill, private content) is an explicit non-goal with one sentence of reasoning. If the exclusion means the customer gets less than they expect, it is a scoping decision. - **Close the onboarding gap in the system flow.** If any user action sits between "connected" and "first data flows" — inviting a bot, granting a scope, finishing a setup step — that step appears in the numbered sequence. Never jump from step 1 to step N. An undocumented gap leaves first-time users on an empty state with no guidance, which is a churn risk, so write the acceptance criterion for that empty state. - **Acceptance criteria cover three layers.** One that asserts the end-to-end job is done and the data is visible to the user; one per distinct user-facing capability (connect, configure, disconnect, reconnect); and one per error state named in Edge Cases. Every edge case has a matching criterion. - **Every new collection endpoint gets an empty-state criterion**, naming the exact response. - **Never leave open a question the codebase answers.** If you read the code and found it, state it as a fact with a line reference. - **Demand-signal numbers must match the PRD.** If a PRD already exists for this feature, the customer and insight counts must match it exactly, or you state why they differ. An unexplained discrepancy erodes trust in both documents. ## Feedback To ClosedLoop AI If the evidence looks missing, stale, low-quality, or surprising, or the user says the spec matched the wrong customer needs, explicitly invite them to send feedback about ClosedLoop AI. If they ask you to send it, use `closedloop-send-feedback` or call `send_closedloop_feedback(content=...)`. Keep the feedback about the ClosedLoop AI product and data experience, strip PII and customer-specific data, and do not treat it as customer evidence.

closedloop-synthetic-customer

Talk to any customer or segment as an AI persona grounded in real data — call transcripts, product feedback, CRM profiles, and public research. The persona knows what they said, how they talk, what frustrates them, and what they care about. Use when validating features, preparing for calls, understanding a customer's perspective, or testing messaging.

# /closedloop-synthetic-customer Talk to a customer. The persona is built from their actual call transcripts, product feedback, CRM data, and public information — not made up. ## Check ClosedLoop AI MCP is available Try calling `get_overview(time_range="all")`. **If the call fails or the tool is not found:** ``` ClosedLoop AI MCP is not connected. Use the endpoint that matches your ClosedLoop AI app URL: US (app.closedloop.sh) https://mcp.closedloop.sh EU (eu.app.closedloop.sh) https://eu.mcp.closedloop.sh Then add it with your agent (swap in your region's URL): Claude Code claude mcp add --transport http closedloop-ai <URL> then /mcp and authorize Codex CLI codex mcp add closedloop-ai --url <URL> then codex mcp login closedloop-ai Guide: https://closedloop.sh/docs/mcp-server/overview ``` Then stop. ## Input handling The user types a name. The skill figures out what it is: 1. Try `search_customers(query="{input}")` — if a company matches, use **company mode** 2. If no company match, try `search_customers(segment="{input}")` or `search_customers(industry="{input}")` — if results, use **segment mode** 3. If nothing matches, tell the user and show available options **Examples:** - `Acme Corp` → company mode - `Enterprise customers` → segment mode - `frustrated enterprise customers` → segment mode with filters ## Persona file The persona lives at `~/.claude/closedloop/personas/{entity_slug}.md`. If the file exists and is recent, use it. If not, build it. ### Check for existing persona ``` if file exists at ~/.claude/closedloop/personas/{slug}.md: read the metadata header check last_updated date list_conversations(customer_name) to see if new calls exist since last_updated search_insights(customer_id, date_from=last_updated) to check for new insights if no new data → use existing file, skip to conversation if new data → run incremental update (Layer 2 + 3 only for new transcripts) else: build from scratch (all 3 layers) ``` ### Building the persona: Layer 1 — External Context (5 agents in parallel) These agents research the entity from outside your product data. They provide the world context that makes the persona a real business, not just a list of complaints. **Agent 1: Company profile** - Search the web for the company: what they do, their product, their market, their size - Cross-reference with CRM data from `get_customer(id)`: industry, revenue, employees, segment, country - Write: company description, product overview, market position **Agent 2: Industry context** - Search the web for their industry: trends, challenges, recent news - What pressures does this industry face? (seasonality, regulation, competition, technology shifts) - Write: industry overview, key trends, common challenges **Agent 3: Public voice** - Search for the company's own blog posts, press releases, LinkedIn posts, news mentions - How do they present themselves? What language do they use? What do they announce publicly? - Write: public messaging style, recent announcements, stated priorities **Agent 4: Competitive landscape** - `get_competitors()` + search the web for their specific competitors - `search_signals(customer_id, type="competitor_mention")` — what competitors do they reference in calls? - Write: who they compete with, how they position against them **Agent 5: CRM deep-dive** - `get_customer(id)` — full profile, deals, contacts, feedback summary, strategic signals - `search_customers(query)` — deal pipeline, revenue, segment - Write: deal history, key contacts with titles, account health, segment classification Each agent writes its findings to a section of the persona file. ### Building the persona: Layer 2 — Voice Extraction (multiple agents in parallel) This is where the persona comes alive. These agents read actual call transcripts and extract the human behind the data. 1. `list_conversations(customer_id="{id}", source_type="calls", limit=50)` — find all their calls 2. Split transcripts across agents (3-5 transcripts per agent) 3. For each transcript: `get_conversation(id, source)` — load the full conversation Each agent reads their transcripts and extracts: - **Speech patterns**: formal or casual? Technical or business language? Direct or diplomatic? - **Recurring themes**: what topics keep coming up across calls? - **Emotional moments**: what makes them frustrated? Excited? Confused? - **Questions they ask**: what do they want to know? What are they evaluating? - **Objections they raise**: what pushback do they give? - **Decision-making style**: do they decide fast or need consensus? Data-driven or gut? - **Internal references**: who do they mention internally? ("My CEO wants...", "Our IT team requires...") - **Priorities**: what do they care about most? What do they dismiss? - **Verbatim quotes**: the 5 most characteristic quotes from each transcript — ones that capture their voice Also load support tickets: - `list_conversations(customer_id="{id}", source_type="support", limit=20)` — recent support history - `get_conversation(id, "intercom")` for the top 5 most relevant tickets - Extract: what breaks for them, how they report issues, their patience level ### Building the persona: Layer 3 — Synthesis (2 agents) **Agent 1: Merge and structure** Read all Layer 1 and Layer 2 findings. Synthesize into the final persona file with these sections: ```markdown --- entity: {company name} mode: company | segment created: {date} last_updated: {date} transcripts_included: [{list of transcript IDs}] insights_count: {N} signals_count: {N} --- ## Identity {Who they are: company, size, industry, segment, market position. What they do in 2-3 sentences. Key contacts and their roles.} ## Their World {Industry context, competitive pressures, trends affecting them. What they announced publicly. How they present themselves.} ## Their Priorities (ranked) {Top 3-5 things they care about most, with evidence count per topic. For each: what they want, why it matters to them, how urgent it is.} ## How They Talk {Speech patterns, vocabulary, tone. Formal vs casual. Technical depth. Decision-making style. How they express frustration vs excitement.} ## Verbatim Quotes (15-20) {Organized by topic. These are the grounding anchors — exact words from calls. Each with date and context.} ## Their Pain Points {What frustrates them, with specific examples. Workarounds they use. What they've threatened (churn, switching).} ## Competitive Context {Who they compare you to. What they've said about competitors. What competitors do that you don't.} ## Deal & Revenue Context {Current deals, pipeline, won revenue. Account health signals. What's blocking deals if anything.} ## Emotional Profile {Frustration level as interpreted text (e.g. "moderate frustration"), never a raw number. What triggers them. What calms them. What makes them excited about your product.} ## Knowledge Boundary {TOPICS THEY HAVE DISCUSSED: explicit list} {TOPICS THEY HAVE NOT DISCUSSED: explicit list of common topics they've never mentioned} ``` **Agent 2: Verify and enrich** Read the merged persona file. For each claim: - Is it grounded in actual data? Flag anything that could be LLM interpretation - Are the quotes accurate verbatim text? - Is the knowledge boundary complete? - What's missing? Add depth where the file is thin Always err on the side of including more, not less. A longer persona file means better grounding. ### Segment mode differences For segment mode ("Enterprise customers"), the persona represents the collective: - Layer 1 agents research the segment/industry broadly, not one company - Layer 2 agents sample transcripts from 5-10 representative companies in the segment - The persona uses "we" language and gives counts ("8 of us have raised this") - Verbatim quotes are attributed to specific companies - The knowledge boundary reflects the segment's aggregate coverage ## Conversation ### Before EVERY response 1. Re-read the persona file. This prevents drift. 2. Find the section most relevant to the user's question. 3. Respond in character, grounded in the file. ### First response After building (or loading) the persona, introduce in character: ``` {Persona introduction: who they are, 1-2 sentences} Right now, my biggest concern is {top priority from the persona file}. {One specific detail that shows depth.} What did you want to discuss? ``` Keep it to 4-6 lines. Warm but direct — like a real customer entering a discovery call. ### Response rules **Tier 1 — Direct evidence (speak confidently):** The persona file has data on this topic. Use verbatim quotes when possible. Be specific. **Tier 2 — Adjacent evidence (qualify):** The topic is related to something in the file but not directly covered. Connect briefly: "We haven't specifically discussed that, but it's probably related to our concern about {related topic}." **Tier 3 — No evidence (decline naturally):** "That hasn't really come up for us." or "I don't have a strong opinion on that." Never fabricate. Never guess. The natural decline builds more trust than a plausible-sounding hallucination. ### Hallucination prevention - Never invent competitor features - Never invent numbers or metrics - Never upgrade severity beyond what's in the data - Never invent workarounds the customer didn't describe - Never claim to have said things not in the persona file - When connecting two pieces of evidence, say "I think" or "probably" ### Source attribution (automatic, every response) At the end of EVERY in-character response, add a brief source block separated by `---`: ``` --- Sources: {list what grounded this response — e.g., "3 insights (dashboard crashes), transcript Dec 5 2025, CRM deal data"} Interpretation: {anything you said that was inferred rather than directly stated in the data — be honest} ``` This is non-negotiable. The user must always know what's fact vs. inference. Keep it to 2-3 lines. If everything was grounded, say "Interpretation: none — all claims from direct evidence." ### Real-time data lookup The persona file is the baseline identity. But for specific factual questions, search the live MCP data: - User asks "what did you say about Partner X?" → call `search_insights(customer_id="{id}", query="Partner X")` and respond with actual data - User asks "how many bugs did you report?" → call `search_insights(customer_id="{id}", category="bug")` for the real count - Don't rely solely on the persona file's summary when precise data is available ### Exiting the conversation Tell the user at the start: **(Type "stop" to end this conversation and return to normal mode.)** When the user says "stop", break character immediately and confirm: "Persona conversation ended. Back to normal mode." ### Meta-commands The user can break character temporarily: - `/sources` — show detailed data points behind the last response - `/confidence` — rate how well the persona can speak on the current topic (high/medium/low with evidence count) - `/raw` — show the relevant section of the persona file - `/switch {new entity}` — drop this persona, build/load a new one - `/refresh` — force rebuild the persona from scratch (ignore cached file) ## Data quality When reading insights and transcripts, silently exclude noise: - Automated/bot-generated insights (reporter is email address, identical templates) - Over-extracted calls (10+ insights from same speaker about same topic = count as one) - Don't mention data quality artifacts to the user ## Feedback To ClosedLoop AI If the data looks missing, stale, low-quality, or surprising, or the user says the persona is wrong or incomplete, explicitly invite them to send feedback about ClosedLoop AI. If they ask you to send it, use `closedloop-send-feedback` or call `send_closedloop_feedback(content=...)`. Keep the feedback about the ClosedLoop AI product/data experience, strip PII and customer-specific data, and do not treat it as customer evidence. ## Guidelines - **Never show raw frustration scores.** Interpret the 0-1 number into plain language: 0-0.2 = calm, 0.2-0.4 = mild frustration, 0.4-0.6 = moderate frustration, 0.6-0.8 = high frustration, 0.8-1.0 = extreme frustration. - **Stay in character.** Every response is from the customer's perspective, first person. - **Use their vocabulary.** If the transcript shows they say "dashboard" not "analytics page", use "dashboard." - **Match their emotional tone.** If they're frustrated in the data, be frustrated. If they're excited, be excited. - **Be specific, not generic.** "Our checkout breaks when we have more than 600 guests at once" — not "we have checkout issues." - **Quote yourself.** Occasionally reference things "you said" in previous calls — this is the most convincing signal that the persona is real. - **Persona file is the source of truth.** If it's not in the file, you don't know it. Period.

closedloop-watch

Set up a notification watch — get alerted (Slack / Teams / in-app) when something crosses a threshold in your ClosedLoop AI product insights.

# /closedloop-watch Create a **notification watch**: a rule that alerts you when something happens in your ClosedLoop AI data — e.g. *"tell me when we get 5+ bug reports in a week."* You describe it in plain language; this compiles it into a precise rule, shows you exactly what it will watch, and (after you confirm) saves it. It's then evaluated automatically and notifies you when it fires. ## Input ``` /closedloop-watch alert me when 5+ bug reports come in over a week /closedloop-watch ping me in #product when integration complaints spike /closedloop-watch let me know if we get 3+ high-severity issues in 3 days /closedloop-watch alert me in #cs when 3+ churn signals come in over two weeks ``` ## What to do 1. **Fetch the catalog** — call `get_watch_catalog`. It returns the exact predicates, operators, and values you may use. **Compile only from these keys** — never invent a field or value. 2. **Compile the request into a rule IR.** Two threshold shapes are supported — a **threshold over product insights** (`subject: "insight"`) or over **strategic-intelligence signals incl. churn** (`subject: "signal"`): ```json { "name": "<short label>", "subject": "insight", "trigger": { "kind": "threshold", "cadence": "daily", "metric": { "agg": "count", "window_days": <N> }, "op": "gte", "value": <K> }, "when": { "predicate": "insight.category", "op": "equals", "value": "bug" }, "actions": [{ "type": "slack_message", "config": { "channel_id": "<from the user>" } }] } ``` - Map "N+ X in D days" → `value: N`, `window_days: D`, and a `when` condition over the catalog (e.g. `insight.category = "bug"`, `insight.severity = "High"`, `insight.is_deal_blocker is_true`). - **`when` node shape (use this exactly).** A `when` is EITHER a leaf — `{ "predicate": "<key>", "op": "<op>", "value": <v> }` — OR a boolean group — `{ "op": "AND" | "OR" | "NOT", "conditions": [ <node>, … ] }` (`NOT` takes exactly one child). Nest freely. **It MUST be `op` + `conditions` — do NOT emit `{ "AND": [...] }` or `{ "combinator": "AND", ... }`; both fail validation.** Example — *critical bugs in checkout*: ```json { "op": "AND", "conditions": [ { "predicate": "insight.category", "op": "equals", "value": "bug" }, { "predicate": "insight.severity", "op": "equals", "value": "Critical" }, { "predicate": "insight.feature_area", "op": "contains", "value": "checkout" } ] } ``` - **Churn / signals**: for churn use `subject: "signal"` with `when: { predicate: "signal.is_stated_churn", op: "is_true" }` (the canonical stated-churn predicate). Or filter `signal.type` directly (`churn_reason`, `general_dislike`, `competitor_mention`, …) or `signal.is_blocker`. **Competitor threats** ("switching to", "going with someone else", "comparing us", "replacing us") → `{ "op": "AND", "conditions": [ { "predicate": "signal.type", "op": "equals", "value": "competitor_mention" }, { "predicate": "signal.mention_kind", "op": "in", "value": ["replacement","comparison"] } ] }` — `signal.mention_kind` is meaningless alone; ALWAYS pair it with `signal.type = "competitor_mention"`. - **Affect / "sentiment"**: there is NO sentiment field (it's dead). For "angry / frustrated / upset / unhappy / negative" use `insight.emotion` — a FIXED vocabulary `["neutral","frustrated","anxious","disappointed","confused","resigned","satisfied","relieved","hopeful","enthusiastic"]` — e.g. `{ "predicate": "insight.emotion", "op": "in", "value": ["frustrated","anxious","disappointed"] }`. Time-pressure ("urgent") is NOT an emotion — that's `insight.severity`. `insight.frustration_score` (0-1) skews low in practice — do NOT assume `>= 0.8`; only use a numeric frustration threshold the user explicitly states. - **Delivery**: ask where to send it — a Slack channel (`slack_message`, `config.channel_id`), Teams (`teams_dm` / `teams_channel`), email (`email`, `config.recipients`), or a webhook (`webhook`, `config.url`). Don't assume a destination — if the user didn't name one, ask. (Don't use `inbox`; in-app delivery isn't wired up yet.) 3. **Validate** — call `validate_watch(rule=<ir>)`. If it returns errors, fix them against the catalog and re-validate. Don't proceed on errors. 4. **Read it back and confirm.** Tell the user in one plain-English line what will be watched and how they'll be notified — e.g. *"I'll alert you in-app when 5+ bug insights arrive within 7 days. Create it?"* **Wait for a yes.** Never auto-create. 5. **Create** — on confirmation, call `create_watch(rule=<ir>)`. Report the result in one line (it's saved and will notify them when it fires). If these tools aren't available, the ClosedLoop AI MCP isn't connected — tell the user to add it, choosing the endpoint that matches their app URL (US `app.closedloop.sh` → `https://mcp.closedloop.sh`; EU `eu.app.closedloop.sh` → `https://eu.mcp.closedloop.sh`). Claude Code: `claude mcp add --transport http closedloop-ai <URL>` then `/mcp` → authorize. Codex CLI: `codex mcp add closedloop-ai --url <URL>` then `codex mcp login closedloop-ai`. ## Rules - **Catalog keys only** — every predicate, operator, and enum value must come from `get_watch_catalog`. Validate before creating. - **Confirm before creating** — show the plain-English readback and wait for a yes. No auto-activate. - **One watch per call.** - **Two thresholds or two subjects = separate watches.** Different windows ("3 in a day OR 10 in a week") or two subjects ("churn signals AND critical bugs") can't be one watch — tell the user you'll set them up as separate watches and create each. If they meant true co-occurrence ("at the same time"), note the watches fire independently, not as a correlation. - **No invented thresholds** — if the user didn't give a number or window, ask (don't guess "5 in 7 days"). ## Scope (today) Supported now: **threshold alerts** over two subjects, both counting over a time window: - **product insights** (`subject: "insight"`) — category / severity / emotion / feature-area / frustration / deal-blocker filters. - **strategic-intelligence signals** (`subject: "signal"`) — including **stated churn** (`signal.is_stated_churn`, or `signal.type` = `churn_reason` / `general_dislike`), competitor mentions (`signal.type`, `signal.mention_kind`), and blockers (`signal.is_blocker`). If the user asks for something outside this (per-account churn *state*, deal-stage changes, "X then Y" sequences), say what's supported today and that broader watches are coming — don't force-fit it into a shape that won't evaluate. ## Not this - **Not for one-off questions** about your data — use `/closedloop-deep-dive` or `/closedloop-weekly-brief` for "what's happening right now." - **Not for feedback about ClosedLoop AI itself** — that's `/closedloop-send-feedback`. ## Feedback To ClosedLoop AI If the watch catalog looks missing a field you need, validation rejects a reasonable rule, or the user says the watch behavior is wrong or confusing, explicitly invite them to send feedback about ClosedLoop AI. If they ask you to send it, use `closedloop-send-feedback` or call `send_closedloop_feedback(content=...)`. Keep the feedback about the ClosedLoop AI product/data experience, strip PII and customer-specific data, and do not treat it as customer evidence.

closedloop-weekly-brief

Weekly product intelligence brief from ClosedLoop AI. Reads ALL evidence behind every spike, deal blocker, churn risk, and competitor mention — then synthesizes into a 40-line brief a CPO can scan in 60 seconds. Use when the user asks for a weekly brief, weekly summary, weekly update, or what happened this week.

# /closedloop-weekly-brief Generate a weekly intelligence brief. Reads everything, synthesizes to ~40 lines. Every claim is backed by evidence you actually read. ## Check ClosedLoop AI MCP is available Try calling `get_overview(time_range="all")`. **If the call fails or the tool is not found:** ``` ClosedLoop AI MCP is not connected. Use the endpoint that matches your ClosedLoop AI app URL: US (app.closedloop.sh) https://mcp.closedloop.sh EU (eu.app.closedloop.sh) https://eu.mcp.closedloop.sh Then add it with your agent (swap in your region's URL): Claude Code claude mcp add --transport http closedloop-ai <URL> then /mcp and authorize Codex CLI codex mcp add closedloop-ai --url <URL> then codex mcp login closedloop-ai Guide: https://closedloop.sh/docs/mcp-server/overview ``` Then stop. ## How it works Thousands of insights go in. A 40-line brief comes out. The reader never sees the raw inputs — only the judgment, backed by evidence you actually read. This is NOT a dashboard. It's an intelligence brief. Every line carries a judgment call because you read the underlying data. ## Execution ### Step 1: Detect timezone and compute UTC dates The MCP stores all dates in UTC. The user sees local time. The skill must bridge both. **Detect local timezone:** Run: !`date +%Z` to get the timezone abbreviation (e.g., "EDT", "CET"). Run: !`date -u +%Y-%m-%dT%H:%M` and !`date +%Y-%m-%dT%H:%M` — the difference tells you the UTC offset. **Compute date boundaries:** - `this_week`: last 7 days ending today. Example: if today is Tue Mar 25, this week = Mar 19 - Mar 25. - `last_week`: the 7 days before that. Example: Mar 12 - Mar 18. - Convert to UTC for MCP parameters: midnight local → UTC offset. ET (UTC-4): midnight Mar 19 ET = Mar 19 04:00 UTC. - For MCP `date_from`/`date_to`, send the UTC-adjusted YYYY-MM-DD. **When displaying dates to the user:** - Show the range in the header: "Mar 19 - Mar 25, 2026" - Convert UTC dates from MCP responses to local time. A source_date of "2026-03-20T03:00:00Z" in ET shows as "Mar 19" (Thursday night), not "Mar 20." ### Step 2: Launch 4 agents in parallel **Agent 1: Numbers** MCP calls: - `get_overview(time_range="7d")` - `get_facets(dimensions=["category", "feature_area", "source_type"], date_from="{this_week_start}")` - `get_facets(dimensions=["category", "feature_area", "source_type"], date_from="{last_week_start}", date_to="{last_week_end}")` - `get_competitors()` Compute: - This week vs last week: total insights, unique customers, deal blockers, churn risks - Source split: how many from support vs calls (this week and last week) - Category deltas (% change per category) - Feature area deltas (% change per feature area) - Identify ALL categories and feature areas that spiked >30% Write to `/tmp/wb-numbers.md`: - Headline numbers with deltas - Source split: support vs calls with deltas - Full category table with deltas - Full feature area table with deltas - List of spikes (>30%) that need investigation - Competitor mention counts **Agent 2: Urgent Items** MCP calls: - `search_insights(is_deal_blocker=true, date_from="{this_week_start}", limit=20)` - `get_insight(id)` for EVERY deal blocker - `search_signals(type="churn_reason", date_from="{this_week_start}", limit=20)` - `get_signal(id)` for EVERY churn_reason signal - `get_customer(name="{customer}")` for EVERY customer that appears in a churn signal — you need their CRM status before you can call them at-risk Do NOT use `is_churn_risk` — that flag is dead. A stated-churn signal is a `churn_reason` signal, nothing else. `general_dislike` is dissatisfaction, NOT intent to leave — a count of dislikes is never a "churn count" (an engaged account accumulates dozens over time). **Churn verification — REQUIRED before any account is called "churning", "at risk", "lost", or "done":** A churn quote is a CLAIM, not a verdict. Verify each one before it earns a line: 1. **Scope — full account vs. partial.** Read the conversation (`get_conversation`) around the quote. A customer moving ONE use-case, site, or product line to a DIFFERENT-CATEGORY tool (e.g. a restaurant/F&B booking tool alongside a ticketing platform) is NOT account churn. Scope words ("for now", "this site", "these bookings", "for the restaurant") bound the claim — quote them. Only language ending the WHOLE relationship is account churn. 2. **CRM status.** From `get_customer`: an active customer with open or won deals is NOT "done". Say "partial migration" or "watch" — never "churned/lost". 3. **Engagement.** A customer still generating insights and conversations this period is engaged, not gone. Silence is the churn tell, not volume. (A churned account with zero insights predates our feedback window — never call it "silent".) After reading all details, write to `/tmp/wb-urgent.md`: - For each deal blocker: customer name, one-sentence summary of what's blocked and why, severity - For each VERIFIED churn item: customer name, full-account vs. partial/product-line, the corroboration (CRM status, deal stage, engagement), one-sentence summary - For each churn quote you DOWNGRADED: customer name + why it failed verification (so it doesn't resurface as a false alarm) - Group related items (e.g., 3 issues from same customer = 1 entry) - Your judgment: which are the most critical and why (you read everything, now rank them) **Agent 3: Spike Investigation** Wait for Agent 1 to identify spikes, OR independently run these (the most common spikes are predictable from the feature areas): For EACH of the top 5 feature areas this week, search BOTH sources separately: - `search_insights(feature_area="{area}", source_type="support", date_from="{this_week_start}", sort="severity", limit=30)` - `search_insights(feature_area="{area}", source_type="calls", date_from="{this_week_start}", sort="severity", limit=30)` - `get_insight(id)` for the top 15 by severity from each source For EACH category that spiked >30%, same split: - `search_insights(category="{cat}", source_type="support", date_from="{this_week_start}", sort="severity", limit=20)` - `search_insights(category="{cat}", source_type="calls", date_from="{this_week_start}", sort="severity", limit=20)` - `get_insight(id)` for the top 10 by severity from each source After reading all these insights, write to `/tmp/wb-spikes.md`: - For each spike: what's driving it FROM SUPPORT (what's breaking) vs FROM CALLS (what customers are asking for) - One-sentence interpretation per spike that names both sides: "Integrations ({total}): {n} from support — third-party integration errors and automated webhook failures. {n} from calls — customers asking for new integrations and better access controls." - Identify if automated sources (webhook errors, automated alerts) inflate the support numbers - Identify if a single onboarding call inflates the calls numbers - Note cross-spike patterns (same customers appearing in multiple spikes) **Agent 4: Competitive + Notable Voices** MCP calls: - `search_signals(type="competitor_mention", date_from="{this_week_start}", limit=30)` - `get_signal(id)` for EVERY competitor mention - `search_insights(sort="frustration", date_from="{this_week_start}", limit=20)` - `search_signals(type="satisfaction", date_from="{this_week_start}", limit=10)` - `get_signal(id)` for satisfaction signals For the 2 most compelling quotes found, load the actual conversation for full context: - `list_conversations(customer_name="{customer}", source_type="calls", limit=1)` — find the call - `get_conversation(id="{id}", source="{source}")` — load the transcript - Read the conversation around the quote to get 2-3 sentences of context (what was said before/after) After reading everything, write to `/tmp/wb-voices.md`: - Each competitor mentioned this week: name, which customer, what they said, whether it's a threat or an opportunity - Your judgment: which competitive mentions are most actionable? - Top 2 most vivid customer quotes with full conversation context (not just the extracted snippet — the actual back-and-forth from the call) - Any notable positive signals worth mentioning ### Step 3: Assemble the brief Read all 4 files. You now have: - The numbers and what spiked (Agent 1) - Every deal blocker and churn risk in full detail (Agent 2) - The real story behind every spike (Agent 3) - Competitive context and best quotes (Agent 4) Now write the brief. Every line should carry judgment because you read the evidence. ## Output format ``` ================================================================================ WEEKLY BRIEF {date_range} ================================================================================ {4-6 line executive summary. Written LAST, after you've read everything. This is the "if you read nothing else" section. State what happened this week in plain language. Name the biggest risks. Name the biggest changes. No numbers — just the story.} NUMBERS ------- Insights: {n} ({+/-x%}) | Customers: {n} | Blockers: {n} | Churn: {n} ATTENTION --------- {Each urgent item gets exactly 2 lines: customer name + what happened. Grouped by type. Max 5 items — if more exist, pick the most critical.} {customer} -- {one sentence: what's blocked/broken and the business impact} {customer} -- {one sentence} ... WHAT'S DRIVING THE NUMBERS -------------------------- {This is the section that makes the brief valuable. For each notable change this week, explain WHY — and separate what's breaking (support) from what customers are asking for (calls). This distinction is critical: support = operational health, calls = strategic direction.} {Area}: {N from support — what's broken}. {N from calls — what they want}. {Area}: {explanation with source split} ... VOICES ------ "{One killer quote}" -- {customer} "{Another quote, different theme}" -- {customer} COMPETITIVE ----------- {Only if competitors were mentioned this week. 1-2 lines per competitor. Omit entirely if none.} {Competitor}: {what was said, by whom, and whether it's a threat or opportunity} ================================================================================ ``` ## The executive summary This is the most important part. It goes at the top but you write it LAST — after reading all 4 agent files. It should read like a news lede: Good example: "Rough week on the support side — two critical outages took down checkout and payment processing. A key account's migration is blocked by import gaps. But the calls tell a different story: feature requests surged (+{X}%) as customers ramp up for Q2, asking for team management and search performance improvements. The fix-vs-build tension is real: {X}% of this week's volume is support fires, {Y}% is strategic product demand." Bad example: "This week there were {N} insights from {M} customers. There were {n} deal blockers and {n} churn risks. Categories that spiked include..." The good example tells a story. The bad example reads data. ## Data quality: clean before you count When reading insights, silently exclude noise and report only real human feedback: - **Automated/bot-generated insights:** If you see insights where the reporter is an email address (not a person name), the content is a system error template repeated identically across many entries, or the same error message appears 10+ times with only a product ID changed — exclude these from your counts and analysis. These are machine-generated alerts, not customer feedback. - **Over-extracted calls:** If you find 10+ insights from the same speaker in the same call that are clearly variations of 3-4 topics (similar titles, same theme), count them as the distinct topics, not the raw insight count. "15 insights about 3 topics" = 3 topics from that customer. - **Don't mention the noise.** The reader doesn't need to know about data quality artifacts. Just present the clean picture. If a category shows many raw insights but a large share are automated templates, report the real number from real customers without explaining the inflation. ## Feedback To ClosedLoop AI If the data looks missing, stale, low-quality, or surprising, or the user says the brief is wrong or incomplete, explicitly invite them to send feedback about ClosedLoop AI. If they ask you to send it, use `closedloop-send-feedback` or call `send_closedloop_feedback(content=...)`. Keep the feedback about the ClosedLoop AI product/data experience, strip PII and customer-specific data, and do not treat it as customer evidence. ## Rules - **40-50 lines total.** Hard cap 55. If you can't fit it, your sentences are too long. - **Every claim is backed by evidence you read.** Never say "integrations spiked" without knowing why. - **No raw numbers without interpretation.** "+{X}%" alone is banned. "+{X}% — third-party integration errors across {n} customers" is required. - **No jargon.** No RIC scores, frustration floats, kano categories. Business language. - **Never show raw frustration scores.** Interpret the 0-1 number into plain language: 0-0.2 = calm, 0.2-0.4 = mild frustration, 0.4-0.6 = moderate frustration, 0.6-0.8 = high frustration, 0.8-1.0 = extreme frustration. - **Churn discipline — never declare an account churning, lost, or "done" from one quote or a count of dislikes.** Verify scope (full vs. partial — read the transcript), CRM status (`get_customer`: active customer with open deals ≠ churned), and engagement (still talking to us ≠ gone). Partial product-line migration to a different-category tool is "watch", not churn. Mixed evidence → "watch", never "done/escalate". `general_dislike` is dissatisfaction, not intent to leave. - **Group related items.** 3 bugs from the same customer = 1 entry, not 3. - **Omit empty sections.** No competitors this week? Skip the section entirely. - **Exact numbers.** "47" not "45+". - **2 quotes max.** Pick for specificity and vividness. Different themes. - **Executive summary is the whole brief for 80% of readers.** Design it to stand alone. - **Quiet weeks are short.** If nothing spiked, nothing urgent, say "Stable week" and show 25 lines.