How does deduplication work during transform?

Short answer: Before commit, transform retrieves related memories and decides if a new fact is a duplicate or truly additive.

Deduplication is a transform job, not a separate pipeline stage. It searches related candidates first rather than comparing against every stored item blindly. It also cleans near-duplicates inside the same extraction batch. Bounded single-memory topics change the job to enforcing one current entry. Engram implements this retrieve-and-decide pattern in transform.

The previous chapter described transformation broadly as the stage where new facts get integrated with what a system already knows. One specific piece of that integration deserves closer attention on its own: how the transform stage actually catches duplication before it ever reaches storage, and what that mechanism looks like as a concrete step inside the pipeline rather than as an abstract goal.

Where Exactly in the Pipeline Does Deduplication Actually Happen?

Deduplication isn’t a separate stage sitting apart from transformation, it’s one of the specific jobs the transform stage performs as part of its broader integration work. Before any newly extracted fact gets persisted, the transform step retrieves memories that seem related to it, using the same semantic search machinery available anywhere else in the system, and only then decides whether the new fact adds something genuinely absent from what’s already stored. This retrieval-then-decide sequence is what actually implements deduplication in practice, not a separate check bolted on afterward, but a built-in part of how transformation does its job.

Why Does Deduplication Need to Retrieve Related Memories Rather Than Just Comparing the New Fact Against Everything Ever Stored?

Comparing a newly extracted fact against an entire memory store, rather than a targeted, retrieved subset, would be both wasteful and unnecessary, the overwhelming majority of stored memories have nothing to do with whatever new fact just arrived. Retrieval narrows the comparison down to exactly the handful of memories that are actually plausible candidates for overlap, letting the deduplication decision focus its attention where duplication could realistically exist rather than scanning irrelevant territory. This is exactly the same principle behind scoped, targeted search covered throughout this knowledge base’s earlier discussion of retrieval, applied here internally, inside the pipeline, rather than by an external caller.

What Actually Counts as a Genuine Duplicate Once Related Memories Have Been Retrieved?

A genuine duplicate is a newly extracted fact that restates something an existing memory already captures fully, even when the wording differs considerably between the two. The judgment call happens through the same kind of decision described in the previous chapter, an underlying model examining the new fact alongside each retrieved candidate and determining whether it’s truly redundant, a partial update worth merging in, or something distinct enough to warrant its own separate memory. This judgment, not a fixed similarity threshold applied mechanically, is what actually determines the outcome, since genuine duplication is ultimately a question of meaning rather than a number that can be computed in isolation.

Does Deduplication During Transformation Only Ever Compare One New Memory Against What’s Already Stored?

Not necessarily. Deduplication can also operate across an entire batch of freshly extracted memories at once, catching redundancy between facts that arrived together in the same input before any of them are even compared against existing history. This matters because a single piece of raw input, a long conversation touching the same point more than once, can itself produce several near-duplicate extracted facts before transformation ever gets the chance to check them against anything already on file. Handling this batch-level redundancy, not just comparisons against history, is part of what keeps deduplication genuinely thorough rather than only catching the most obvious, cross-session repetition.

How Does a Bounded Topic Change What Deduplication Actually Needs to Accomplish?

A topic configured to hold at most one memory per scope changes deduplication’s job from deciding whether two memories are the same to guaranteeing that only one memory can ever exist for that scope in the first place. Rather than comparing a new fact against a handful of retrieved candidates and judging overlap, the transform stage consolidates everything relevant to that bounded scope down to the single canonical memory the topic is designed to hold, updating it in place rather than producing a second, competing entry. This is a stronger, structural guarantee against duplication, appropriate specifically for the kind of running, single-record memory a bounded topic is meant to represent.

How Does Weaviate Engram’s Transform Stage Implement This Retrieval-and-Decide Deduplication in Practice?

Weaviate Engram’s transform step retrieves candidate memories before making its integration decision, applying exactly this retrieval-then-judge pattern to catch duplication as part of its ordinary processing. Consider a talent agency’s audition-feedback tracking assistant, gathering notes from casting directors across multiple auditions for the same represented actor:

from engram import EngramClient

client = EngramClient(api_key=os.environ["ENGRAM_API_KEY"])

client.memories.add(
    "Casting director noted that this actor consistently brings strong physical comedy instincts but tends to rush emotional monologue delivery.",
    properties={"actor_id": "actor-representation-2214"},
)

A later audition for a different role produces feedback covering much of the same ground, phrased differently by a different casting director:

client.memories.add(
    "Another casting director's notes echoed a similar pattern: excellent comedic timing, but the actor rushes through more dramatic, emotional beats.",
    properties={"actor_id": "actor-representation-2214"},
)

results = client.memories.search(
    query="What recurring feedback themes has this actor received across auditions?",
    properties={"actor_id": "actor-representation-2214"},
)

Because the transform stage retrieves the earlier feedback memory before committing this second one, it recognizes the genuine overlap between the two observations despite the different casting directors and different phrasing, merging them into one consolidated memory that captures this as a recurring pattern rather than storing two separate, redundant entries that each only partially capture the full picture. An agent reviewing this actor’s development later sees one clear signal, a consistently noted strength paired with a consistently noted area for growth, rather than a scattered pile of overlapping notes that all say roughly the same thing in slightly different words.

Deduplication during transformation keeps genuinely repeated information from piling up as separate, redundant entries. A related but distinct challenge arises when two memories don’t simply repeat each other, but actively conflict, each asserting something the other directly contradicts. Our next chapter, How does reconciling conflicting memories work?, takes up exactly that challenge.