Agent Memory Consolidation: Dedup, Contradictions, and Orphan Cleanup

Agent Memory Consolidation: Dedup, Contradictions, and Orphan Cleanup

A wave of agent-memory tools shipped in the last few weeks. Most of them demo the same happy path: store a fact, recall it later, show a similarity score. That demo works on day one. It says nothing about day ninety, when the store may hold a dozen versions of the same deploy note, two contradictory rate limits, and hundreds of entries no agent has touched since the sprint ended.

Retrieval degrades quietly in that environment. Every duplicate occupies a slot in the top-k results, crowding out a distinct memory that deserved the space. When an old fact and its replacement both rank, the agent cannot tell which one is current. Nobody notices until answers start drifting, and the usual fix is dumping the whole store and starting over.

We treat this as a first-class problem in Uteke, our local-first memory engine for AI agents. This post covers how consolidation and deduplication work there, and the trade-offs behind the thresholds we picked.

The Problem: Agent Memory Accrues Noise

Agents write memory the way logs get written: eagerly, repeatedly, and with slight rephrasing each time. Three kinds of noise dominate.

Near-duplicates. An agent told "deploy v2.1 to staging at 3pm" and later "staging deploy is scheduled for 3" has stored one fact twice. Exact-hash dedup catches none of this because the strings differ. Only semantic similarity sees it.

Contradictions. Facts change. "The API rate limit is 100 rpm" was true last month. Its update is true now. A recall that returns both forces the agent to guess, and embeddings alone cannot tell which memory is newer or correct.

Orphans. One-off memories from finished tasks stay forever. They connect to nothing, nobody pins them, and they still cost index space and ranking attention on every single query.

How Uteke Handles It: The Dream Cycle

Uteke ships one maintenance command, uteke dream, which runs seven phases in dependency order:

lint -> backlinks -> dedup -> contradict -> orphans -> compact -> verify

Each phase records its own status, and an error in one phase does not abort the rest. A lint failure should not block dedup from running.

Dedup: Merging Near-Duplicates at Cosine 0.90

The dedup phase finds near-duplicate memories by embedding similarity and merges pairs at cosine 0.90 or above. Rephrased duplicates land in that band; genuinely distinct facts rarely do.

Why merge rather than delete? Merge is the conservative primitive. If either copy carries metadata the other lacks, like tags or an entity link, collapsing to one entry is an opportunity to keep that information. Deletion is final in a way a merge is not.

Contradict: Flagging Stale Facts at 0.65

The contradict phase detects contradictory memory pairs at a 0.65 similarity threshold and flags them for review. It does not auto-delete either side.

That is deliberate. A model can reliably detect that two memories cover the same subject and disagree. Deciding which one is currently true needs a timestamp rule, the owning agent, or a human. Uteke's relationship graph has typed edges for exactly this, including supersedes: once you resolve a flagged pair, the current fact supersedes the stale one, and future recall prefers the winner.

Orphans, Compact, and Smart Decay

The remaining phases clean up the long tail. Orphans surfaces disconnected, low-importance memories for cleanup. Compact applies auto-prune to cold-tier and deprecated memories. Verify closes the pipeline by checking database and index consistency, so maintenance cannot silently corrupt the store it was supposed to clean.

Underneath all of this sits Smart Decay, a composite importance score. You pin what matters, and stale memories fade on their own schedule instead of living forever.

Decisions and Trade-offs

Three choices worth explaining, because reasonable people disagree on each.

Thresholds ship conservative. Dedup at 0.90 under-merges on purpose. Merging two distinct facts is worse than leaving two copies of one fact, because a bad merge destroys information and a missed duplicate only costs a ranking slot. If your agents rephrase aggressively, some duplicates will survive. That is the accepted cost.

Contradictions flag instead of resolve. Full automation here is the feature everyone asks for, and the one we refused to ship blind. Wrong auto-resolution poisons recall with confidence: the agent stops seeing two options and starts citing the wrong one as fact.

Maintenance is explicit. uteke dream is a command you run, with --dry-run to preview changes and --phases to select a subset. Nothing rewrites your memory store in the background without you asking. Cron it nightly if you want. The point is that you decide when.

Running It

# preview every phase before touching data
uteke dream --dry-run

# full pipeline
uteke dream

# just the consolidation phases
uteke dream --phases dedup,contradict

# scoped to one agent namespace
uteke dream --namespace my-agent

# machine-readable report for CI
uteke dream --json

Backlinks and verify run globally regardless of namespace scoping, since graph integrity is a property of the whole store.

What's Next

Uteke is at v0.16.0, which made fusion recall the default retrieval strategy: vector and hybrid rankings fused with Reciprocal Rank Fusion, validated on the full 500-question LongMemEval run at 0.977 recall@10 and 0.946 recall@5, published in the repo benchmark results.

Better retrieval raises the value of a clean store, and a clean store protects every retrieval improvement. Expect maintenance and recall quality to keep shipping together, because they are the same problem seen from two ends.

Try It

Uteke is a single Rust binary, Apache-2.0 licensed, at 235 stars at the time of writing. No API keys, no cloud required:

curl -sSL codecora.dev/uteke/install | sh
uteke remember "first memory"
uteke dream --dry-run

Repo and full CLI reference: github.com/codecoradev/uteke. If your agent has been remembering for months without maintenance, run the dry-run and read the report. It is usually convincing on its own.