Agent Memory Write Gate: What Never Gets Stored
An importance gate prevents noise from accumulating in persistent agent memory only as well as the test behind it: a write gate decides whether an incoming write is stored at all, and what it keeps out depends on what it tests, such as sameness, worth, or a type you declared.
Disclosure: we build Mnemoverse, one of the six products compared here. Every fact below, ours included, comes from a page its vendor published, read on 25 September 2026, and our own row is checked hardest.
TL;DR
- A write gate is a decision on the write path. It decides whether a write is stored, not how it ranks when memories are read.
- The name tells you little. Our own gate is called an importance gate and tests novelty; Mem0 uses the same phrase for a triage protocol whose second gate is called NOVELTY. A gate is known by what it tests.
- The test decides what stays out. A comparison with what is already stored catches repeats as far as its idea of sameness reaches, and not new chatter. A model's judgement against criteria you write catches chatter, at the cost of a model call. A test by declared type catches only what you declared.
- A refused write can become nothing, an update, a reason, a report for you to approve, or text that stays in the store. The vendor's page says which.
- You can check your own setup in minutes: write the same fact twice, write a correction phrased like the original, and see whether a refused write comes back with a reason.
What a write gate is, and why the name misleads
A write gate is a decision on the write path about whether an incoming write is stored at all. It is not how a memory ranks later, when memories are read. Whether it gets in.
The phrase importance gate appears in our own API reference. A write to Mnemoverse comes back with a field named stored, and the reference defines it in one line: "True if the atom passed the importance gate". The same response carries a field named importance and a field named reason, "Why stored or filtered". So what does the gate test? Our own library page answers:
Our shipped write-path gate scores geometric novelty against the nearest existing memory in the same domain.
That is from RAG vs Agent Memory. Mem0 uses the same phrase: its documentation applies it to the triage step of its plugin for the OpenClaw agent harness, "a structured protocol with importance gates and domain overlays".
So a gate is known by what it tests, not by what it is called. Whether it keeps noise out depends on the test.
What each product tests on the write path
One row per product, from what each one publishes. Where they use the word gate, they do not mean the same thing.
| Product | What the write-path test asks | Where it is documented | What happens to a write that does not pass |
|---|---|---|---|
| Mem0 | Add path: related existing memories are checked so it can avoid storing the same fact again; custom instructions in plain language decide what is recorded. OpenClaw plugin: a triage protocol whose Gate 2, NOVELTY, checks a candidate against memories already recalled, plus an importance value per fact | Mem0 docs, the OpenClaw integration page, and the plugin's SKILL.md in Mem0's repository on main | In the triage protocol, nothing is written; a known fact that has materially changed is updated in place |
| Cognee | Session distillation: a lesson is eligible when it has not been rated harmful and its confidence passes the distillation gate. Folder presort, when the caller asks for it | Cognee docs and its session distillation source on main | The distillation rejects a lesson with a reason; the presort reports groups and ingests the ones you approve |
| Letta | The reflection pass applies filters to each candidate: lasting or ephemeral, already captured, generalizable, relative dates made absolute, memory or skill. The prompt, read on 25 September 2026, publishes no order of precedence among them | Letta docs and the reflection prompt in Letta Code, its open harness, on main | If nothing survives the filters, no change and no commit |
| Supermemory | A model's judgement against a filter prompt you write, in effect when shouldLLMFilter is set to true. Its coding-agent plugins add a capture mode whose default filters noise | Supermemory docs, customization page | Content can be filtered from what gets indexed; no page read shows what the filter did to a given write |
| Zep | Declared type, speaker, identity and size. In Graphiti, its open framework, excluded entity types and extraction instructions you write | Zep help center and Graphiti's documentation and source | An episode over the size limit is rejected rather than truncated; the raw episode of an accepted write is kept |
| Mnemoverse | Novelty against the nearest existing memory in the same domain | Our API reference, our changelog and our library page | No memory is stored; the response says whether the write was stored or filtered, with a reason field |
Mem0
Mem0's add path checks related existing memories, "so it can avoid storing the same fact again", in the words of How Mem0 works. It also takes custom instructions in plain English, which its page describes as "acting as smart filters so your AI application only remembers what matters for your use case". On its two add pages, the API reference and the add operation, read on 25 September 2026, a write takes no importance argument.
One layer up there is more. Mem0's plugin for the OpenClaw agent harness extracts facts with "a structured protocol with importance gates and domain overlays", and the protocol is published in Mem0's own repository. A candidate fact has to pass every gate in that protocol, and Gate 2, NOVELTY, checks it against the memories already recalled. Rephrasing, synonyms and punctuation are not a difference there: "Only UPDATE if new information adds real context, details, or changes meaning." The plugin's write tool also takes an importance value from zero to one, with a default set by the fact's category, and a threshold on that value applies only when the plugin is configured with one.
Cognee
Cognee's distillation gate sits on the path from a conversation into permanent memory. Its improve page says: "Guidance is eligible only when it has not been rated harmful and its confidence passes the distillation gate." In Cognee's source that is two conditions, net helpfulness not below zero and confidence at or above one published constant. On the write path itself, its remember call can presort a folder first, when the caller asks for it.
Letta
Letta's memory page puts the decision in the agent's own judgement: "Your agent updates memory when it learns something durable." The rule behind it is published in the reflection prompt that Letta Code, its open harness, ships for the background pass. For each candidate the prompt lists filters to apply before acting, among them an already-captured check: "If memory or skills already contain this information adequately, skip it."
Supermemory
In Supermemory's settings, the test is a model's judgement against a filter prompt you write: "Tell Supermemory what content matters during ingestion. This helps filter and prioritize what gets indexed." The criterion is prose, set for the whole organisation, and applied to new content only: "Settings are organization-wide. Changes apply to new content only". It takes effect when the flag shouldLLMFilter is set to true. On the 146 documentation pages its own index lists and on 331 of its site pages, read on 25 September 2026, no page states a default for that flag. Its coding-agent plugins add tests of their own, among them a capture mode whose default filters noise.
Zep
Zep documents tests of declared type, speaker, identity and size. Extracted entities are matched by declared identity properties first, otherwise primarily by name: "When Zep extracts entities from episodes, it deduplicates them primarily by name." In Graphiti, the open framework under Zep, you can exclude entity types from extraction, and add_episode takes extraction instructions you write, which go into its extraction prompts.
Each row asks a different question of the same write.
What happens to the write that does not pass
A gate decides. Then something happens to what it turned down, and here the vendors split again.
In Mem0's OpenClaw triage protocol, a write that fails a gate is not written, and a known fact that has materially changed is updated in place; a rephrasing is not an update. The protocol states the expected result plainly: "Most turns produce zero memory operations. That is correct and expected."
In Letta's background reflection pass, if nothing survives the filters, it makes no changes, and nothing is committed to the memory repository.
Cognee's session distillation can reject a lesson, and its source gives each rejection a reason: already known, not durable, or unsupported. Its remember call can also presort a folder before it stores anything, and that scan "reports what is junk, duplicated, versioned, personal, or already in cognee, and then ingests the groups you approve". Here the no comes back to you.
Zep refuses on size: an episode over its documented limit is rejected rather than truncated. Its type and speaker filters act on what reaches the graph instead. With strict ontology on, "an entity that doesn’t match a declared type is dropped instead of added as an untyped node". Ignore a speaker, and the message itself is still added and retained. In both cases the write itself stays: each write becomes an episode, and "the raw source material remains searchable and retrievable", per how graph creation works. What extraction passes over is still in the episode, so the store grows by the original as well as by whatever was derived from it.
Supermemory, too, keeps your text as well as what it understood, for a document it processes. Per how it works, one document leads to three things, chunks, memories and a profile, and the chunks are the source, kept for grounding.
So a write that is turned down can become nothing, an update, a rejection with a reason, a report for you to approve, or text that stays in the store. The vendor's page says which.
Ours, checked hardest
Ours answers the refusal question in the response itself: stored, a null atom_id and a reason say whether a write was kept and why. The test behind it is novelty: it compares a write against the nearest existing memory in the same domain.
What does it refuse? Our public changelog says it in one sentence, in the 0.8.3 entry, for shared rooms:
A restatement, such as a briefing or a status summary, does store in a room, because a room is a message bus; only a write the embedder cannot distinguish from one already present is refused.
Which test matches which noise
A test that compares a write with what is already stored asks about sameness, not worth. Mem0's open source pipeline hashes each extracted memory and drops exact duplicates, and Mem0 names the limit of an exact match on its own blog:
Exact-match deduplication catches identical text, but "prefers window seats" and "always books window seats on long-haul flights" are different strings.
Its hosted platform reaches further, and says how far: "most exact or near-duplicate restatements of a fact you already have are recognised and deduplicated as the memory is added". Ours belongs in this family: it measures how much a write adds over what is already stored.
A test that asks a model can judge worth. Set Supermemory's LLM filter flag to true, and a model judges incoming content against a paragraph you write about what matters. Mem0's custom instructions do the same in plain English. Supermemory states its automatic side as a tendency, not a rule: "casual, non-meaningful chatter is less likely to become durable memory".
The price is a model call. Letta's option to have the agent review memory updates before applying them says, in its next sentence, that it uses more model tokens. And a judgement can miss. Mem0 writes that compressing on every write is usually what you want, "except when the fact you needed most is exactly the one it judged not worth keeping."
A test by declared type catches only what you declared. Turn on Zep's strict ontology, and an entity that does not match a declared type is dropped. By default Zep favours recall, and what does not match is still added, classified generically.
A written list works the same way. Mem0's OpenClaw plugin drops, by pattern, whole messages its own source calls noise: "Patterns that indicate an entire message is noise and should be dropped." The list covers acknowledgements, timestamps, tool output, JSON-only messages and single emoji.
So match the test to the noise. The same text twice: a hash is enough. The same fact reworded: a hash is not, by Mem0's own sentence. Chatter: a list that names it, or a model that judges it, at the cost of a call. Anything outside your schema: declared types.
Three checks you can run on your own setup
You do not need anyone's word for this, ours included. Three checks, on whatever memory layer you use today.
1. Write the same fact twice, then once more in other words. Look at what was kept. The reworded write is where the tests part ways. Cognee deduplicates by file content, not by filename, per its add page. The same bytes make no second record, and a comma of difference makes a new document. Mem0's hosted platform says most exact or near-duplicate restatements are recognised and deduplicated as the memory is added.
2. Write a correction, phrased like the fact it corrects. A test of sameness has to tell a correction from a restatement, and a correction is phrased almost like the fact it corrects. Vendors write down different answers. Mem0's plugin updates a known fact when its meaning changes. Zep "invalidates the old fact and keeps it as history". Letta's reflection prompt says to "fix the stale entry at the source". Run the check, and see what your store does.
3. When a write is turned away, see whether it comes back with a reason. Ours documents a reason field on the write response, "Why stored or filtered", and a refused write returns no memory; on the batch path, per our rooms page, "a refused item carries the gate explanation", while stored items currently carry an empty string. In Cognee's source, each lesson the distillation pass rejects carries a reason. Mem0's library shows a refusal as a worked example: "Empty results show the prompt successfully ignored content outside your target domain." Across its documentation, its site and its release notes, read on 25 September 2026, Supermemory publishes no way to see from outside what its filter did to a given write.
A refusal you cannot see is a memory you think you have.
Where to find an MCP memory server with noise filtering built in
Ours ships as a published MCP package, @mnemoverse/mcp-memory-server. The description its write tool sends to every client, in src/tools.ts, says a write may be filtered and that the result says whether the memory was stored or filtered.
Zep documents a Memory MCP server. On its server pages, the admission gates are checked at login: "Allowed domains (Custom OIDC) and allowed groups are admission gates checked at login against the signed claims from the identity provider." Admission into memory, its security page says, remains your application's job.
Supermemory's self-hosting page lists its MCP, managed endpoints on the hosted platform, among the platform-only features, and says the self-hosted binary does not include them.
For Mem0, Cognee and Letta, this page's facts do not cover an MCP server, so it makes no claim either way. Whichever server you connect, run the three checks through it, and read what the write tool gives back.
What this page does not claim
- No count of gates. The word gate means different things in different rows. This page defines the term and names each test; it does not count them.
- No performance number, for anyone, ours included. Nothing here says one test keeps a store cleaner than another in measured terms.
- Every absence is bounded. Where a sentence says a page does not state something, it names the pages read and the date, and it says nothing about what a vendor ships without writing down.
- Nothing about our internals beyond what our reference, rooms page, changelog, library page and published MCP package say.
Sources
Vendor pages read on 25 September 2026; every vendor address re-read on 26 September 2026; every quotation on this page re-read verbatim on 27 September 2026. Each quotation above is taken verbatim from one of the pages listed below.
- Mem0: How Mem0 works; custom instructions, Platform; custom instructions, Open Source; Add Memories API reference; add operation; OSS v2 to v3 migration; Dream; OpenClaw integration; memory-triage SKILL.md on main; OpenClaw filtering.ts on main; OpenClaw skill-loader.ts on main; blog, Dream; blog, infer=True vs infer=False.
- Cognee: improve; presort downloads; legacy add; session distillation source on main: distill.py, models.py, session_context_models.py.
- Letta: memory configuration; reflection prompt in Letta Code on main; blog, context repositories.
- Supermemory: customization; graph memory; how it works; self-hosting configuration; OpenClaw integration; GitHub releases; the page counts come from llms.txt, sitemap-blog.xml and sitemap-0.xml.
- Zep: how graph creation works; customizing graph structure; prepare data for ingestion; add messages to a thread; Graphiti custom entity and edge types; Graphiti graphiti.py on main,
add_episode; Memory MCP server authentication; security and compliance; agent memory product page. - Mnemoverse: API reference; rooms; changelog, the 0.8.3 entry; RAG vs Agent Memory; MCP server; mcp-memory-server src/tools.ts on main.
Common questions
What is a write gate in agent memory?
A write gate is a decision on the write path about whether an incoming write is stored at all. It is not how a memory ranks later, when memories are read. Products use the word gate for different things, so a gate is known by the test it runs, such as sameness against what is already stored, a model's judgement of worth, or membership of a type you declared.
How does an importance gate prevent noise accumulation in agent memory?
Only as well as its test. The phrase importance gate does not name one test. Our own shipped gate scores novelty against the nearest existing memory in the same domain. Mem0 uses the phrase for the triage step of its OpenClaw plugin, whose second gate is called NOVELTY; the same plugin's write tool takes an importance value with a default by category. A novelty test keeps out what is too close to something already stored; it does not keep out chatter that is new.
How do I filter out low-value background noise before it reaches agent memory?
Use a test that judges worth or names the noise. Supermemory takes a filter prompt judged by a model when its LLM filter flag is set to true. Mem0 takes custom instructions in plain language, and its OpenClaw plugin drops whole messages its own source calls noise, such as acknowledgements, timestamps and tool output. A test that only compares a write with what is already stored does not catch new chatter.
How do I prevent duplicate context buildup in agent memory?
Compare each write with what is already stored, and check how the comparison treats rewording. Exact matching catches identical text only: Cognee deduplicates by file content, and Mem0's open source pipeline drops exact duplicates by hash. Mem0's hosted platform says most exact or near-duplicate restatements are recognised as the memory is added. Write the same fact in other words and see what your store keeps.
What happens to a memory write that the gate refuses?
It depends on the product. In Mem0's OpenClaw triage protocol nothing is written. Letta's reflection pass skips a candidate that fails its filters and commits nothing if none survives. Cognee's session distillation rejects a lesson with a reason, and its folder presort reports groups for you to approve. Zep rejects an episode over its size limit, and keeps the raw episode when extraction passes over part of it. Supermemory keeps a processed document's source chunks, and publishes no way to see what its filter did to a given write. Ours returns no memory and a reason field.
Which MCP memory servers have noise filtering built in?
Of the six products read here, Mnemoverse ships a published MCP package whose write tool tells the client that a write may be filtered and that the result says whether it was stored or filtered. Zep documents a Memory MCP server and says admission into memory remains your application's job. Supermemory lists its MCP among the features of its hosted platform. This page's facts do not cover an MCP server for Mem0, Cognee or Letta, so it makes no claim either way.
