Your GTM belongs in gitRegister
Blog

Spot Expansion Moments in Your Customer Base Before Renewal

16 Oct
6min read

To spot expansion moments before renewal, judge each customer once, when its won deal turns ten months old: read its purchase history and any dated public event (a funding round, a hiring push, a new leader), label it expansion, at_risk, repeat_purchase, renewal or none with a reason, and send the go-to-market team one list a week. The expansion signals cookbook deploys exactly that on Cargo: a weekly play, a read-only analyst agent, three columns on the account, and one Slack digest.

The problem it solves is that the renewal call is usually the first time anyone looks at a customer since it signed. By then the budget is set. We run the same idea on Cargo’s own customer book: the signal shows up weeks before the renewal, in data you already hold, as long as something reads it on a schedule.

How it works, end to end #

  1. Monday 06:00 UTC, a play picks up won deals entering the window. The play runs on a deals model (gtm_opportunities) and enrolls a deal when it is won, has an account_id, and closed between ten and twelve months ago. It uses changeKinds: ["added"], so a deal enters once and each renewal is judged once, not every Monday for two months.
  2. An analyst agent judges the account. It queries the deals model in SQL for every won deal on that account: if a newer win closed more than two months after the trigger, the account already renewed and gets none. Otherwise it states the cadence across wins and the last price paid. It reads your expansion plays from the workspace context, then runs at most three web searches for public events in the last 120 days, keeping only events with a dated source.
  3. The play writes three columns onto the account, by id. expansion_signal, expansion_reason (the reason, the suggested play and the source URLs) and expansion_signal_at. Nothing else is written: no deal, no contact, no owner. The agent itself has read-only access to both models.
  4. Monday 15:00 UTC, a digest agent posts once. It reads the accounts stamped in the last seven days with a signal other than none, posts one Slack message with at_risk first, then expansion, repeat_purchase and renewal, each line with the reason as written on the account and its owner. A ledger model (expansion_digests) keeps it to one post per ISO week, so a re-run posts nothing.

The five labels mean:

SignalWhat it means
expansionAn outside event or usage pattern says they need more
at_riskAn event puts the renewal itself in doubt, such as layoffs or a new leader
repeat_purchaseThe cadence across won deals says the next order is due
renewalThe anniversary is the moment, nothing more
noneNothing to act on, including an account a newer win already renewed

Run it #

shellscript
npm install -g @cargo-ai/cli
cargo-ai login --email you@company.com      # emailed code, no browser, 100 free credits, no card

cargo-ai project cookbook view expansion-signals    # what it asks you for, before anything is written
cargo-ai project init my-gtm --cookbook expansion-signals && cd my-gtm && npm install
# already have a Cargo project? from its root:
cargo-ai project add cookbook/expansion-signals

Then, before the first deploy:

  • Fill the models. The example ships native accounts and deals models, so it deploys with no CRM connector. A native model starts empty: load accounts, then won deals with their account_id, with cargo-ai storage record create-bulk --model-uuid <uuid> --records '[{"data":{...}}]'. A won deal with no account is never judged.
  • Write your expansion plays into the workspace context (context/expansion-plays.md, from the example in the cookbook). Without it, the suggested play is generic advice.
  • Set the Slack channel id (C...) on the digest and the languageModel on both agents.
  • Plan, then deploy. cargo-ai project plan prints the diff: three models, two agents, the play, two connectors and three folders. cargo-ai project deploy applies it. The play ships disabled: run it by hand on five deals, read each reason against its sources, then enable it and execute it once, because an added play does not backfill deals that entered while it was off.

If your customers and deals live in HubSpot, Salesforce or Attio, the cookbook’s crm-backed variation swaps in connector-backed models and writes the three properties back to the CRM company record by id. Create the three custom properties first: a write to a property that does not exist fails every row.

What it needs and what it costs #

NeedsWhy
A Cargo workspace and @cargo-ai/cliThe project is deployed with cargo-ai project
An authorized Anthropic connectorBoth agents run on it
An authorized Slack connectorThe digest’s only post path
Won deals with an account and a close dateThe trigger and the purchase history

Cost, from the code: the native model writes and Slack’s postMessage carry no Cargo credit price in their action definitions, so the recurring cost is model usage on your Anthropic connector: one analyst run per won deal entering its window each week (with up to three web searches inside it) and one digest run. It scales with how many customers are near renewal, not with the size of the book. Count the window before you enable the play: a SELECT count(*) over the deals model with is_won true and close_date ten to twelve months back.

What it will not do #

  • It does not change a deal, a contact or an owner. The only write is three columns on the account.
  • It does not contact a customer or post anywhere but the one locked Slack channel. Locking the channel on the action is deliberate: the digest names customers and their renewal risk.
  • It does not read product usage. The judgment comes from won deals, your written expansion plays and public events. If usage against plan is your strongest signal (it is ours), that is a column you add, not something the example reads.
  • It does not re-judge in Slack. The digest repeats the reason on the account, so the record and the channel never disagree.
  • It judges an annual book by default. Monthly or two-year contracts change the two close_date values in the play.

Related: Customer expansion revenue strategies covers the playbook side, and track job changes catches a champion who left, the first at-risk signal. To verify who expands in the first place, pair it with a monthly win-loss review.

Frequently asked questions #

AurelienOct 16, 2026

Give your agents a runtime

Bring the agents you have.Start free, deploy in one command.