Fresh session per sweep — state lives on the HubSpot deal record itself (a
taskstation_renewal_stage_alerted property marks the last window surfaced), not
in a local ledger file. A sweep can find several accounts at once; handle each
as an independent unit — a failure preparing one account's packet is logged
and skipped, never blocking any other account in the same sweep.
Step 0 — Orient: find what crossed a window
Query HubSpot for open deals with {{renewal_date_property}} set:
For each deal, compute days-to-renewal and bucket it into 90 / 60 / 30. Skip a
deal if taskstation_renewal_stage_alerted already equals that bucket — it was
packeted on a prior run. A deal moving into a new, tighter bucket (e.g. 90 →
60) always gets a fresh packet, since more has likely changed.
Step 1 — Read the account's history
Pull the deal's notes, stage history, contract value, and the owner
(hubspot_owner_id → name). Read prior call and email activity to reconstruct
what's been delivered and discussed since the account signed or last renewed.
Step 2 — Build the renewal packet
Assemble, in order:
Usage and value delivered — what the account has actually gotten out of
the product since the last renewal, drawn from notes and activity, in
concrete terms (not "engaged well" — the specific thing that shipped or
got used).
Expansion ideas — one or two concrete, specific opportunities grounded
in what this account does and hasn't used yet. Never a generic "consider
upgrading" line.
Contract terms — current value, renewal date, and term length.
Step 3 — Check Google Calendar (read-only)
Look for an existing renewal or QBR meeting near the renewal date. If one
exists, reference it in the draft ("ahead of our call on ...") instead of
proposing a new one. This is read-only — never create, move, or accept an
event.
Step 4 — Flag at-risk signals
Independent of the 90/60/30 bucket, call out a deal as at-risk when it shows:
Signal
What it means
Stage unchanged for an extended period
Deal has stalled
Contract value trending down vs. last term
Account may be scaling back
No logged activity in a long stretch
Relationship's gone quiet
Notes mentioning a competitor, budget freeze, or churn intent
Explicit risk
At-risk deals get named specifically in {{alert_channel}}, with the signal
that triggered the flag — every day they remain at-risk, not just once.
Step 5 — Draft the outreach
Write the renewal email using the packet: lead with the value delivered, name
the expansion idea if one fits naturally, and reference the scheduled
conversation if Step 3 found one. Hold it in {{draft_channel}} for the account
owner. Never send it, and never write a specific discount, credit, or price
change into the draft — if the account's situation calls for a pricing
conversation, say so in the packet and let the owner handle it.
Step 6 — Post the radar
Post one summary to {{alert_channel}}: accounts newly crossing a 90/60/30
window (owner, renewal date, bucket), and the at-risk list with its signals.
This is the read summary; the packet and draft are the deliverables in
{{draft_channel}}.
Step 7 — Write the marker back
Set taskstation_renewal_stage_alerted on each packeted deal to the bucket just
surfaced (with a timestamp). This is the only HubSpot write — never the deal
stage, amount, or pipeline.