← Files Cargo CLIARCHIVED FILE

skills/cargo-gtm/recipes/lost-deal-revival.md

7.54 KB · Sep 30, 2026 · 23:14 UTC

↓ Download file

# Recipe — Revive Closed-Lost deals when the original blocker is gone

Use this recipe when the user wants to systematically revisit **Closed-Lost CRM deals** and only re-engage the ones where the *original lost-reason* is no longer relevant. Tighter scope than [`re-engagement.md`](re-engagement.md): input is explicitly Closed-Lost deals from the CRM (HubSpot, Salesforce, etc.), and the scan branches on `lost_reason`.

**Trigger phrases:**

- *"Revisit Closed-Lost deals where the champion left."*
- *"Find lost deals worth reopening — anyone who lost on budget but just got funded?"*
- *"Replay our Closed-Lost pipeline against current signals."*
- *"Which lost deals are revivable this quarter?"*

## Why this recipe exists

Most Closed-Lost deals stay lost. But specific lost-reason categories have specific revival triggers:

| `lost_reason` | Revival trigger |
|---|---|
| `champion_left` / `no_decision_maker` | Original contact moved to a new company (`waterfall.detectJobChange`) — warm intro at the new account. |
| `price` / `budget` / `no_budget` | Company raised a fresh round (`cargo.fetchBusinessEvents`). |
| `wrong_time` / `timing` | A re-org or new exec hire (`salesNavigator.searchLeads` with `seniority: ["VP+", "C-Level"]` filter, joined date < 90d). |
| `feature_gap` / `missing_feature` | Manual — replay based on your product release date vs. deal close date. |
| `competitor_won` | Annual revisit at renewal time — check competitor satisfaction signals if available. |

The recipe runs each branch only against deals with the matching reason, keeping credit spend bounded.

## Recipe

### Step 1 — Pull Closed-Lost deals from the CRM

```bash
cargo-ai storage model list  # find the Deals / Opportunities model UUID
DEALS_MODEL=...

cargo-ai segmentation segment fetch \
  --model-uuid "$DEALS_MODEL" \
  --filter '{"conjonction":"and","groups":[{"conjonction":"and","conditions":[
    {"kind":"string","columnSlug":"stage","operator":"is","values":["Closed Lost"]},
    {"kind":"date","columnSlug":"closed_at","operator":"olderThan","values":["90d"]}
  ]}]}' > /tmp/lost-deals.json
```

The 90-day floor avoids re-touching deals while they're still mentally fresh with the buyer. Adjust to match the workspace's cooling convention.

### Step 2 — Branch by `lost_reason`

```bash
jq -c '[.records[] | select(.lost_reason == "champion_left" or .lost_reason == "no_decision_maker")]' /tmp/lost-deals.json > /tmp/lost-champion.json
jq -c '[.records[] | select(.lost_reason == "price" or .lost_reason == "budget" or .lost_reason == "no_budget")]' /tmp/lost-deals.json > /tmp/lost-budget.json
jq -c '[.records[] | select(.lost_reason == "wrong_time" or .lost_reason == "timing")]' /tmp/lost-deals.json > /tmp/lost-timing.json
```

### Step 3a — Champion-left branch: detect job changes

```bash
cargo-ai orchestration action execute-batch \
  --action '{"kind":"connector","integrationSlug":"waterfall","actionSlug":"detectJobChange"}' \
  --records "$(jq -c '[.[] | {
    professional_email: .primary_contact_email,
    contact_linkedin: .primary_contact_linkedin,
    company_domain: .account_domain
  }]' /tmp/lost-champion.json)" \
  --wait-until-finished > /tmp/champion-changes.json

# Keep MOVED rows — the contact is at a new (target) company
jq -c '[.results[] | select(.status == "MOVED")]' /tmp/champion-changes.json > /tmp/revive-champion.json
```

### Step 3b — Budget branch: detect fresh funding

```bash
cargo-ai orchestration action execute-batch \
  --action '{"kind":"connector","integrationSlug":"cargo","actionSlug":"matchBusiness"}' \
  --records "$(jq -c '[.[] | {domain: .account_domain}]' /tmp/lost-budget.json)" \
  --wait-until-finished > /tmp/budget-matched.json

cargo-ai orchestration action execute-batch \
  --action '{"kind":"connector","integrationSlug":"cargo","actionSlug":"fetchBusinessEvents"}' \
  --records "$(jq -c '[.results[] | select(.business_id) | {business_id, event_types: ["funding"], since: "180d"}]' /tmp/budget-matched.json)" \
  --wait-until-finished > /tmp/budget-events.json

# Keep deals where a funding round closed AFTER the original deal lost
jq -c '[.results[] | select((.events // []) | length > 0)]' /tmp/budget-events.json > /tmp/revive-budget.json
```

### Step 3c — Timing branch: detect new exec hires at the account

```bash
cargo-ai orchestration action execute-batch \
  --action '{"kind":"connector","integrationSlug":"salesNavigator","actionSlug":"searchLeads"}' \
  --records "$(jq -c '[.[] | {
    company_domain: .account_domain,
    seniority: ["VP+", "C-Level"],
    function: ["Sales","Revenue Operations","Engineering"],
    joined_within_days: 90
  }]' /tmp/lost-timing.json)" \
  --wait-until-finished > /tmp/timing-execs.json

# Keep accounts with at least one fresh exec hire
jq -c '[.results[] | select((.leads // []) | length > 0)]' /tmp/timing-execs.json > /tmp/revive-timing.json
```

Adjust the function list to match where your buyer typically sits.

### Step 4 — Merge into a single revive segment

```bash
jq -c -n '
  ([inputs[0][] | {deal_id: .deal_id, account_domain: .company_domain, revival: "champion_changed", details: .new_company}] +
   [inputs[1][] | {deal_id: .deal_id, account_domain: .domain, revival: "fresh_funding", details: .events[0]}] +
   [inputs[2][] | {deal_id: .deal_id, account_domain: .company_domain, revival: "new_exec", details: .leads[0]}])
' /tmp/revive-champion.json /tmp/revive-budget.json /tmp/revive-timing.json > /tmp/lost-revival.json
```

### Step 5 — Hand off to outreach activation

Pass `/tmp/lost-revival.json` to [`outreach-activation.md`](outreach-activation.md). The `revival` field becomes the `signal_summary` input to the personalization prompt — *"They lost on budget, but just raised a $40M Series B"* writes much better cold-email copy than a generic signal.

## Recurring scan (cron / play)

For ongoing revival:

1. Trigger: monthly cron (lost deals don't churn signals fast enough for weekly).
2. Source: Closed-Lost deals segment with `closed_at older than 90d`.
3. Nodes: branch by `lost_reason` → run matching detector → union → write to "Lost — revival candidates" segment.

For play setup, see [`../../cargo-orchestration/references/examples/plays.md`](../../cargo-orchestration/references/examples/plays.md).

## Credit budget

For a 300-deal Closed-Lost cohort, scanned monthly:

| Branch | Per record | Records (assumed 1/3 each) | Subtotal |
|---|---|---|---|
| `waterfall.detectJobChange` | 3 | 100 | 300 |
| `cargo.matchBusiness` + `fetchBusinessEvents` | 0.6 | 100 | 60 |
| `salesNavigator.searchLeads` | 2 | 100 | 200 |
| **Total monthly** | — | 300 | **560** |

Much cheaper than the broader [`re-engagement.md`](re-engagement.md) scan because each branch only runs on the relevant subset.

## Action shape

Every action follows: `{"kind":"connector","integrationSlug":"<slug>","actionSlug":"<slug>"}`. **No `connectorUuid` in `config`** — see [`../../cargo-orchestration/references/examples/actions.md`](../../cargo-orchestration/references/examples/actions.md).

## Output retrieval

For batch runs, use `cargo-ai orchestration run download-outputs --workflow-uuid <uuid> --output-node-slug <slug>`. See [`../references/output-retrieval.md`](../references/output-retrieval.md).

## Related

- [`re-engagement.md`](re-engagement.md) — broader: any stale contact, not specifically Closed-Lost deals.
- [`icp-discovery.md`](icp-discovery.md) — upstream: surfaces *why* deals are being lost (Closed-Won vs Closed-Lost diff), which informs the lost-reason categorization here.
- [`outreach-activation.md`](outreach-activation.md) — downstream: turns the revival segment into send-ready outreach.

SHA-256: ed67de782fc0f862d8391dcfc1f85355782640c9e9ec63b3eb751c55ef37bbcb