Connect by JBRH Open Connect

A WhatsApp follow-up, end to end

When a WhatsApp follow-up falls due, the engine tick composes a message from the reason recorded on it and hands it to whatsapp.dispatch. Inside the 24-hour window that message goes as written; outside it, only the approved template the workspace nominated. A refusal is recorded with its reason and the commitment stays visible rather than vanishing.

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

The stages#

  1. Trigger — a follow-up on the whatsapp channel reaches its due time and the engine tick picks it up.
  2. User or external event — none. The reason is already a record; nothing has arrived from outside.
  3. Authentication and workspace resolution — the queue runs inside the owning workspace before any rule or setting is read.
  4. Ingest — the row names the Person, the channel, the due time and the reason the commitment exists.
  5. Canonical record — the follow-up is already canonical; the message it produces will join the Person's existing thread.
  6. Reasoning — the message is composed from the reason plus what Connect knows about the relationship, so it reads as a continuation rather than a fresh approach.
  7. Knowledge, memory and rules — the same bounded Knowledge, memory tiers and channel standing instructions that govern any reply.
  8. Autonomy and approval — dispatch prices the message on Meta's category and the narrowest applicable rule decides: send, queue for approval, hold as a draft, or refuse. A marketing template counts as sales outreach whatever it says.
  9. Action through Meta — consent, do-not-contact, any block directive and the window are checked; inside the window the written message goes, outside it the nominated template, and nothing at all if that template is missing or unapproved.
  10. Result — a returned message id records the send with evidence; a refusal — the window, an unapproved template, the hourly cap — is recorded with its reason.
  11. Relationship, timeline and memory — the message joins the Person's history whether or not a reply follows.
  12. Audit, usage and Needs You — the decision is in the audit trail, the send is metered on a customer plan, and an unkept commitment becomes something a person can see.

Stage by stage, with the failures#

StageWhat you seeWhat changesWhat can fail
DueThe row moves to due on #/follow-upsNothing outbound yetA workspace whose runtime is switched off does no draining
ComposedA message drafted against the threadA draft existsA reason too thin to write from — the message reads generic
Autonomy appliedSent, queued, or keptThe decision, with its ruleask_before_send means nothing goes until somebody acts
Compliance checkedNothing, when it passesNothingA STOP, a suppression or a block — the commitment closes rather than retrying
Meta askedThe message in the chat, if it goesState uncertain → sent when Meta returns a message idThe window has closed and no approved template is nominated; or the hourly cap for the connection type is reached
RecordedThe outcome on the conversation and in the logTimeline, audit, usageNothing fails silently here — a refusal is a recorded decision

What happens to a refused follow-up#

It is not retried against the same refusal and it is not deleted. The refusal and its reason are recorded, and the commitment remains visible as unfinished business — which is what lets somebody pick it up on a channel that is open, or decide it no longer matters.

Three refusals deserve different responses. A window refusal means the message was fine and the moment was wrong: nominate an approved template, or move the commitment to another channel. A rate-limit refusal means nothing is wrong at all — Meta is saying slow down, and waiting is the whole fix. A consent or suppression refusal means the message should not be sent at all: close the commitment rather than rerouting it.

The general principle — that an agent must not quietly abandon something it undertook to do — is argued in Preventing a voice agent from promising a call-back it cannot keep, and it applies here for the same reason.

Proving it worked#

  1. The row is no longer due — it either completed or is recorded as refused with a reason.
  2. If it sent, the message is on the customer's thread with an acknowledgement behind its sent state.
  3. If it was held, there is an item in Needs You naming the person and the reason.
  4. The decision log carries the rule that produced whichever of those happened.

A follow-up that silently vanished satisfies none of these, and that combination — nothing sent, nothing queued, nothing recorded — is the one worth investigating rather than explaining.

Questions#

Does a follow-up wake the workspace up?

No. Draining happens while the workspace runtime is on. A workspace switched off does not send, and the commitments are still there when it is switched back on.

Can I approve a held follow-up later than its due time?

Yes, and it sends when you approve it. Whether Meta still accepts it is a separate question — a window that had closed by then refuses it just the same, because the check runs at send time and not at approval time.

Has a WhatsApp follow-up ever executed against Meta in production?

No. No number is connected in production, so the due-time composition, the category decision and the refusal paths are what run there; the send itself is proven against a stubbed Meta in test_whatsapp_platform_v1.

Will Connect send the same follow-up twice?

No. A commitment is acted on once and then completed or recorded as refused. Two similar messages usually means two rows, which is worth looking at on the follow-ups screen.