D3 — intent
Traced at commit e53d0dc ·
libs/contracts/src/lib/{vector-resolution,extractor,canonicalization,contracts,outbox}.ts ·
libs/temporal/src/{workflows,activities}/call-attempt.ts ·
apps/worker/src/main.ts · live state read 10 September 2026
Summary
- D3 records what the person intends. It holds one value or nothing.
- Five values exist. The model can also answer
UNKNOWN, which the platform discards. - Two values give
not_qualified. Three givequalified_no_action. - D3 is the last step of the headline waterfall. Every other dimension outranks it.
- The voice provider can set one value only:
INTERESTED. It sets D4QUALIFIEDat the same time. - That rule needs a field named
qualified. No live agent declares it. - The phrase list and the model run on every answered call.
- Step 1 never sets D3 on a real call, so steps 2 and 3 decide every real D3 value.
- The phrase list checks values in a fixed order. Any refusal phrase beats any interest phrase.
- In a test, a caller who answered a greeting with
I'm goodbecameNOT_INTERESTED. - The outbox reads D3 directly.
NOT_INTERESTEDcan send the client anot_interestedemail.
Workflow 1 — where the value comes from
Step 1 — the voice provider
- The platform reads
call_successfulfrom the analysis. It readsqualifiedfrom the custom analysis data. - When both are the boolean
true, step 1 sets D3INTERESTED. - The same rule sets D4
QUALIFIED. From step 1, the two values always arrive together. - When
call_successfulis true andqualifiedis not true, step 1 sets only D4. - Step 1 cannot set
NOT_INTERESTED,CALLBACK_REQUESTED,MORE_INFO_NEEDEDorOBJECTION. - No live agent declares
qualified, so step 1 never sets D3 on a real call. - Steps 2 and 3 therefore decide every real D3 value.
- See D4 — qualification for the effect of that missing field on the headline.
Steps 2 and 3
- The phrase list and the model work as they do for D2. See D2 — who answered.
- The D3 list holds 55 phrases. Their confidence runs from 0.85 to 0.95.
- Step 2 checks the values in this order:
NOT_INTERESTED,INTERESTED,CALLBACK_REQUESTED,MORE_INFO_NEEDED,OBJECTION. - A refusal phrase anywhere in the call therefore beats an interest phrase anywhere in the call.
- Step 2 reads the agent’s words too. In a test, an agent line with
Sounds good.setINTERESTED. - Step 3 fills D3 only when no phrase matched. The platform discards an
UNKNOWNanswer.
Workflow 2 — what each value does
- D3 decides the headline only when D5, D6, D1, D2 and D4 all give no headline.
- A D3 value from steps 2 and 3 reaches the headline only when step 1 left it at
needs_review. NOT_INTERESTEDandOBJECTIONgivenot_qualified.INTERESTED,CALLBACK_REQUESTEDandMORE_INFO_NEEDEDgivequalified_no_action.- The headline has no callback value. A scheduled callback comes from D6 or from a callback tool call.
The outbox
- The outbox reads D3 after the headline and the tool calls.
- A stop request, a booking, a transfer, or a callback (booked or ASAP) comes first.
- If none of those applies,
NOT_INTERESTEDgives the outbox outcomenot_interested. - The outbox ignores the other four D3 values.
- An outbox outcome makes the workflow run
notifyOutbox, which emails the client’s CRM.
Workflow 3 — one greeting
- The test ran the real extractor on the two turns in the diagram.
- A model stub answered
INTERESTEDwith confidence 0.9. - The extractor returned
NOT_INTERESTEDat 0.9, from the phrasei'm good. - The caller used the phrase to answer a greeting. The caller then asked to hear more.
- Step 2 checked
NOT_INTERESTEDfirst and stopped. It never reachedtell me more. - The merged result had the headline
not_qualified, confidence 0.9 and no review. - A real call with that greeting gets the same result.
- The table below shows more lines from the same tests.
| Transcript | Step 2 result | Matched phrase |
|---|---|---|
No thanks. Actually, wait, tell me more. | NOT_INTERESTED | no thanks |
We already have a line of credit, but I'm interested. | NOT_INTERESTED | already have |
We're good on cash flow for now, but tell me more. | NOT_INTERESTED | we're good |
I'll pass that on to my husband. | NOT_INTERESTED | pass |
Agent: Sounds good. Caller: I need to talk to my partner first. | INTERESTED | sounds good |
What else do you need from me? | INTERESTED | what else |
The phrase list
Step 2 checks the rows from top to bottom. The first row with a match wins. Dictionary version 1.0.
| Order | Value | Confidence | Phrases |
|---|---|---|---|
| 1 | NOT_INTERESTED | 0.90 | not interested · no thank you · no thanks · don't need it · don't want it · pass · i'll pass · not for me · we're good · i'm good · already have · not looking |
| 2 | INTERESTED | 0.90 | i'm interested · i am interested · im interested · tell me more · sounds good · i want to know more · yes please · that's interesting · go ahead · i'd like to hear · keep talking · what else · i'm listening · sounds promising |
| 3 | CALLBACK_REQUESTED | 0.95 | call me back · call back later · try again later · not a good time · bad time · busy right now · i'm driving · i'm in a meeting · call tomorrow · call next week · can you call later |
| 4 | MORE_INFO_NEEDED | 0.85 | send me information · email me · send me details · need to think about it · let me think · need to discuss · talk to my spouse · talk to my partner · need more time |
| 5 | OBJECTION | 0.85 | too expensive · can't afford · not in the budget · don't trust · sounds like a scam · is this a scam · don't believe · not falling for · heard this before |
Known defects
- Value order beats word order. Any refusal phrase beats any interest phrase, wherever each one occurs.
- Step 2 reads the agent. An agent line with
sounds goodorgo aheadsetsINTERESTED. - Short phrases match ordinary speech.
pass,i'm good,we're good,already haveandwhat elseoccur in calls with other intents. - Step 1 ties D3 to D4. Step 1 sets
INTERESTEDonly withQUALIFIED. An interested person who does not qualify gets no D3 value. - Three values share one headline. The headline cannot separate a callback request from interest.
- A false refusal reaches the client. A wrong
NOT_INTERESTEDcan send anot_interestedemail to the client’s CRM. - The outbox ignores the headline for D3. A
wrong_numbercall withNOT_INTERESTEDstill givesnot_interested. The outbox comment says a CRM should not hear about a wrong number. - One label for two sources. Step 2 and step 3 both write
llm.
What rehearsal data can show
- A sample of about 1% of stage attempts held 338 D3 values.
- The phrase list set 244 of them. The phrase
go aheadset 203. - The simulator’s caller line
Yeah, go ahead.produces those matches. - The impersonated model set 63. Step 1 set the other 31.
- A rehearsal therefore tests the phrase list against a script. It does not measure a real caller.
D2 — who answered — the gate, and the phrase list reading the agent.
D4 — qualification — the value that outranks D3.
Outcome resolution — how D3 fits among the seven dimensions.