Use cases / Customer analytics
Which deals are most likely to close
Which deals close this quarter, and what could stop them.
- Unit
- One opportunity, all its calls this quarter
- Ask
- Next step? Objection? Stage? Then: likely to close by the date?
- Get
- Ranked deals with p(close) and the top risk
Fireflies · Attio · 2 reducers · 5 questions · updated Sep 21, 2026
The flow
Score every call once. Then score every deal with its calls and its record. 137 requests for 96 calls and 41 deals. Replay last quarter for the calibration table.
Follow one record
- calls
- Call signals
- Group by opportunity
- Attach the record
- Close likelihood
- Outputs
Three calls this quarter
snapshot v8, transcripts C-0871, C-0902, C-0917
- C-0871 Aug 21Discovery. Ops lead describes manual dispatch reconciliation, 3 people, 2 days a week.
- C-0902 Sep 9Demo with the VP. Asked about pricing per depot. Wants a pilot in the Ohio region.
- C-0917 Sep 18VP: “If you can land at 40 per seat we sign this month. Legal has the paper.” Owner: Priya, redline by Sep 24.
Request 27 of 96
call C-0917, model jev-1.13.0, attempt 1, succeeded
- true0.88
named owner and a date
- pricing0.71
- none raised0.17
- timing0.08
- integration effort0.03
- security and compliance0.01
confidence 0.69, provider reported
- Discovery0.00
- Evaluation0.02
- Validation0.36
- Negotiation0.58
- Verbal commitment0.04
between Validation and Negotiation, leaning Negotiation
{
"model": "jev-1.13.0",
"state": {
"call_id": "C-0917",
"opportunity_id": "OPP-3312",
"date": "2026-09-18",
"transcript": [
{ "speaker": "VP Operations", "text": "If you can land at 40 per seat we sign this month. Legal already has the paper." },
{ "speaker": "AE", "text": "I can take 40 to our side today. What do you need from us by when?" },
{ "speaker": "VP Operations", "text": "Redline back to Priya by the 24th. She owns it." }
]
},
"questions": {
"next_step": { "type": "noul",
"instructions": "Did the prospect in `transcript` commit to a specific next step with a named owner or a date?" },
"objection": { "type": "choice",
"instructions": "Which objection, if any, dominates `transcript`?",
"criteria": { "pricing": "Price, discount or budget",
"security_compliance": "Security review, compliance or data handling",
"integration_effort": "Effort to integrate or migrate",
"timing": "Not now, later quarter, other priorities",
"none_raised": "No objection was raised" } },
"stage": { "type": "score",
"instructions": "How far along is the buying process as evidenced in `transcript`?",
"criteria": ["Discovery", "Evaluation", "Validation", "Negotiation", "Verbal commitment"] }
}
}
{
"model": "jev-1.13.0",
"answers": {
"next_step": { "probability": 0.88 },
"objection": { "choice": "pricing",
"probabilities": { "pricing": 0.71, "none_raised": 0.17, "timing": 0.08,
"integration_effort": 0.03, "security_compliance": 0.01 },
"confidence": 0.69 },
"stage": { "expected": 3.64, "probabilities": [0.00, 0.02, 0.36, 0.58, 0.04], "confidence": 0.58 }
}
}
Three scored calls become one unit
deterministic, no model call
- key
- OPP-3312
- members
- C-0871, C-0902, C-0917
- next step committed
- 0.12, 0.41, 0.88 across the three calls
- latest stage
- 3.64 on the last call
The Attio opportunity record
left key input.key, right key id
- company
- Halyard Freight
- ARR
- 48,000
- close date
- 2026-09-30
- CRM stage
- Proposal
- owner
- Priya Nair
Request 12 of 41
model jev-1.13.0, attempt 1, succeeded
- true0.79
conditioned on these calls and this record
- pricing0.62
- timing0.21
- none0.10
- no decision owner0.05
- security review0.02
confidence 0.57, provider reported
{
"model": "jev-1.13.0",
"answers": {
"close": { "probability": 0.79 },
"risk": { "choice": "pricing",
"probabilities": { "pricing": 0.62, "timing": 0.21, "none": 0.10,
"no_decision_owner": 0.05, "security_review": 0.02, "champion_left": 0.00 },
"confidence": 0.57 }
}
}
One ranked row
sorted by p(close) in the Outputs table
- opportunity
- Halyard Freight
- p(close)
- 0.79
- latest stage
- Negotiation (3.64)
- next step committed
- yes (0.88, C-0917)
- top risk
- pricing (0.62)
- close date
- 2026-09-30
- trace
- 6 nodes, 4 attempts, 3 call requests and 1 opportunity request
What comes out
| Opportunity | p(close) | Latest stage | Next step | Top risk | Close date | ARR |
|---|---|---|---|---|---|---|
| Gable Manufacturing | 0.91 | Verbal commitment | yes 0.94 | none | 2026-09-26 | 36,000 |
| Halyard Freight | 0.79 | Negotiation | yes 0.88 | pricing | 2026-09-30 | 48,000 |
| Brightwater Labs | 0.64 | Validation | yes 0.71 | security review | 2026-10-14 | 22,000 |
| Corvid Systems | 0.41 | Evaluation | no 0.22 | timing | 2026-10-31 | 60,000 |
| Tidewater Legal | 0.22 | Discovery | no 0.09 | no decision owner | 2026-11-15 | 18,000 |
| Fennel & Co | 0.12 | Evaluation | no 0.15 | champion left | 2026-09-30 | 9,000 |
Synthetic rows in the app's Outputs layout. ARR and dates come from the joined Attio record, not from the model.
Details, if you want them
whyWhy this shape
Why this shape
- Per call first. Next step, objection, stage. One call is the natural unit.
- Per deal second. All its calls plus the record. A true dependency, so a second stage.
- Between them, no model calls. Group, then join.
Make the probability earn its threshold
- Run the same definition on last quarter’s snapshots.
- Join closed-won and closed-lost on
opportunity_id. - Bucket by p(close). Count won and lost per bucket.
- Read the table. That is what 0.8 means for your team.
| p(close) | deals | won | share |
|---|---|---|---|
| 0.90 and up | your number | your number | your number |
| 0.70 to 0.89 | your number | your number | your number |
| 0.50 to 0.69 | your number | your number | your number |
| below 0.50 | your number | your number | your number |
questionsThe 5 questions, verbatim
- Call signals
next_stepbinary, noul
Did the prospect in `transcript` commit to a specific next step with a named owner or a date?
- Call signals
objectioncategorical, choice
Which objection, if any, dominates `transcript`?
pricingsecurity and complianceintegration efforttimingnone raised - Call signals
stageordinal, score
How far along is the buying process as evidenced in `transcript`?
DiscoveryEvaluationValidationNegotiationVerbal commitment - Close likelihood
closebinary, noul
Given the call signals in `calls` and the record in `opportunity`, is this opportunity likely to close by `opportunity.close_date`?
- Close likelihood
riskcategorical, choice
What is the single biggest risk to closing, based on `calls` and `opportunity`?
pricingsecurity reviewchampion leftno decision ownertimingnone
buildHow each stage is built, as JSON
1 reducer Call signals
stage is an ordinal over your own sales stages, so the expected value is a position on that scale, and the distribution shows when a call sits between two stages.stage definition
{
"id": "call_signals",
"input": "source:calls",
"kind": "evaluate",
"model": "jev",
"name": "Call signals",
"questions": {
"next_step": {
"instructions": "Did the prospect in `transcript` commit to a specific next step with a named owner or a date?",
"type": "noul"
},
"objection": {
"criteria": {
"integration_effort": "Effort to integrate or migrate",
"none_raised": "No objection was raised",
"pricing": "Price, discount or budget",
"security_compliance": "Security review, compliance or data handling",
"timing": "Not now, later quarter, other priorities"
},
"instructions": "Which objection, if any, dominates `transcript`?",
"type": "choice"
},
"stage": {
"criteria": [
"Discovery",
"Evaluation",
"Validation",
"Negotiation",
"Verbal commitment"
],
"instructions": "How far along is the buying process as evidenced in `transcript`?",
"type": "score"
}
},
"state_path": []
}2 group Group by opportunity
opportunity_id collects them into one unit per deal. The members are kept, so the trace shows which call said what.stage definition
{
"id": "by_opportunity",
"input": "call_signals",
"key": [
"opportunity_id"
],
"kind": "group",
"name": "Group by opportunity"
}3 join Attach the record
stage definition
{
"id": "with_record",
"input": "by_opportunity",
"kind": "join",
"left_key": [
"input",
"key"
],
"name": "Attach the record",
"right": "source:opportunities",
"right_key": [
"id"
]
}4 reducer Close likelihood
close is a probability conditioned on exactly this evidence; risk names the thing most likely to stop it.stage definition
{
"id": "close",
"input": "with_record",
"kind": "evaluate",
"model": "jev",
"name": "Close likelihood",
"questions": {
"close": {
"instructions": "Given the call signals in `calls` and the record in `opportunity`, is this opportunity likely to close by `opportunity.close_date`?",
"type": "noul"
},
"risk": {
"criteria": {
"champion_left": "The internal champion is gone or disengaged",
"no_decision_owner": "Nobody with authority has committed",
"none": "No material risk visible",
"pricing": "Price or budget",
"security_review": "An open security or compliance review",
"timing": "The buyer's timeline slipped"
},
"instructions": "What is the single biggest risk to closing, based on `calls` and `opportunity`?",
"type": "choice"
}
},
"state_path": []
}5 definition The whole workflow, as saved
Saving publishes an immutable version. A run freezes this definition, the snapshot IDs and each reducer’s model profile, so the trace can always show exactly what ran. Edits create a new version; old runs keep theirs.
jevreduce.local.v1
{
"name": "Which deals are most likely to close",
"schema_version": "jevreduce.local.v1",
"sources": {
"calls": "snap_fireflies_calls_v8",
"opportunities": "snap_attio_opps_v5"
},
"stages": [
{
"id": "call_signals",
"input": "source:calls",
"kind": "evaluate",
"model": "jev",
"name": "Call signals",
"questions": {
"next_step": {
"instructions": "Did the prospect in `transcript` commit to a specific next step with a named owner or a date?",
"type": "noul"
},
"objection": {
"criteria": {
"integration_effort": "Effort to integrate or migrate",
"none_raised": "No objection was raised",
"pricing": "Price, discount or budget",
"security_compliance": "Security review, compliance or data handling",
"timing": "Not now, later quarter, other priorities"
},
"instructions": "Which objection, if any, dominates `transcript`?",
"type": "choice"
},
"stage": {
"criteria": [
"Discovery",
"Evaluation",
"Validation",
"Negotiation",
"Verbal commitment"
],
"instructions": "How far along is the buying process as evidenced in `transcript`?",
"type": "score"
}
},
"state_path": []
},
{
"id": "by_opportunity",
"input": "call_signals",
"key": [
"opportunity_id"
],
"kind": "group",
"name": "Group by opportunity"
},
{
"id": "with_record",
"input": "by_opportunity",
"kind": "join",
"left_key": [
"input",
"key"
],
"name": "Attach the record",
"right": "source:opportunities",
"right_key": [
"id"
]
},
{
"id": "close",
"input": "with_record",
"kind": "evaluate",
"model": "jev",
"name": "Close likelihood",
"questions": {
"close": {
"instructions": "Given the call signals in `calls` and the record in `opportunity`, is this opportunity likely to close by `opportunity.close_date`?",
"type": "noul"
},
"risk": {
"criteria": {
"champion_left": "The internal champion is gone or disengaged",
"no_decision_owner": "Nobody with authority has committed",
"none": "No material risk visible",
"pricing": "Price or budget",
"security_review": "An open security or compliance review",
"timing": "The buyer's timeline slipped"
},
"instructions": "What is the single biggest risk to closing, based on `calls` and `opportunity`?",
"type": "choice"
}
},
"state_path": []
}
]
}limitsWhat it will not do
- p(close) is conditioned on these calls and this record. Not a pipeline forecast.
- Calibrate on last quarter before you threshold.
- Transcription errors propagate.
- No live CRM reads, no write-back. Your code does that.
- No follow-up emails. Jev does not write prose.