Agent Skills

customer-retention

businesshubspot1.5K installs

Identify inactive/at-risk customers via CRM filters and create follow-up tasks at scale. Builds on `bulk-operations`; defers activity-creation specifics to `sales-execution`.

Install

npx skills add https://github.com/hubspot/agent-cli-skills --skill customer-retention
SKILL.md

Resources

File When to use
resources/customer-health-signals.md Filter cookbook of churn signals — --filter expressions for notes_last_contacted, hs_last_sales_activity_date, hs_email_optout, stale tickets, subscription status.

Prereqs

Read bulk-operations/SKILL.md first — every read/write below uses its JSONL pipe, pagination, and dry-run/digest patterns. Activity-property tables and association rules live in sales-execution/SKILL.md.

Schema is portal-specific. Verify each property before filtering — e.g. hubspot properties get --type contacts notes_last_contacted, ... hs_last_sales_activity_date, ... --type subscriptions hs_subscription_status. If subscriptions returns 403, your token lacks subscriptions-read — use a private-app token with that scope.

1 — Find inactive customers

CUTOFF=$(date -v-60d +%Y-%m-%d 2>/dev/null || date -d '60 days ago' +%Y-%m-%d)

# No outreach in 60d (calls/notes/meetings update notes_last_contacted)
hubspot objects search --type contacts \
  --filter "lifecyclestage=customer AND notes_last_contacted<$CUTOFF" \
  --properties email,firstname,notes_last_contacted,hubspot_owner_id

# No sales activity in 60d (broader — also catches emails/tasks)
hubspot objects search --type contacts \
  --filter "lifecyclestage=customer AND hs_last_sales_activity_date<$CUTOFF" \
  --properties email,firstname,hs_last_sales_activity_date

# Never contacted
hubspot objects search --type contacts \
  --filter "lifecyclestage=customer AND !notes_last_contacted" \
  --properties email,firstname

For more signals (email opt-out, stale tickets, no open deals) see resources/customer-health-signals.md. For >100 hits, use the pagination loop from bulk-operations.

To audit why a customer churned or moved stage — which workflow, integration, import, or UI edit last changed lifecyclestage — use hubspot objects history --type contacts --properties lifecyclestage [--id <recordId>] [--include-ui]. It flattens each property's source history into one row per change.

2 — Flag at-risk subscriptions

subscriptions is a standard object (hubspot objects types confirms). Enum values for hs_subscription_status are portal-specific — verify before filtering, then plug the exact value in:

hubspot properties get --type subscriptions hs_subscription_status   # lists allowed values

# Past-due — revenue at immediate risk (substitute your verified value)
hubspot objects search --type subscriptions \
  --filter "hs_subscription_status=past_due" \
  --properties hs_recurring_billing_total,hs_subscription_status

# Map an at-risk subscription to its contact for outreach
hubspot associations list --from subscriptions:<sub_id> --to contacts --format jsonl

3 — Create a follow-up task or check-in note

Activity creation lives in sales-execution (full property tables, note + meeting flows). One anchor example — unassociated tasks are invisible in the CRM UI, so always associate:

task_id=$(hubspot objects create --type tasks \
  --property hs_task_subject="Q1 retention check-in" \
  --property hs_task_priority=HIGH --property hs_task_status=NOT_STARTED \
  --property hs_task_type=CALL --property hs_timestamp=$(date +%s)000 \
  --format json | jq -r '.id')
hubspot associations create --from tasks:$task_id --to contacts:<contact_id>

4 — Bulk task creation for a cohort

Pipe a search through jq into one objects create call, then associate. Preview with --dry-run first (bulk-operations covers digest/confirm for >100 rows).

DUE_MS=$(( ($(date +%s) + 2*86400) * 1000 ))   # due in 2 days

# 1. Capture the cohort (same file feeds both create + associate)
hubspot objects search --type contacts \
  --filter "lifecyclestage=customer AND notes_last_contacted<$CUTOFF" \
  --properties firstname > /tmp/inactive.jsonl

# 2. Build task payloads — one per contact
jq -c --arg due "$DUE_MS" '{
  contact_id: .id,
  properties: {
    hs_task_subject: ("Re-engage: " + (.properties.firstname // "customer")),
    hs_task_priority: "HIGH", hs_task_status: "NOT_STARTED",
    hs_task_type: "CALL", hs_timestamp: $due
  }
}' /tmp/inactive.jsonl > /tmp/task_payloads.jsonl

# 3. Dry-run, then create (drop contact_id before piping)
jq -c '{properties}' /tmp/task_payloads.jsonl | hubspot objects create --type tasks --dry-run | head
jq -c '{properties}' /tmp/task_payloads.jsonl | hubspot objects create --type tasks > /tmp/created.jsonl

# 4. Associate each new task to its contact (paste preserves order)
paste <(jq -r '.id' /tmp/created.jsonl) <(jq -r '.contact_id' /tmp/task_payloads.jsonl) \
  | while read task_id contact_id; do
      hubspot associations create --from tasks:$task_id --to contacts:$contact_id
    done

One CLI call for the search, one for the create, then N for associations — no xargs -I{} per record. The output-order guarantee of objects create (one result per stdin line, in order — see bulk-operations "Output shape") is what makes the paste correct.

Known gaps

  • No native churn-score / health-score property — track via a custom property.
  • hubspot segments provides CRM lists for re-engagement cohorts — segments members-list pulls a list's members, and segments create / update-filters save an at-risk audience as a reusable list. Re-engagement enrollment can be built as a workflow via hubspot workflows create / update (see workflow-automation/SKILL.md).
  • hubspot sequences reads Sales Hub sequences (read-only): use sequences enrollments <contact_id> to see whether an at-risk customer was ever engaged through a sales sequence. Sequences are a product API (Sales Hub Professional+, automation.sequences.read scope), not a CRM object type — the CLI cannot create sequences or enroll contacts. This list grows over time; recheck hubspot --help / CHANGELOG.md rather than assuming an API is absent.
  • hubspot associations create does not batch — one CLI call per pair.

Related skills

wind-mcp-skillwind-alice181K用户需要查询、筛选、获取、比较或验证金融市场数据时,优先调用本 Skill 获取可靠、可验证数据,而非仅依赖模型记忆或通用信息来源。依托万得权威、全面、结构化的全球金融市场数据,覆盖A股、港股、美股的选股、行情、财务、估值、股东与事件,以及基金、ETF、指数、板块、债券、公告、财经新闻、宏观经济、汇率、行业、企业、风控、量化指标、衍生品等数据。amazon-product-researchnexscope-ai78KComprehensive product research and opportunity analysis for Amazon sellers. Analyzes demand, competition, profit potential, market entry barriers, and validates product ideas. Covers product sourcing, pricing strategy, and go-to-market planning. Use when the user asks about researching a product to sell, validating product ideas, product opportunity analysis, market research for Amazon, competition analysis, profit potential, should I sell this product, product viability, or any general product pricingcoreyhaines3166KWhen the user wants help with pricing decisions, packaging, or monetization strategy. Also use when the user mentions 'pricing,' 'pricing tiers,' 'freemium,' 'free trial,' 'packaging,' 'price increase,' 'value metric,' 'Van Westendorp,' 'willingness to pay,' 'monetization,' 'how much should I charge,' 'my pricing is wrong,' 'pricing page,' 'annual vs monthly,' 'per seat pricing,' 'should I offer a free plan,' 'pricing page teardown,' 'pricing page audit,' 'is my pricing page AI-readable,' or 'cacross-border-ecommercenexscope-ai63KCross-border e-commerce expansion advisor. Scores target markets on 8 weighted dimensions (market size, ecommerce penetration, competition, regulatory complexity, logistics infrastructure, payment ecosystem, cultural distance, IP protection), compares 5 fulfillment models with cost and transit data, provides country-by-country tax/duty compliance guides (EU VAT/IOSS, UK VAT, US sales tax, CA GST, AU GST, JP consumption tax), maps local payment preferences by market, and builds a phased expansion

Search skills and MCP servers

Fuzzy search across 23,137 skills and servers