# Creating a conversation thread, end to end

An arriving message is matched to an existing conversation or starts a new one, and the sender is resolved to a person — an existing one wherever the evidence supports it — who may in turn be linked to a company. Two things are decided at this moment and then kept: which mailbox the conversation belongs to, and which person it is about.

- **Status:** Available
- **Audience:** both
- **Channels:** email
- **In the app:** #/inbox, #/relationships
- **Last verified:** 2026-09-10
- **Canonical:** https://connectbyjbrh.com/docs/workflows/thread-creation/

## The flow, stage by stage

1. Trigger — a message is taken in from Gmail, Microsoft Graph or an IMAP server.
2. External event — someone sent mail to an address the workspace owns.
3. Authentication and workspace resolution — the receiving mailbox names the workspace, and everything after this point is scoped to it.
4. Ingest — the provider's own shape is stored first; nothing downstream reads that copy.
5. Canonical record — the message is matched to a thread or a thread is created, and the message is written as a canonical row the engine and every screen read.
6. Classification and reasoning — triage runs: what kind of message this is, how urgent, and whether it needs an answer at all.
7. Knowledge, memory and rules — memory for the contact and the channel is consulted, including any block directive, which is a tag rather than a column.
8. Autonomy and approval — consulted only if a reply is going to be written; creating a thread never sends anything.
9. Action through a provider — none at this stage. Read marks and labels belong to the write-back step beside a reply.
10. Result — a conversation you can open, with a person on it and a company where one is known.
11. Relationship, timeline and memory — the message joins the person's timeline, which spans every channel rather than email alone.
12. Audit, usage and Needs You — the work is metered, and anything a person must decide is queued rather than assumed.

> **Note** Stage four matters more than it looks. The provider's copy and the canonical record are two different things on purpose: the engine never reads the provider tables, so adding a provider changes nothing downstream and a bug in one adapter cannot corrupt a workspace's conversation history.

## What is matched before anything is created

| Question | Matched against | If no match |
|---|---|---|
| Is this message already held? | The identifiers the message itself carries | It is recorded as new |
| Does it belong to a conversation? | The threading information the message carries and the conversation it answers | A new thread is created |
| Who sent it? | The identities already known for people in the workspace | A person record is created from what the message actually contains |
| Which company? | The company records the workspace already holds | The person stands alone until evidence links them |
| Which mailbox owns it? | The mailbox that received it | Not applicable — a message always arrives somewhere |

Matching before creating is what keeps a relationship from fragmenting into one record per message. It is also why a person who writes from a second address appears as a second person until the two identities are joined: Connect attaches an address to a person on evidence rather than on resemblance.

## Two decisions made once

**The mailbox binding** — The conversation belongs to the mailbox that received it, and replies leave from there for the life of the thread. Changing a mailbox role later does not move it — see [Assigning a mailbox role, end to end](/docs/workflows/mailbox-role-assignment/).
**The person** — The thread is about a person, and their history is what a draft is grounded in. Correcting a wrong match is worth doing early, because everything written afterwards inherits it.

Both are deliberate stickiness. A conversation that changes its address mid-way splits in the recipient's client; a conversation that changes who it is about loses the history that made its replies sensible. Where either needs to change, the change is an explicit correction rather than a re-derivation on the next message.

## Where it goes wrong

- **One conversation appears as two.** Usually two mailbox rows for one real inbox, or mail arriving at two addresses that have not been recognised as the same conversation. The duplicate-threads page covers the diagnosis.
- **The wrong person is attached.** A shared address, a forwarded introduction, or two people at one company writing from one mailbox. Correct the person on the thread rather than editing the draft it produced.
- **No company is linked.** A personal address gives no evidence of an organisation, and Connect does not infer one from a domain it cannot support. The link can be made by hand.
- **A thread arrives with no reply written.** That is triage deciding it needs none, or memory carrying a block directive for that contact on this channel.

> **Careful** A block is a memory row tagged for the channel, not a flag on the thread. That is what makes it hold across channels and across future conversations — and why deleting a thread does not block anybody.

## Checking a new conversation was built correctly

1. Open the thread and read the header: the mailbox, the person, the company.
   - Result: You are reading the three decisions in one place, before any reply depends on them.
2. Open the person from the thread and look at their timeline.
   - Result: A timeline that spans calls and messages as well as email tells you the identity was matched, not merely created.
3. Correct the person or the company now if either is wrong.
   - Result: Later drafts are grounded in the corrected record. A correction after ten replies fixes the record but not the ten replies.

## Questions

### Does every arriving email create a new conversation?

No. A message is matched to an existing conversation first, using the threading information it carries. A new thread is created only when nothing it belongs to is already held.

### Why is one person showing up twice?

They wrote from a second address that has not been joined to their record. Connect attaches an identity to a person on evidence rather than on a similar name, and joining the two is an explicit merge.

### Can I move a conversation to a different mailbox?

No. The binding is made when the thread is created and kept, so the recipient keeps one thread rather than two. A conversation that belongs elsewhere is handled by saying so and letting the next one start in the right place.

## Related

- [Conversation threads](https://connectbyjbrh.com/docs/email/threads/)
- [Resolving a sender to a person](https://connectbyjbrh.com/docs/email/contact-resolution/)
- [From a provider message to a canonical one](https://connectbyjbrh.com/docs/email/message-canonicalisation/)
- [The same conversation appears twice](https://connectbyjbrh.com/docs/troubleshooting/duplicate-threads/)
- [Why the machine proposes a merge and a person disposes](https://connectbyjbrh.com/research/one-person-many-channels/)

## What this page is based on

- CHANNELS.md §1 — the two mail models, triage and blocking
- GENERAL.md §3 and §6 — canonical records, memory tiers and `directives()`
- `backend/app/connect_core.py` — the bridge between provider and canonical rows
- Connect capability registry (docs-source/facts.py) — `cross_channel_identity`
