Connect by JBRH Open Connect

Placing outbound calls

An outbound call passes five gates before a number is dialled: consent to be called, any memory block against the contact, the autonomy mode for the voice channel, the budget, and the line's own permission and hours. Both engines dispatch through the same call, so an engine-placed call, a follow-up call and a browser call are gated identically, and a refusal is recorded with its reason.

Status
Available What this means
Audience
both
Channels
phone
In the app
#/calls, #/follow-ups
Last verified
Product version
6.3.2

The gates, in the order they refuse#

GateWhat it checksWhat you see
ConsentWhether this person may be called at all on this channelrefused: consent against the follow-up or the request
Memory blockA block:phone directive stored against the contactThe call is not attempted; the block is visible in Memory and can be forgotten
AutonomyThe mode on the voice channel at the narrowest applicable scopeautonomous places it; ask_before_send queues an approval; draft_only and off do not ask
BudgetWhether the workspace can pay for the call at audio-token ratesrefused: budget, before any dial
LineOutbound permission and hours on the line the call would useA line that is not ready is retried in an hour rather than failed

Everything reaches the carrier through comms_providers.dispatch_call with a placer naming what asked for the call, which is what makes the gating uniform. There is no path that dials a number without passing through it — not the realtime engine, not the follow-up drain, not a person clicking dial in the browser.

Blocking is a memory, not a checkbox#

A block against a contact is a connect_memory row tagged block:phone in its tag list, not a column on the contact. That looks like an implementation detail and is not: because directives() reads only the tag list, a block written once holds across channels, across conversations and into the future, and a person can read it and remove it in the same place they read everything else Connect knows.

It also means a block cannot be quietly lost by a record being merged or recreated, and it cannot be set by accident in the body of a note. If a contact is not being called and consent looks fine, the tag list is the next place to look.

Call-backs the engine places by itself#

Most outbound calls in a working system are not somebody deciding to ring a customer — they are follow-ups coming due. runner.chase_phone drains phone follow-ups on every tick, two per tick, through the same place call path and therefore the same gates. Each attempt is recorded as "call placed", "awaiting approval" or refused: with the reason.

Line not ready
Retried in an hour. Readiness is transient — a worker restart, a saturated fleet — so failing the follow-up would throw away a commitment for a temporary condition.
More than 24 hours late
Closed as missed: and never rung. A call-back a day after it was promised is worse than none, and pretending otherwise makes the record dishonest.
Held for approval
The follow-up stays open and the approval appears in Needs You. Nothing dials until a person says yes.
Work for a person
Follow-ups on the task channel are never dialled by anything. They appear as work for a human and drain only when a human does them.

When the dial itself fails#

A dial that the carrier answers with a timeout — 408, 503 or 504 — is dialled once more, because a timeout is not evidence that anything happened. A leg the carrier reports as answered but which never joins the room is written off after the join timeout instead of being waited for; holding capacity open for a leg that is never coming costs other callers their admission.

A call that never rang at all is not_reached, which is a different outcome from no_answer — the phone ringing with nobody picking up. Neither creates a lead, and the distinction matters when a line's health is being judged: a run of not_reached results points at the dial, the dispatch or the worker, while a run of no_answer results points at the list being called.

Questions#

Can I stop Connect calling one specific customer without turning the channel off?

Yes — that is exactly what a block is for. A block:phone memory against that contact stops calls to them while the rest of the channel carries on, and it survives the contact being updated or the conversation ending.

What does ask_before_send mean on a phone call, when there is nothing to read?

It holds the decision to place the call, not the words. The approval in Needs You says who would be rung and why, and nothing is dialled until somebody agrees. draft_only on the voice channel prepares the intent and deliberately does not even ask.

Why does a refused call still appear anywhere?

Because a refusal is a decision, and the audit trail records decisions including the ones that produced no action. Without that, a follow-up that was blocked and a follow-up that was forgotten look identical a month later.