Per-customer memory
How conversations become durable facts about a customer — derivation, deduplication, importance, and what gets recalled.
Retrieval answers from your documents. Memory is the other half: what the agent knows about this particular customer, carried across sessions, channels and months.
Memory is derived, not logged
A conversation turn finishes. Nothing is stored yet — transcripts are not the unit of memory here.
A model extracts normalised entries from what was said: facts ("runs a fleet of four vehicles") and topics, each with an importance score so a passing remark and a hard constraint are not weighed equally.
The turn's entries are embedded as one batch rather than one at a time. The embedding endpoint runs at a concurrency of one, so a sequence of single calls would block other users' queries behind it.
Each entry is checked against what already exists — topics by name, facts by vector proximity within a threshold. Without this, the same fact mentioned across five conversations becomes five memories that crowd out everything else.
A match updates the existing row rather than adding one: content and embedding refreshed, importance raised to the higher of the two, and re-pointed at the most recent session so recency tracks the live relationship. No match is stored as new, encrypted and scoped to the space.
At the next turn, memories are retrieved by similarity under a tighter threshold than documents use — a marginally-related passage is merely unhelpful, while a marginally-related "fact" about someone is actively wrong.
Runs after a turn. The deduplication step is what keeps recall from degrading as a relationship gets longer.
Storing whole transcripts and searching them back is the obvious approach and a poor one. Transcripts are mostly filler, the same fact appears in twenty phrasings, and recall gets worse as the relationship gets longer — exactly backwards.
Instead, after a turn, the platform asks a model to extract normalised entries from what was said, of two kinds:
- Facts — durable statements about the customer. "Runs a fleet of four vehicles." "Renewal is in May." "Prefers WhatsApp."
- Topics — recurring subjects the relationship keeps returning to, each with a topic name.
Each entry carries an importance score, so a passing remark and a hard constraint are not treated as equals when space is tight.
Deduplication is the whole game
A customer mentions the same thing across five conversations. Without deduplication you accumulate five near-identical memories, they crowd out everything else at recall time, and the agent starts repeating itself.
Before an entry is written, the platform looks for one it should merge into instead:
- Topics match by topic name — exact, because a topic is already a normalised label.
- Facts match by vector proximity: the nearest existing memory of the same kind, accepted as a duplicate only if its cosine distance is within a configured threshold.
On a match the existing row is updated rather than duplicated — content and embedding refreshed, and importance raised to the higher of the two, so a fact that turns out to matter more later is promoted rather than stored twice at different weights. The entry is also re-pointed at the most recent session and message that triggered it, so its recency reflects the live relationship.
Batched embedding
A single turn often yields several entries. Embedding them one at a time means several sequential round trips to the embedding endpoint — and because that endpoint runs with a concurrency of one, that sequence blocks other users' query embeddings behind it.
So a turn's entries are embedded as one batch and the vectors passed down into the write path. Measured on a three-entry turn: 117 ms sequential versus 46 ms batched — a 2.4× difference on a path that sits between the customer and their answer.
Recall
At the start of a turn, memories are retrieved for that customer by vector similarity, under their own distance threshold — tighter than the one used for document retrieval, because a marginally-related document passage is merely unhelpful, while a marginally-related "fact" about someone is actively wrong.
Retrieved memories join the prompt alongside any retrieved document chunks. The agent answers from your documents, addressed to a person it already knows.
Scoping and encryption
Memories are scoped to the end user's space, enforced at the database level like every other tenant-owned record, and stored encrypted per space. One customer's history cannot surface in another's conversation, and the stored text is not readable from the database alone.
Why this is hard to bolt on later
Per-customer memory changes the shape of the data model: an identity per end user, a space to scope it, encryption keyed to that scope, and a derivation step in the turn loop. Systems that start as a single shared assistant tend to end up with a CRM field somewhere and call it memory — which is why the difference shows up in the conversation rather than in the feature list.
The business argument for this, rather than the mechanism, is on Per-customer memory.