Problem
When an AI agent writes to basic-memory across multiple sessions, it frequently creates duplicate notes on the same topic with slightly different titles. For example:
- Session 1 creates
reference_bu_product_mapping about BU-to-product mapping
- Session 3 creates
bu-mapping-analysis-2026-08-15 with updated findings on the same topic
Now search_notes("BU mapping") returns both, potentially with conflicting information. The agent (or human) has no way to know which is current. Over time, the knowledge graph accumulates contradictory entries that degrade retrieval quality.
The write_note tool with overwrite=True only helps when the caller knows the exact title of the existing note. In practice, agents don't — they know the topic but not whether a note already exists or what it's called.
Proposed Solution
A new upsert_note tool that leverages the existing FastEmbed embeddings to check for semantic duplicates before writing:
upsert_note(
title: str,
content: str,
directory: str,
project: str = None,
similarity_threshold: float = 0.85, # cosine similarity
on_match: str = "update", # "update" | "merge" | "ask"
)
Behavior:
- Compute embedding for the new note's title + first paragraph
- Search existing notes using the same vector index already used by
search_notes
- If a note exceeds
similarity_threshold:
on_match="update": overwrite the matched note with new content (like write_note with overwrite=True, but the caller doesn't need to know the existing title)
on_match="merge": append new content to the matched note
on_match="ask": return the match and let the caller decide
- If no match: create a new note (same as
write_note)
Return value should indicate what happened:
{
"action": "updated_existing",
"matched_note": "reference_bu_product_mapping",
"similarity": 0.91,
"path": "reference_bu_product_mapping.md"
}
Why This Fits basic-memory's Architecture
- No LLM needed — uses the FastEmbed embeddings already computed and indexed for
search_notes. Pure cosine similarity, same as the existing search pipeline.
- Zero new dependencies — the vector search infrastructure is already there.
- Backward compatible —
write_note stays unchanged. upsert_note is additive.
- Consistent with existing patterns —
write_note already has overwrite logic; this just makes it semantic-aware.
Use Case
AI agents (Claude Code, Cursor, etc.) that use basic-memory as a persistent knowledge store across hundreds of sessions. Without server-side dedup, the only defense is prompting the agent to "search before write" — which works ~95% of the time but fails when context is long, the agent is in a hurry, or a subagent doesn't inherit the parent's rules.
Problem
When an AI agent writes to basic-memory across multiple sessions, it frequently creates duplicate notes on the same topic with slightly different titles. For example:
reference_bu_product_mappingabout BU-to-product mappingbu-mapping-analysis-2026-08-15with updated findings on the same topicNow
search_notes("BU mapping")returns both, potentially with conflicting information. The agent (or human) has no way to know which is current. Over time, the knowledge graph accumulates contradictory entries that degrade retrieval quality.The
write_notetool withoverwrite=Trueonly helps when the caller knows the exact title of the existing note. In practice, agents don't — they know the topic but not whether a note already exists or what it's called.Proposed Solution
A new
upsert_notetool that leverages the existing FastEmbed embeddings to check for semantic duplicates before writing:Behavior:
search_notessimilarity_threshold:on_match="update": overwrite the matched note with new content (likewrite_notewithoverwrite=True, but the caller doesn't need to know the existing title)on_match="merge": append new content to the matched noteon_match="ask": return the match and let the caller decidewrite_note)Return value should indicate what happened:
{ "action": "updated_existing", "matched_note": "reference_bu_product_mapping", "similarity": 0.91, "path": "reference_bu_product_mapping.md" }Why This Fits basic-memory's Architecture
search_notes. Pure cosine similarity, same as the existing search pipeline.write_notestays unchanged.upsert_noteis additive.write_notealready hasoverwritelogic; this just makes it semantic-aware.Use Case
AI agents (Claude Code, Cursor, etc.) that use basic-memory as a persistent knowledge store across hundreds of sessions. Without server-side dedup, the only defense is prompting the agent to "search before write" — which works ~95% of the time but fails when context is long, the agent is in a hurry, or a subagent doesn't inherit the parent's rules.