Connect by JBRH Open Connect

An inbound SMS, end to end

A customer texts the business number. The provider posts it, Connect verifies the post, resolves the workspace, deduplicates on the provider's identifier, attaches the message to a Person and lets the agent loop reason about it. The flow then stops short of where email's continues: on the live carrier there is no SMS reply, so the decision that comes out is work on another channel, or an item for a person.

Status
Foundation In development What this means
Audience
both
Channels
sms
In the app
#/inbox, #/relationships, #/needs-you
Last verified
Product version
6.3.2

The chain#

  1. Trigger — a person types a message and sends it to the workspace's business number.
  2. External event — the provider that carries that number posts the message to Connect's inbound endpoint.
  3. Authentication and workspace resolution — the post is verified against the provider's own scheme, then the receiving number is resolved to exactly one workspace. Everything after this runs inside it, under the isolation kernel and row-level security.
  4. Ingest — sms.py normalises the payload; the provider-shaped row keeps the original wording of the request, and no provider vocabulary travels further.
  5. Canonical record — a message on a conversation, keyed on the provider's message identifier so a retry updates rather than duplicates.
  6. Classification and reasoning — the agent loop triages the message in the context of its conversation: an opt-out word short-circuits everything here; anything else is ordinary correspondence.
  7. Knowledge, memory and rules — bounded extracts from the workspace's Knowledge, the memory tiers that apply to this contact, and any standing directive such as block:sms.
  8. Autonomy and approval — autonomy.py resolves the narrowest applicable rule for the sms channel. With no carrier for outbound text, the honest outcome of this stage today is not a send decision but a routing decision.
  9. Action through a provider — nothing goes out by SMS. What can go out is a reply on email, WhatsApp or phone, or a follow-up booked on one of those, under that channel's own rule.
  10. Result — recorded with evidence. A send is sent only on a provider acknowledgement; a refusal is recorded with its reason rather than dropped.
  11. Relationship, timeline and memory — the text joins the Person's history beside their email and their calls, and anything durable is written as memory instead of being left in the conversation.
  12. Audit, usage and Needs You — the decision and the rule behind it are in the audit trail, any send is metered on a customer plan, and anything a person must handle is queued for them.
  13. Next — the conversation stays open. A later text from the same number joins it; a reply on another channel is linked to it, so the relationship reads as one exchange rather than two disconnected ones.

Stage by stage, with the failures#

StageWhat you seeWhat changesWhat can fail
Webhook arrivesNothing yetA provider-shaped rowNo webhook configured at the provider; the post cannot be verified
Workspace resolutionNothing yetThe scope everything else runs inThe receiving number maps to no workspace — the message is a dead letter
DeduplicationOne conversation, not twoThe existing message is updated on a retryThe provider issues a different identifier per attempt
Person resolutionThe message on a contactAn identity match, or a new contactCaller identity withheld; a recycled number attaching to its previous owner
Opt-out scanA suppression on the contactA block:sms memory row and an audit entryNothing — this is the most reliable step in the chain
ReasoningPriority and classification on the conversationTriage state the engine reads when picking workA message with no actionable content; ambiguity that should go to a person
DecisionAn item in Needs You, or a follow-upA commitment with a date and a reasonAn autonomy rule set to off for every channel that could carry the answer
AnswerA sent email, WhatsApp message or callProvider evidence on the recordNo SMS reply is possible at all on the live carrier

Where this flow differs from the email one#

Three places. The identity is a mobile rather than an address, so resolution is likelier to produce a new contact for someone you already know. There is no thread header to follow, so conversation grouping is by the pair of numbers rather than by a threading identifier the sender supplies. And the flow terminates in a different medium, which is unusual enough to be worth saying twice: the answer to a text goes out by email, WhatsApp or phone.

That third difference is not a workaround dressed up as design — it is the consequence of a foundation channel, and the reason a business should decide deliberately whether text is an acceptable intake route for the kind of question its customers send.

Questions#

Does the whole chain run for a stop request?

No, and deliberately. An opt-out short-circuits at the classification stage: the suppression is written, the audit entry is made, and no draft is prepared against a person who has just asked not to be contacted. An SMS STOP, end to end follows that shorter path.

How long does the chain take?

Ingest is a webhook and a few writes and is not where the time goes. The reasoning stage runs on the engine's own schedule, and any human decision waits for a person. No published measurement of end-to-end latency for this channel exists, so this page does not offer one.

Can I see the whole chain for one message afterwards?

The conversation shows the message and what followed; the timeline shows it beside everything else about that person; the Decision Log shows what was decided and under which rule. Between them the chain is reconstructable without reading anything internal.