People
A Person is the canonical human, and the record itself is deliberately thin — a name, the company it attaches to, and its lifecycle stage. Nearly everything else on a person's screen is derived: identities come from people.add_identity, the history is assembled by timeline.py, the written summary is generated, and the deals, cases, follow-ups and onboarding belong to the services that own them.
Typed, derived, or borrowed#
Three kinds of thing appear on a person's screen and they behave very differently under editing, merging and export. Knowing which is which explains most of the surprises.
| On screen | Origin | Editable |
|---|---|---|
| Name, company link | Typed, or captured at first contact | Yes |
| Lifecycle stage | journey.py, moved by move_stage | Through a stage move, not by typing |
| Identities | people.add_identity, keyed by value_key(kind, value) | Added and removed as rows |
| The relationship summary | Generated by relationship_console.story | Regenerated, not edited in place |
| Timeline | Assembled by timeline.py from the underlying records | No — it is a view |
| Deals, demos, cases, onboarding, follow-ups | sales.py, crm.py, journey.py, followups.py | In the service that owns them |
The rule behind that table is that a person record never becomes a second copy of something another service already owns. A deal on the pipeline is the pipeline's row; the person screen shows it. The Data grid follows the same rule — every change goes through the service that owns the record, so the grid is not a second CRM and neither is this screen.
How a person comes into existence#
Usually nobody creates one. A message arrives on any channel, the address it came from is resolved through by_handle, and either it matches an identity that already resolves to a person or a new person is created with that identity attached. The full path, stage by stage, is from first contact to a person record.
The other routes in are deliberate: a person typed by hand, a prospect that has become a relationship, an import through the Data grid, or the Connect Assistant creating one on request. The Assistant's rights are narrower than a person's — it can create records and move stages, and it cannot price anything or clear a do-not-contact entry.
What a person carries with it#
- Identities — one row per address per channel, which is what makes the same human recognisable when they arrive somewhere new.
- A stage — where the relationship has got to, read by other parts of the product rather than shown as decoration.
- Memory at the contact tier — what Connect knows about this human specifically, readable and removable at /docs/relationships/person-memory/.
- Open work — follow-ups, cases, demos and opportunities, each owned elsewhere and surfaced here.
- A written summary — the story, regenerated rather than kept up to date by hand.
Editing, deleting, and what resists it#
Correct a name or a company link.
Result The change lands immediately and the timeline is unaffected, because the timeline reads the underlying records rather than a copy of the name.
Remove an identity that turns out to belong to somebody else.
Result That address stops resolving to this person. The next message from it arrives as a first contact, which is correct and looks like a new person appearing.
Try to remove a person who has history.
Result The history does not evaporate — conversations, calls and cases live in their own tables. Merging is usually what was actually wanted: see merging two records.
Two records that turn out to be one human are not repaired by deleting one of them. duplicates proposes the pair, a human decides, and merge_people preserves both sides. Deleting throws away the half you were not looking at.
Questions#
Can two people share an email address?
An identity is keyed by value_key(kind, value) and resolves to one person, so a shared address resolves to whoever holds it. A genuinely shared mailbox — accounts@, support@ — is better modelled against the company's own contact than attached to an individual, so replies are not attributed to a human who did not write them.
Does changing a person's stage change what Connect does?
Yes. Stage is read rather than displayed: it feeds what the next best action looks like and what the relationship summary emphasises. That is why a move goes through move_stage and its rules rather than a free-text field somebody can type anything into.
Where is the full field list?
The Data grid's people sheet is the honest answer — it shows the record as it actually is, sortable and exportable, and every edit there goes through the service that owns the field. This documentation does not publish a column list, because a column list goes stale a release after it is written.