To run a win-loss review every month without a spreadsheet, extract your CRM’s deals, accounts and contacts whole, run the same fixed SQL over the closed ones each month (won versus lost by industry, size and country, plus the lost reasons), and land the findings in your go-to-market repository as one pull request a human merges. The win-loss review cookbook deploys that as one Claude Code harness agent on a monthly cron, three CRM models and a five-line Slack digest.
The problem: what the CRM knows about who buys and who does not ends up in a quarterly deck nobody reopens, while the ICP every scoring and outbound agent reads stays whatever someone wrote a year ago. This puts the evidence where those agents read, with every count next to its denominator.
How it works, end to end #
- The platform extracts the CRM into three models.
crm_deals,crm_accountsandcrm_contacts: every record and every column, refreshed hourly, with no filter in the model config. The queries do the narrowing. - On the 1st of the month at 06:00 UTC, the agent runs the audit. A fixed set of named queries, run with
cargo-ai storage query execute: counts by pipeline, lost reasons, contacts on deals, won versus lost by industry, by size band and by country, titles at won accounts, and the deals closed since the last run. The agent is told to run those and no other SQL, so one month is comparable to the next. No query selects a deal amount. - It states two hygiene findings first. The lost-reason fill rate (“lost reason on 11 of 14”) and the deal-to-contact rate. Under half on lost reasons, and it writes no objection files that month and says why.
- It picks a mode from the won count. With 20 or more closed-won deals in the 365-day window it is in verify mode and states what won versus lost shows. Below that, every finding is written with
confidence: hypothesisand the pull request says how many wins would make it an analysis. - It writes, then appends. The first pass verifies
icp/against the deals and names a disqualifier (a profile that looks like a fit and loses), adds datedinsight/files,objection/files from recurring lost reasons, and oneclient/file per closed-won account. Every month after, it only adds files: personas are never edited, and the ICP only on the first pass. A change the deals suggest is a proposal in the pull request body, with the deal ids. - It records the run, opens one pull request and posts once.
outputs/<date>-win-loss-review/README.mdholds each query’s result, so every[R: <query>]tag in the context files points to something a reader can check. A month with no newly closed deal opens no pull request. After a human merges, the nextcargo-ai project deploysyncscontext/into the workspace context that every other Cargo agent reads.
The Slack digest is five lines and its numbers come only from the queries:
:bar_chart: *Win-loss review Oct 2026*: 23 deals closed
Won 9, lost 14 · lost reason on 11 of 14 · contacts on 19 of 23
Learned: a RevOps title at 6 of 9 won accounts · 8 of 14 losses were under 50 employees
Proposed: add "under 50 employees" as an ICP disqualifier (8 of 14 losses, 0 of 9 wins)
PR: https://github.com/<you>/<repo>/pull/<n>
(Illustrative, fictional records.)
Run it #
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 win-loss-review
cargo-ai project init my-gtm --cookbook win-loss-review && cd my-gtm && npm install
# already have a Cargo project? from its root:
cargo-ai project add cookbook/win-loss-review
Before deploying, set the Slack channel id and languageModel on the agent, and, if your portal records the lost reason on a custom property, set LOST_REASON_COLUMN in infra/agents/win-loss-analyst.prompt.ts (HubSpot’s standard closed_lost_reason ships). cargo-ai project plan should show one agent, three models, the bound connectors and two folders. After cargo-ai project deploy and the first sync, run the pipelines query by hand and confirm both won and lost are non-zero. Then start the first pass yourself:
cargo-ai ai message create --agent-uuid <uuid> \
--parts '[{"type":"text","text":"Run the win-loss review first pass. Follow your system prompt exactly and open one pull request."}]'
The monthly cron takes it from there.
What it needs and what it costs #
| Needs | Why |
|---|---|
| An authorized CRM connector (HubSpot in the example) | The only source; Salesforce and Attio adapt the models and queries |
| An authorized GitHub connector | The agent’s only write path: a branch and a pull request |
| An authorized Anthropic connector | The harness runs on Cargo’s model proxy, billed to it |
| An authorized Slack connector | The digest, through postMessage with the channel locked |
A repository with context/ and outputs/ | The shape cargo-ai project init scaffolds |
Cost, from the code: the HubSpot fetchRecords extractor and Slack’s postMessage carry no Cargo credit price in their definitions, and the SQL queries are not billed actions. The recurring cost is model usage for one harness run a month, scaling with how many deals closed since the last one, plus the first pass over the whole window. Nothing in the cookbook needs a credential in .env.
What it will not do #
- It does not read calls, an inbox, a website or Slack. The CRM is its only source; keeping company and competitor context fresh from the web is a separate cookbook, so a page and a deal never end up at one confidence level in one file.
- It does not write to the CRM, select a deal amount, contact a customer or merge its own pull request.
- It does not write the workspace context directly. The pull request is the gate; the agent has no
contextcapability. - It does not edit a persona, or the ICP after the first pass.
One status note from the cookbook itself: it is marked to-be-approved, meaning it has not yet been deploy-verified against a live workspace. Treat its acceptance list as the test and read the plan before you deploy.
Related: the verified ICP is what account scoring reads, and the closed-won accounts feed expansion signals before renewal.
Frequently asked questions #
The cookbook draws the line at 20 closed-won deals in a 365-day window. At or above it, won versus lost is treated as an analysis. Below it, the same files are written with confidence hypothesis and every count carries its denominator. Both numbers are constants in the prompt file you can change.
The agent reports the fill rate on every run, for example 4 of 9, and writes no objection files when it is under half. A rate of zero with lost deals in the window usually means the reason lives on a custom property, which you name in LOST_REASON_COLUMN.
The checked example is HubSpot. Salesforce and Attio change the connector, the three models’ config and the queries together, following the CRM audit reference in the cookbook, and the first pass should be checked by eye.