---
ref: workflow:closed-lost-reengagement
title: Reopen closed-lost deals when something has changed
author: thedogwiththedataonit
tools: [tool:salesforce/query-records, tool:apollo/enrich-person, tool:apollo/enrich-company, tool:lemlist/add-lead-to-campaign, tool:salesforce/create-record]
tags: [capability:enrich-companies, capability:enrich-contacts, capability:enroll-in-sequence, capability:manage-crm, channel:email, has:api, has:cli, motion:outbound]
updated: 2026-09-27
---

# Reopen closed-lost deals when something has changed

Set up the tools below, then run the steps in order for the user, carrying each step's results into the next.

## Inputs

Ask the user for these before you start.

- `lost_between`: how long ago the deal was lost, e.g. 90 to 180 days
- `lost_stage`: the Salesforce opportunity stage for lost deals, e.g. Closed Lost
- `product_changes`: what you shipped since, e.g. SSO and a HubSpot integration
- `campaign_id`: the lemlist campaign that sends the emails, e.g. cam_123
- `email_variable`: the custom variable that campaign's email prints as its body, e.g. drafted_email

## Set up

### Salesforce (tool:salesforce/query-records, tool:salesforce/create-record)

Use the first option your agent supports.

Notes:

- Query records with SOQL: One response holds up to 2,000 records; when there are more, fetch the next batch from `nextRecordsUrl`.

#### MCP (official, remote)

Add this server to your agent's MCP settings, then sign in when asked.

```json
{ "mcpServers": { "salesforce": { "url": "https://api.salesforce.com/platform/mcp/v1/platform/sobject-mutations" } } }
```

- Query records with SOQL: call the MCP tool `soqlQuery`
- Create a record: call the MCP tool `createSobjectRecord`

Note: An admin creates an External Client App and activates the server first. It never deletes records.

#### CLI (official)

Install the command and sign in with it, then confirm it runs.

```sh
npm install @salesforce/cli --global
sf --version
```

- Query records with SOQL: run `sf data query`
- Create a record: run `sf data create record`

Note: Sign in with `sf org login web`; `sf org display` then prints the instance URL and API version.

### Apollo (tool:apollo/enrich-person, tool:apollo/enrich-company)

Use the first option your agent supports.

Notes:

- Enrich a person: A match costs 1 credit, plus 8 for a mobile phone; no match costs nothing. Personal emails and phone numbers are off unless you set `reveal_personal_emails` or `reveal_phone_number`, and phone numbers arrive later at a `webhook_url`.
- Enrich a company: Costs 1 credit per company. To enrich up to 10 companies in one call, use bulk organization enrichment instead.

#### MCP (official, remote)

Add this server to your agent's MCP settings, then sign in when asked.

```json
{ "mcpServers": { "apollo": { "url": "https://mcp.apollo.io/mcp" } } }
```

- Enrich a person: call the MCP tool `apollo_people_match`
- Enrich a company: call the MCP tool `apollo_organizations_enrich`

#### CLI (official)

Install the command and sign in with it, then confirm it runs.

```sh
brew install apolloio/apollo-io-cli/apollo-io-cli
apollo --version
```

- Enrich a person: run `apollo people enrich`
- Enrich a company: run `apollo companies enrich`

### Add a lead to a campaign (lemlist, tool:lemlist/add-lead-to-campaign)

Use the first option your agent supports.

Note: The campaign automates outreach to its leads: confirm it first. `findEmail`, `verifyEmail`, `findPhone` and `linkedinEnrichment` spend credits, and a lead already in the campaign is refused with `400 LEAD_ALREADY_IN_CAMPAIGN`.

#### CLI (official)

Install the command and sign in with it, then confirm it runs.

```sh
npm install -g @lemlist-official/cli
lemlist --version
```

Run `lemlist api POST /campaigns/{campaignId}/leads/`.

#### API (official)

- Base URL: https://api.lemlist.com/api
- Endpoint: `POST /campaigns/{campaignId}/leads/`
- Auth: send the header `Authorization: Basic $LEMLIST_API_KEY`
- Get a key: https://app.lemlist.com/settings/integrations

Note: `LEMLIST_API_KEY` holds the base64 of `:<api key>`, an empty username and the key; 20 requests every 2 seconds per key.

Before step 1, confirm access to each service with its cheapest read-only call, like a list or a search. Never send or change anything to test access.

## Steps

1. **Find lost deals** with Query records with SOQL (Salesforce). Query opportunities in `lost_stage` whose `CloseDate` falls within `lost_between`, with their `Id`, name, close date, account name and website, and each contact role's `ContactId`, name, title and email. Keep one row per contact, once per email; note the opportunities with no contact roles.
2. **Check who is still there** with Enrich a person (Apollo). Match each contact on their email. Keep the ones whose current employer's domain is the account website's domain, with their current title; mark the rest as left or unknown.
3. **Check what changed** with Enrich a company (Apollo). For each account website, keep any funding round dated after the close date.
4. **Write emails** yourself. Draft a three-sentence plain-text email per contact still there that names one change: a funding round from step 3, or else the most relevant item in `product_changes`. Show the drafts to the user.
5. **Queue the emails** with Add a lead to a campaign (lemlist). After the user approves, add each contact to `campaign_id` with their approved email in `email_variable`.
6. **Log it** with Create a record (Salesforce). Create a Task per queued contact, with `WhatId` set to the opportunity `Id` and `WhoId` to the `ContactId`, saying they were contacted again and why.

## Done when

- Every contact on a lost deal in the window is queued, or marked as left, unknown or skipped.
- Each opportunity with a queued contact has a Task, and the user has a summary table with the opportunities that had no contacts.

## Rules

- Use only the services set up above. The read-only calls they need, like listing ids or polling for results, are fine.
- Ask the user before anything that sends messages, costs money, or changes data, and say how many records it touches. One approval covers a batch the user has seen.
- Never print API keys.
