Syncing an inbox
The first pass on a new mailbox has no position to resume from, so it reads what the provider offers and builds the workspace's starting history. Every later pass resumes from where the last one stopped, fetches what is new, and hands it to the bridge. A pass is bounded by the workspace's daily allowance, and reaching that bound holds work rather than dropping it.
The first pass is not like the others#
A newly connected mailbox has no cursor, no history ID and no prior state — nothing that says where reading should begin. So the first pass is the only one that establishes a starting point rather than continuing from one, and it is the only one whose size is set by what is already in the mailbox rather than by what has arrived recently.
Two things follow. A busy mailbox takes visibly longer to become useful than an empty one, and the Conversations screen fills progressively rather than all at once. And a mailbox that looks empty an instant after connection is not evidence of anything — the honest verdict before a pass completes is that the credential was accepted, which is what Mailbox health says on that row.
What one pass does#
- Fetch — the adapter asks the provider for what is new since its position.
- Store — rows land in
tenant_*in the provider's own shape. - Bridge —
connect_core.bridge_*copies into canonicalthreads,messagesandcontacts. - Resolve — each sender becomes an identity, and an identity resolves to a person.
- Triage — the engine ranks what it now has, reading
threads.priority. - Advance — the position moves, but only for work that was actually accepted.
The last stage carries the rule that matters most. The position advances for work that was taken; it deliberately does not advance past work that was refused. When the daily allowance is spent, the refusal is recorded, Needs You shows it, and the unread mail stays unread at the provider — advancing on a refusal is how a mail agent loses messages permanently.
The engine reads only the canonical side. tenant_* is what the adapter produced; threads, messages and contacts are what everything after the bridge sees. From a provider message to a canonical one follows one message through that copy.
What bounds a pass#
| Bound | Effect when reached | Where it comes from |
|---|---|---|
| The workspace's daily allowance | Work is held, the position does not advance, the refusal appears in Needs You | metering.py and the plan; the Owner has no plan and no gate |
| What the provider will return | The pass ends normally with what it got and resumes next time | The provider's own API or IMAP behaviour |
| Nothing new to fetch | The pass completes having done nothing — a quiet mailbox | The mailbox genuinely being idle |
There is no mode in which a pass discards mail to stay within a bound. The three outcomes are: it was processed, it is waiting at the provider to be processed later, or there was nothing. A message that has been read past without being processed is not one of them, and the cursor rule is what guarantees that.
Provider differences that show up here#
- Gmail
- Resumes by history ID, which lets a workspace catch up without re-reading everything — Gmail history sync.
- IMAP
- Resumes by UID cursor, with its own lifecycle and its own ways of going wrong — IMAP UID and cursor lifecycle.
- Microsoft
- Resumes through the Graph adapter's own position. The governing rule — never advance on a refusal — is identical.
- A sudden arrival of hundreds of messages
- Handled as a burst rather than as an incident; ordering and fairness are covered in Large batches and bursts.
Questions#
How far back does the first sync read?
As far as the provider offers for that account, since there is no earlier position to resume from. What a provider offers differs between Gmail, Graph and an IMAP server, and it is a property of your account rather than a Connect setting.
Will the first sync reply to old mail?
Only within the autonomy already set for the channel. A workspace at ask_before_send gets drafts and approvals; one at draft_only gets drafts and no approvals at all. Nothing is enabled by connecting a mailbox.
The sync stopped part-way through. Have I lost messages?
No, if it stopped on a refusal — the position did not advance and the mail is still at the provider. Needs You shows the refusal and why. If it stopped on a failure, the mailbox's health verdict names it.