# Why a sales agent should refuse to answer

A price, a delivery commitment or a warranty that Knowledge does not support is refused and passed to a person rather than improvised. `safe_sales` treats that refusal as the correct outcome rather than a gap to close, because an invented commercial term binds a business to something nobody agreed. On the realtime voice path the rule can only live in the instructions, so a breach is detected rather than prevented.

- **Status:** Available
- **Audience:** both
- **In the app:** #/pipeline, #/knowledge
- **Last verified:** 2026-09-10
- **Canonical:** https://connectbyjbrh.com/research/safe-refusals-in-sales/

## The questions that create an obligation

Most of what a customer asks is a question about facts, and an agent grounded in a workspace's own Knowledge answers those well. A small set is different in kind: the answer is not information, it is a commitment, and the business is bound by it whoever typed the sentence.

- **Price, discount and terms** — what something costs, what can be taken off, what the payment terms are.
- **Time and service commitments** — how fast, by when, what happens if it slips.
- **Warranty and liability** — what is covered, for how long, and who bears a loss.

The failure is not that a model gets these wrong at random. It is that a model asked a direct commercial question produces a fluent, specific, plausible answer — which is exactly the kind of answer a customer quotes back later.

## Refusing is the behaviour, not the bug

`safe_sales.py` refuses a commercial term Knowledge does not support and escalates it. That reads as a limitation until you price the alternative: a single improvised discount on a live call is worth more than the entire efficiency gain of automating the conversation, and a customer who was told a delivery date is entitled to it.

This is why the refusal is written down as correct rather than logged as unhandled. A gap invites somebody to close it — by adding a fallback price, by widening what counts as supported. Naming it as the designed outcome changes the review question from *why did it refuse* to *why is this not in Knowledge yet*, which is the question with a useful answer.

## Prevented on one path, detected on the other

The carrier voice path and email both run each generated sentence through the check before anything leaves, so a priced sentence never reaches the customer. The realtime path is different by construction: the model speaks directly to the caller, and nothing sits between its output and the line.

| Path | Mechanism | Guarantee |
|---|---|---|
| Email and turn-based voice | Checked before the sentence is sent or spoken | Prevention |
| Realtime voice | The rule lives in the instructions; `price_spoken` counts the lines the voice priced | Detection after the fact |

`price_spoken` deliberately uses the **same expression** the carrier path checks each sentence with, so the two paths agree on what a price is. Without that, the detector and the preventer would drift apart and the realtime numbers would mean something slightly different from the email ones — which is worse than not measuring.

> **Careful** Detection is not prevention. A workspace whose calls need a hard commercial guarantee should keep pricing conversations on a path where the sentence can be stopped, or hold the reply for approval.

## Keeping the deal alive while refusing

1. The agent declines to state the term and says a person will confirm it.
   - Result: The customer has an answer that is true, and no commitment has been created.
2. The opportunity is raised for review (`raise_for_review`) with the question attached.
   - Result: It appears for a person with the context around it rather than as a bare alert, and `clear_review` closes it when the answer exists.
3. A follow-up is created with its reason, on the channel that suits the answer.
   - Result: The commitment to come back is itself recorded, so the refusal does not become silence.

The Assistant's rights are narrower than a person's for the same reason: it cannot set pricing, and it cannot clear a do-not-contact entry. Two capabilities are operator-only because they are the business of running the platform rather than using it — verifying customer payments, and JBRH's own pricing.

## Where this is still weak

- A refusal that sounds like a stonewall costs the deal anyway. The wording is part of the mechanism, not decoration around it.
- Knowledge that is out of date produces confident wrong answers that the rule does not catch, because the term *is* supported — by a stale source.
- The realtime detector counts priced lines; it cannot count the ones that were correctly refused, so the rate on live calls is UNKNOWN here.
- A customer can extract a commitment by implication — *so that would be within the week?* — which reads as agreement rather than as a stated term.

## Questions

### Why not let the agent quote a price if the price is in Knowledge?

It does. The rule is about terms Knowledge does not support, not about secrecy. The distinction is what makes it workable: a workspace that puts its published terms into Knowledge gets an agent that answers them, and one that has not gets an agent that says a person will confirm.

### Is a refusal recorded anywhere?

Yes. The audit trail records what was decided, by what, under which rule, and what happened — refusals included, because a refusal is a decision. It is also the cheapest way to find out which questions your Knowledge is missing.

### Can the rule be switched off for a trusted workspace?

The safer instrument is the autonomy mode. Holding replies for approval on the channel where commercial questions arrive gives a person the last word without removing the check, which is a different thing from letting an agent improvise terms.

## Related

- [Sales in Connect](https://connectbyjbrh.com/docs/sales/)
- [Why uncertainty is a valid answer from a business agent](https://connectbyjbrh.com/research/uncertainty-is-an-answer/)
- [Separating the agent's authority from the person's](https://connectbyjbrh.com/research/authority-separation/)
- [Knowledge in Connect](https://connectbyjbrh.com/docs/knowledge/)
- [Making a next-best-action defensible](https://connectbyjbrh.com/research/evidence-for-next-action/)

## What this page is based on

- `docs-source/sources/CHANNELS.md` §6 — `safe_sales`, `price_spoken` and the review flags
- `docs-source/sources/GENERAL.md` §5 and §8 — the audit trail and the Assistant's narrower rights
- `docs-source/sources/GENERAL.md` §1 — the two operator-only capabilities
- Connect capability registry (`docs-source/facts.py`) — `CAPABILITY_STATUS`
