From first contact to a person record
An address nobody has seen before arrives on a channel. The provider adapter stores it, the bridge copies it into canonical records, by_handle finds no identity, and a Person is created with that address attached. Everything after that — triage, grounding, the reply, the timeline entry — happens against the new record rather than against an address.
The chain#
- TRIGGER — a message or a call arrives from an address that resolves to nobody.
- USER / EXTERNAL EVENT — the provider delivers it: a Gmail or Microsoft Graph fetch, an IMAP poll, a WhatsApp message, or a carrier's inbound call webhook.
- AUTH / WORKSPACE RESOLUTION — the mailbox, number or handle it arrived on decides the workspace, and
workspace_scope()fixes that boundary for everything downstream. - INGEST / REQUEST — the adapter stores what the provider sent in the
tenant_*tables, in the provider's own shape, untranslated. - CANONICAL RECORD —
connect_core.bridge_*copies it into the canonicalthreads,messagesandcontactsthe engine reads;by_handlefinds no identity, so a Person is created and the address is attached withpeople.add_identity. - CLASSIFICATION / RESEARCH / REASONING — the engine triages: what this is, how urgent it is, what it needs. The relationship starts at the first position on the journey.
- KNOWLEDGE + MEMORY + RULES — memory resolves narrowest-first across workspace, channel, endpoint and contact. The contact tier is empty and is returned as empty, which is a visible answer rather than an absence; the workspace tier still applies.
- AUTONOMY / APPROVAL — the channel's mode decides whether the drafted reply may leave.
ask_before_sendputs it in Needs You;draft_onlywrites it and stops. - ACTION / PROVIDER — a permitted reply leaves through
outbound.py, the single send boundary a person's own reply also uses. - RESULT — the provider's acknowledgement is what makes the state *sent*. Until it arrives the honest state is uncertain, not sent.
- RELATIONSHIP / TIMELINE / MEMORY — the new person holds the identity, the position on the journey and the thread; the timeline gets its first entry, and anything durable learned in the exchange can be remembered at the contact tier.
- AUDIT / USAGE / NEEDS YOU — the decision is recorded with the rule it was taken under, including a refusal; usage is metered against the workspace's allowances; anything held is waiting for a person.
- NEXT — the same human on a second channel arrives as a second record until an identity links them, and
duplicatesmay propose the pair.
Stage by stage#
| Stage | What you see | What changes | What can fail |
|---|---|---|---|
| Ingest | Nothing yet | A provider-shaped row | A mailbox whose credentials have gone stale fetches nothing, and silence looks like quiet |
| Canonical record | A new conversation | threads, messages, contacts | Nothing downstream reads provider tables, so a bridge that has not run means the engine never sees the message |
| Person created | A new name in relationships | A Person, one identity | A display name that is really an honorific is rejected rather than stored, so the record can appear unnamed |
| Grounding | Nothing yet | Nothing | An empty contact tier is normal for a stranger; a workspace with no knowledge answers thinly |
| Autonomy | A reply, or an item in Needs You | A draft | A mode of draft_only never asks, so nothing appears in the approval queue at all |
| Send | A sent reply | A message and its evidence | Without the provider's acknowledgement the state is uncertain and must not be read as sent |
| Timeline | The first entry | Nothing new — it is assembled | An entry missing usually means the work is attached to a different record for the same human |
What makes this the same on every channel#
The stages above name email, WhatsApp and phone in one place only: ingest. After the bridge, the engine reads canonical records, which is why adding a provider changes nothing downstream and why a first call and a first email produce the same kind of record.
The differences that remain are the honest ones. A call is answered live, so the briefing it is given has tight character budgets — see the contact brief. A written reply can wait for approval without anybody hearing silence.
Verifying it worked#
Open the new person and check the identity.
Result The address that arrived should be attached. Without it, the next message from that address creates yet another record.
Check the position on the journey.
Result A new relationship starts at the first position. An old contact row bridged in carries a legacy word that reads as the same first position rather than as a jump.
Read the timeline.
Result One entry, for the message that started it. If the reply is missing, look at autonomy before looking for a fault.
Look for a duplicate proposal a few days later.
Result If this human already existed under another address, the pair is proposed — merging duplicate people takes it from there.
Questions#
Does Connect reply to a stranger at all?
That is autonomy's decision, not the record's. The channel's mode governs whether a drafted reply leaves, needs approval, or is written and held — and a block held in memory stops an outbound message regardless of what was drafted.
Why did a person appear with no name?
Because what arrived in the name position was rejected as not a name — an honorific, a role word or an acknowledgement. Storing it would mean Connect later addressing somebody as *sir* as though it were their name.
Is a prospect turned into a person by this path?
Yes, when they make contact. Research produces a prospect record; a message or a call from them runs the same resolution as anybody else, and the relationship starts from there.