# Calls that were never a conversation

Three different nothings share one word in Connect: `NOT_A_CONVERSATION`. `no_answer` rang and nobody picked up. `not_reached` never rang at all — the dial, the dispatch or the worker failed. A silent failure is worse than both: the call connected and nothing could be said. None of the three creates a lead.

- **Status:** Available
- **Audience:** both
- **Channels:** phone
- **In the app:** #/calls
- **Last verified:** 2026-09-10
- **Canonical:** https://connectbyjbrh.com/docs/phone/not-a-conversation/

## Telling them apart

|  | `no_answer` | `not_reached` | Silent failure |
|---|---|---|---|
| Did it ring? | Yes | No | Yes — and it was answered |
| Did anyone speak? | No | No | No, though both parties were connected |
| Whose problem is it? | The person being called, or the list | The dial, the dispatch or the worker | Connect's |
| How it looks in the record | A short call with no turns | A call that never reached a ringing state | Historically: "the caller hung up before speaking" |
| What to do | Nothing, or call at a better hour | Check line health and worker capacity | Check the greeting path and the model |

The middle column is the one that escalates by itself. Past `HEALTH_MIN_FAILURES` inside `HEALTH_WINDOW_HOURS`, a run of calls that never rang becomes a line-health finding in Needs You, because a line failing to reach anybody is an operational fault rather than a bad day on the phones.

## The silent one

A silent failure is a call the caller answered, held to their ear, and heard nothing from. It has a specific cause with a specific record: when the greeting cannot be said — the synthesis is refused and the model in use takes no generated line — the worker posts `engine_error {at: greeting}` and ends the call with `hangup_by=engine` rather than leaving somebody listening to silence.

The engine then writes `facts.silent_failure` from that event, and `voice.no_conversation` says so, with outcome `not_reached`. Before that chain existed, **five inbound calls on 2026-09-07 sat silent and were recorded as "the caller hung up before speaking"** — a row that is entirely plausible, contains no error, and is false.

> **Careful** This is the failure mode to check first whenever a caller reports dead air. A silent failure produces no turns, no summary and no error anybody notices, so it will not appear on a dashboard of things that went wrong. It appears as a slightly quieter day.

## Why none of them creates a lead

`_capture_lead` creates nothing from a call that was never a conversation. The reasoning is the same as the summariser's floor: a lead is a claim that somebody is interested, and there is no evidence of interest in a phone ringing out. A pipeline fed by dialling volume measures effort and presents it as demand.

The same holds for memory and facts. Nothing is remembered about a person from a call in which they said nothing, so a run of unanswered attempts does not gradually build a profile out of its own failures.

**What is created** — A `Call` row with the outcome, the attempt, the cost and the attribution. The attempt is on the record.
**What is not created** — A lead, a summary, a fact, a memory or a person, unless one already existed.
**What happens to the follow-up** — It is not completed by a call nobody answered. A phone follow-up that could not be placed is retried; one more than 24 hours late is closed as `missed:`.

## Reducing them

1. Split your failures by outcome before changing anything.
   - Result: You know whether you are looking at a calling problem or an engineering one, which are fixed in different places.
2. For `not_reached`, check whether a worker had checked in and whether the fleet had capacity.
   - Result: Admission refuses `not_ready` before a row exists when no worker has checked in for 90 seconds, precisely so the drain can retry rather than burn the follow-up.
3. For silent failures, check whether the greeting was warmed or synthesised live, and whether the model in use accepts a generated line.
   - Result: A greeting that cannot be spoken at all now ends the call deliberately — visible as `engine`, not as the caller.
4. For `no_answer`, look at when you are calling rather than at the stack.
   - Result: The line's hours and the promised time from the call are both in the record, and one of them is usually wrong.

## Questions

### Does an unanswered call cost anything?

It is metered like any other call. A call that reports no model usage is charged from its own duration at the published per-minute rate, so an unanswered attempt is cheap rather than free — which is the honest way for a large outbound list to appear in a ledger.

### Can I make Connect retry a call nobody answered?

A follow-up is the mechanism, not a retry loop inside the call. The promise stays due, the drain attempts it on the next tick within the line's hours, and a promise more than a day late is closed rather than kept — a very late call-back is treated as worse than none.

### How do I know a silent failure happened rather than a caller who really did hang up?

Look for `engine_error` at the greeting and for `facts.silent_failure` on the call. A genuine early hang-up leaves the greeting event showing that the greeting was said. If both are absent on an old row, treat the attribution as uncertain — the vocabulary that distinguishes them is newer than the row.

## Related

- [Call outcomes and dispositions](https://connectbyjbrh.com/docs/phone/call-outcome/)
- [Who ended the call](https://connectbyjbrh.com/docs/phone/hangup-attribution/)
- [The greeting](https://connectbyjbrh.com/docs/phone/greeting/)
- [Phone line health](https://connectbyjbrh.com/docs/phone/phone-health/)
- [Abandoned calls](https://connectbyjbrh.com/docs/phone/abandonment/)
- [When a call is answered in silence](https://connectbyjbrh.com/research/silent-failure/)

## What this page is based on

- AGENTS.md §9a — `NOT_A_CONVERSATION` and lead capture (via docs-source/sources/PHONE.md §9)
- PROJECT-STATE.md — five silent inbound calls, 2026-09-07 (via docs-source/sources/PHONE.md §8)
- `backend/app/voice.py` — `no_conversation` and `_capture_lead`
- `backend/app/voice_engine.py` — `line_health` and `ring` refusals
