# Spending research budget where it changes a decision

A deeper pass is worth running only where its result could change what happens next. `prospect_cost_router` applies that test before spending, so a candidate already ruled out on cheap evidence is not researched further, while one whose fate turns on a single unknown is. The same principle governs model spend on calls: a budget check before dialling, and a breaker that skips scheduled work while still answering a live caller.

- **Status:** Available
- **Audience:** both
- **In the app:** #/prospects, #/billing
- **Last verified:** 2026-09-10
- **Canonical:** https://connectbyjbrh.com/research/research-cost-routing/

## The test is about the decision, not the price

The usual way to control research spend is a cap: so many enrichments per day, so many pages per prospect. A cap controls the total and says nothing about which spending was worth it, so the expensive pass runs on the first hundred candidates in the queue rather than on the hundred where it matters.

The routing test is different. Before a deeper pass runs, the question is whether any plausible answer would change the next action. If a candidate is already disqualified by criteria the cheap evidence settled, a richer profile changes nothing and is not fetched. If the whole judgement rests on one unknown — whether they sell into a segment, whether the site is live, whether a named role exists — that is exactly where a deeper pass pays.

## Cheap first, and only then expensive

1. **Candidate shape** — what discovery already returned. Effectively free, and enough to eliminate a large share of candidates outright.
2. **Published sources** — reading what an organisation says about itself. This is where most evidence comes from, and every claim it produces carries its source.
3. **A deeper pass** — routed, not automatic, and only where the result could move the decision.
4. **Re-research** — governed by `prospect_freshness`, so a record is refreshed when it has aged rather than every time it is looked at.

> **Note** Routing spend is not the same as saving it. The output of the rule is often *more* money on one candidate than a flat policy would have allowed, and none at all on the twenty either side of it.

## The same principle governs the model bill on a call

Voice makes the argument concrete because a live call spends continuously. Metering is split by modality rather than by total, since audio tokens run about **4× the same model's text rate on input** and roughly **2.7× on output**, and `brief.usage_summary` reads the breakdown the SDK actually reports. `merge_usage` adds every session a call held, because a restart used to bill only the survivor.

| Check | Before what | Behaviour |
|---|---|---|
| `budget_refusal` | An outbound call, and answering an inbound one | A refused inbound hears the spoken closed-line message, not silence |
| `ai_quota` breaker | Any model call after a 429 or a revoked key | Scheduled work is skipped; a caller already on the line is still attempted |
| `sweep_stale` | Continuously, from the engine tick and the worker heartbeat | Holds every provider to the configured cap and charges what it closes |
| Zero-token fallback | Billing a finished call | A call reporting no tokens is charged from its own duration, never at zero |

The breaker's asymmetry is the routing rule in miniature: the same refusal applied uniformly would drop a person mid-sentence to protect a budget. `sweep_stale` exists because a browser call has no worker to close it and one sat *active* for **24.78 hours**.

## What the measurements can and cannot say

`GET /api/usage/voice` is the per-call profiler. Its useful property is that it reports what was measured and **says what was not**, rather than filling the gap with an estimate — which is how a wrong figure becomes a trusted one. An early version looked for an `input_audio_duration` the SDK does not report and recorded 0.0 seconds for every call ever metered.

For prospecting, the saving attributable to routing is **UNKNOWN** here. No controlled comparison against a flat policy has been run, and the honest position is that the rule is defensible on its logic and not yet on a measured delta. The counting fix described in [evidence-first prospecting](/research/evidence-first-prospecting/) is a prerequisite for ever measuring it, because headline numbers that stopped at 500 could not have shown the difference.

## How the rule fails

- **The decision boundary is wrong.** If qualification criteria are badly drawn, the router faithfully avoids spending on the candidates that would have overturned them.
- **Cheap evidence is stale.** Eliminating on an old published fact is a false economy that freshness rules only partly cover.
- **Under-research reads as thoroughness.** A short evidence list looks disciplined whether it is disciplined or merely truncated, which is why the record shows what was not established rather than only what was.
- **Spending routed by cost rather than by value** drifts back into a cap. The test has to stay *would this change the next action*, not *is this the cheap option*.

## Questions

### Is this not just lazy evaluation with a business label on it?

Structurally, yes — and that is the point. The work is deferred until something depends on it, and the dependency is a decision rather than a field being read. The label matters because the alternative most teams reach for is a quota, which defers work by arrival order instead.

### Why is a live caller allowed past a breaker that stops everything else?

Because the failure modes are not comparable. A skipped scheduled task runs later; a caller refused mid-conversation hears a business hang up on them. The breaker distinguishes the two rather than protecting the budget uniformly.

### How would I tell whether routing is working in my workspace?

Look for candidates that were stopped early and never revisited, and for deep passes on candidates that were already disqualified. Both are visible on the prospects screen, and both indicate the boundary rather than the router is at fault.

## Related

- [Evidence-first prospecting without guessed emails](https://connectbyjbrh.com/research/evidence-first-prospecting/)
- [Prospecting in Connect](https://connectbyjbrh.com/docs/prospects/)
- [What every character of a prompt costs on a live call](https://connectbyjbrh.com/research/prompt-size-and-first-token/)
- [Phone and voice in Connect](https://connectbyjbrh.com/docs/phone/)
- [Why uncertainty is a valid answer from a business agent](https://connectbyjbrh.com/research/uncertainty-is-an-answer/)

## What this page is based on

- `docs-source/sources/CHANNELS.md` §4 — cost routing and freshness in prospecting
- `docs-source/sources/PHONE.md` §4 — voice metering, budget refusal and `sweep_stale`
- `docs-source/sources/GENERAL.md` §11 — measured facts
- Connect capability registry (`docs-source/facts.py`) — `MEASURED`
