Human approval without blocking low-risk work
The unit of approval is a rule, not a message. autonomy.py decides per channel across four scopes — contact, endpoint, channel, workspace, narrowest first — so low-risk work runs and only the categories a business chose to hold ever reach a person. Needs You is ranked rather than chronological, and every entry drains by itself once its cause clears.
Deciding once, not per message#
A queue that asks about everything is abandoned in a week, and an agent that asks about nothing is not one a business will switch on. The split that survives contact with a working day is made before anything is drafted: a rule says what this channel may do, and a narrower rule overrides it for the places that matter.
| Mode | Connect writes it | Connect asks | It can go |
|---|---|---|---|
off | No | No | The channel is disabled |
draft_only | Yes | No — deliberately | Only if a person sends it from the conversation |
ask_before_send | Yes | Yes, every time | On approval |
autonomous | Yes | Only when a gate holds it | Within the gates |
Scopes are what keep the mode from being a blunt instrument. A workspace on autonomous can hold one account, one mailbox or one phone number under ask_before_send, because the narrowest applicable scope wins. That is the ordinary way to handle an account where every word matters without slowing everything else down, and it is why the queue length is a consequence of a decision rather than of volume.
What Needs You holds, and what it refuses to hold#
Needs You is the queue of decisions, approvals and operational problems for a person. It is not a notification feed, and the difference is enforced by what gets to create an entry: something a person can act on, or something that is stopping work. Voice line health escalates into it through voice_engine.line_health and operator_ui._voice_line_items, the same items for both audiences.
- A worker that has not checked in — an inbound call would reach nothing at all, which the Phone screen used to describe as "ready".
- A fleet with no capacity left, judged against the same
WORKER_BUSY_LOADof 0.85 the worker gives its own admission control. - Calls that never rang, past
HEALTH_MIN_FAILURESinsideHEALTH_WINDOW_HOURS. - Sessions the model refused.
- Held replies, and the refusals that produced them — a daily allowance spent, a suppressed recipient, a commercial claim Knowledge does not support.
Each of those drains by itself as its cause clears. Nobody dismisses a line-health item; the worker checks in and the item goes. That property is what makes the queue trustworthy as a measure — a long queue means work is genuinely waiting, not that somebody has not tidied up.
Ranked, because waiting is not uniform#
The queue is ordered by what the delay costs rather than by when the item arrived. A held reply to a first-time enquiry is a different kind of debt from a held reply on a thread that has been running for a week, and a chronological list buries the first under the second.
The reason this matters more than it looks is that a held draft is not a slow reply. Nothing has been handed to a provider, so there is no message in flight and nothing in a sent folder — the customer is experiencing silence, and the clock they are counting is still running. Ranking is the only part of the design that knows that.
The audit trail records what was decided, by what, under which rule, and what happened — including refusals, because a refusal is a decision. That is what makes "why did nothing go out on Tuesday" answerable months later without reconstructing anyone's memory.
What the split costs#
- Approving is not always sending
- Where the daily allowance is already spent, the approval is recorded and the send waits. The item stays in the queue until it goes, which reads as an unresponsive button unless you know why.
draft_onlyqueues nothing- Deliberately. A person looking for their draft in Needs You will not find it; it is on the conversation.
- A held draft goes stale
- The thread moves on while it waits. Editing an old draft sends an answer to the older message; regenerating gives the model the newer ones.
- Some work is closed rather than held
- A phone follow-up more than
PHONE_FOLLOWUP_MAX_LATE_HOURS— 24 — late is closed asmissed:and never rung. A very late call-back is worse than none, so that queue empties itself in the other direction.
The drain rate is deliberate too. runner.chase_phone takes two phone follow-ups per tick through the same gates as any outbound call, and a line that is not ready is retried in an hour rather than burned through. An approval queue is only useful while the thing behind it is paced.
Questions#
Can approval be required for one customer only?
Yes, and it is the usual shape. Autonomy resolves across four scopes and the narrowest wins, so a rule set against one contact overrides the channel's and the workspace's. One mailbox or one phone number is the endpoint scope, which does the same job for a line rather than a person.
What clears an item I never acted on?
Its cause. Line-health entries drain when the worker checks in, when capacity returns or when the failure window ages out; a held reply drains when the allowance resets or the suppression is lifted. Nothing needs to be dismissed, which is why the queue's length can be read as a real backlog.
Is there a mode where nothing is ever held?
autonomous is the closest, and it is not unconditional. Compliance runs first — suppression, unsubscribe and do-not-contact — the daily allowance still bounds volume, and a commercial claim Knowledge does not support is still refused and escalated. Those gates are not autonomy settings and are not switched off with one.