# 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.

- **Status:** Available
- **Audience:** both
- **Channels:** email, whatsapp, phone
- **In the app:** #/inbox, #/relationships, #/calls
- **Last verified:** 2026-09-10
- **Canonical:** https://connectbyjbrh.com/docs/workflows/first-contact-to-person/

## The chain

1. TRIGGER — a message or a call arrives from an address that resolves to nobody.
2. 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.
3. AUTH / WORKSPACE RESOLUTION — the mailbox, number or handle it arrived on decides the workspace, and `workspace_scope()` fixes that boundary for everything downstream.
4. INGEST / REQUEST — the adapter stores what the provider sent in the `tenant_*` tables, in the provider's own shape, untranslated.
5. CANONICAL RECORD — `connect_core.bridge_*` copies it into the canonical `threads`, `messages` and `contacts` the engine reads; `by_handle` finds no identity, so a Person is created and the address is attached with `people.add_identity`.
6. 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.
7. 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.
8. AUTONOMY / APPROVAL — the channel's mode decides whether the drafted reply may leave. `ask_before_send` puts it in Needs You; `draft_only` writes it and stops.
9. ACTION / PROVIDER — a permitted reply leaves through `outbound.py`, the single send boundary a person's own reply also uses.
10. RESULT — the provider's acknowledgement is what makes the state *sent*. Until it arrives the honest state is uncertain, not sent.
11. 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.
12. 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.
13. NEXT — the same human on a second channel arrives as a second record until an identity links them, and `duplicates` may 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](/docs/relationships/contact-brief/). A written reply can wait for approval without anybody hearing silence.

## Verifying it worked

1. 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.
2. 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.
3. 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.
4. 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](/docs/workflows/duplicate-merge/) 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.

## Related

- [People](https://connectbyjbrh.com/docs/relationships/people/)
- [Identities](https://connectbyjbrh.com/docs/relationships/identities/)
- [One person across phone, email and WhatsApp](https://connectbyjbrh.com/docs/relationships/cross-channel-identity/)
- [Merging duplicate people, end to end](https://connectbyjbrh.com/docs/workflows/duplicate-merge/)
- [What Connect may do](https://connectbyjbrh.com/docs/autonomy/)
- [The customer timeline](https://connectbyjbrh.com/docs/relationships/timeline/)
- [Email in Connect](https://connectbyjbrh.com/docs/email/)

## What this page is based on

- `docs-source/sources/GENERAL.md` §2 and §3 — the request path and canonical records
- `docs-source/sources/CHANNELS.md` §5 — `by_handle`, people and identities
- `backend/app/journey.py` — the first position and legacy stage words
- `docs-source/sources/GENERAL.md` §5 — autonomy, Needs You and the audit trail
