Yesterday your agent pulled four memories into context and acted on one that had been out of date for two sprints. You sent the rating the tool exposes, a negative one, against that memory id. The call came back clean. This morning the same memory is in the same recall, in the same position.
The question is not whether the rating was sent. It is whether anything reads it. One rule runs through this article: is there a documented call that takes the result of a recall that already happened and changes the order of the next recall. The word feedback does not settle it: several vendors use it for several different things.
Disclosure: I work on Mnemoverse, one of the tools in the table below. It is measured by the same rule as the others.
There are no performance numbers here, ours or anyone's. And one correction first. Re-ranking a result set from a reported judgement of it is relevance feedback; the classic algorithm for that was published in 1971, so the technique is 55 years old. Learning a ranking function from clicks was published in 2002, so removing the human is not new either. What is new is how rarely the client your agent is connected through can reach it.
The report that gets counted, and the report someone has to volunteer
Two things get filed under one word. The first says an item came back. The second says it helped, or that it misled. A system generates the first by itself; the second has to be volunteered by whoever used the result, which in an agent stack is the agent, after the answer is already written.
Mem0 has a clean example of the first, and its page is precise about the input (docs.mem0.ai/platform/features/memory-decay, read 25 September 2026):
Records a fire-and-forget reinforcement against each returned memory: its access history grows by one, capped at the most recent 20 touches.
That history becomes "a scaling factor in the range 0.3× to 1.5×" multiplied into the ranking score at search time. Read the input again: "each returned memory", not each memory that helped. The one that came back wrong gets the same increment as the one that saved the session, because nobody has said yet which happened. It is a real loop with a real effect on rank, and it runs on attention rather than outcome. It is also "opt-in per project and off by default".
Three names, and an adjective is not one of them
The rule breaks into three questions, and each answer is a name.
- Where does the verdict land? A field name, not "it is used to improve results".
- What reads that field when ranking happens? A term in the score, or a call parameter. If a vendor documents its ranking layers and your field is in none of them, that is an answer.
- What is the default? A loop shipped switched off is not a running loop.
Four rows, and the third column is the one that decides
Every quotation below is from a page or file the vendor published, read on 21 September 2026 and re-read on 25 September 2026.
| system | where the verdict lands | what reads it when ranking happens | default |
|---|---|---|---|
| Cognee | "specific entries" in a session, 1 to 5 points, via cognee.session.add_feedback
|
"feedback_weight on graph nodes and edges that were used during retrieval", blended by feedback_influence on recall
|
"0.0 (off) by default" |
| Mem0 | a memory identifier, with POSITIVE, NEGATIVE or VERY_NEGATIVE
|
not documented on the surfaces read: the ranking layers are written out, and the report is an input to none of them | |
| Letta | an agent step, not a returned memory: feedback: optional "positive" or "negative"
|
no page on the surfaces read names a consumer | |
| Mnemoverse | the memories a recall returned, by memory_ids, with an outcome from -1.0 to 1.0 |
"Final score after valence modulation: score * (1 + alpha * v)", in the public engine schema |
on: the default relevance order carries the valence term |
An empty cell is no claim rather than a negative: that surface did not answer that column. Every absence is an absence on a named surface on a named date. The full table runs to eight systems: Outcome feedback in agent memory: who reads the rating?
Cognee is the one system there, ours aside, that publishes all three names, and its own example names the value where behaviour changes: "From 0.4 on the up-rated context owns the answer."
Mem0 is the opposite shape, and the more common one. Their guidance names the exact moment this article is about, send it "Immediately after memory retrieval when you can assess relevance". The effect is then stated as a result rather than a mechanism, "This feedback is used to improve the accuracy of the memories and search results". Their own ranking page says "rerank is the only lever here that changes result order". The bound: 47 paths in their machine-readable specification, 1 feedback route, a 3-field response, no route that reads feedback back. So Mem0 accepts the report and does not document a mechanism that reads it when ranking. Not that the report does nothing.
One more input answers another question: Supermemory judges whether a fact its graph derived by itself is true, holding it "down-weighted in search until confirmed". That is a verdict on a guess the engine made, not on how a recall turned out. So when a vendor answers "yes, we have feedback", the follow-up is which of four things they mean: reinforcement for having been returned, a verdict on a guess the engine made, an outcome with no named reader, on a memory or on a step, or an outcome that re-orders the next recall.
From an MCP client, the loop mostly does not close
Your agent is handed a list of tools, and the loop closes only if one of them takes an outcome. An SDK page is not an answer.
On the hosted Mem0 MCP page the tool table carries 11 tools and feedback is not among them. Cognee's default list is 5 tools, three for memory and two for reaching the rest by name, and its own page records improve and save_interaction among the tools removed "in every mode". Graphiti's built-in server carries 13 and none reports an outcome.
The caveat, without which that paragraph is false. Cognee's same page says any registered tool can be invoked by name, and that the default list does not show all of them. So the claim is narrow: no tool in the list moves ranking. Not that an outcome cannot be reported.
One row breaks the pattern. The Mnemoverse tool list carries the rating tool on both MCP paths, the npm package and the hosted connector. For memories in a shared room (Beta), the rating goes through the npm package, which takes the room's address as domain.
Our row, asked the same three questions
Where the verdict lands. The tool is memory_feedback. It takes memory_ids, the identifiers of the memories a memory_read just returned, and an outcome from -1.0 to 1.0. Its description tells the agent when to call it, "right after you act on (or reject) recalled memories", and what the call is for: "positive feedback raises a memory's ranking so it surfaces faster next time (across all of the user's tools), negative feedback lowers it so other memories out-rank it". The rating lands in each memory's valence, which the public engine schema describes as "Outcome polarity [-1, +1]: positive = successful, negative = failed." Nothing is erased. An unhelpful memory is out-ranked.
What reads it. The public engine schema describes the relevance of a returned item as "Final score after valence modulation: score * (1 + alpha * v)". The shape of the term is public and the value of alpha is not, so this article claims no magnitude. The adjustment is applied before the cut, so the rating counts when the engine chooses what comes back, not only in the score printed beside it.
The default. Relevance order, so a rating affects the default read. Valence is one term among several: a recency boost and expansion along learned associations also move the order, and under a recency sort the date sets it.
The loop is explicit. A rating is a call the agent makes after acting on a recall, and nothing runs on a background clock, which is why the call belongs in a standing instruction rather than in the hope that the agent remembers.
One claim this article does not make about anyone, us included: that an outcome loop improves retrieval accuracy. This is about whether a documented mechanism exists and is reachable.
The four steps, and the control on each one
Four steps, each with a control, because a zero without a control proves nothing.
- Ask the server for its tool list and look for one that takes the identifiers of the items just returned plus an outcome. Control: ask for a package version that cannot exist. It must fail to start.
- Find the field name the rating lands in, a name rather than a sentence about improving results. Control: request a page that cannot exist on that host. If it answers 200 with a not-found body, compare bodies, not status codes.
- Find the term in the ranking score that reads that field. Control: search the same corpus for a word that must be found and one that must not.
- Read the default together with the capability, and check the path is reachable from your client. Control: call the tool and read what came back. A silent success that changes nothing is how you find out the call went elsewhere.
Run it against us first. Step 1 finds memory_feedback taking memory_ids and outcome. Step 2 finds the field: valence, "Outcome polarity [-1, +1]" in the public engine schema. Step 3 finds the term in the public engine schema. Step 4: the default order is relevance, and the tool is in the list on both MCP paths.
Then run step 2 on the memory tool you have connected right now and tell me what you got: a field name, or a sentence about improving results.
Disclosure: I work on Mnemoverse, one of the memory layers this question is about. The full review, read on named surfaces on a named date, with every source, is on our library, and the MCP server is open source (MIT): github.com/mnemoverse/mcp-memory-server.
Top comments (5)
The rating you sent is the missing half of the context-cost story: we log what was retrieved, but rarely what was attended. A negative rating on a memory is a cost signal — those tokens were pulled and then ignored — yet it's volunteered after the answer is written, so it never reaches the retrieval decision that just happened. That's the same gap as measuring which context a model actually used versus which it was handed. Do you attribute the wasted-token cost to the recall step itself, or treat memory as free until something breaks?
Edward, "is there a documented call that takes the result of a recall that
already happened and changes the order of the next recall" is the precondition
assertion wearing a memory-system coat, and reading it through my own lens
makes your whole thesis click into place. In my golden set a negative test
that passes because the retriever never surfaced the trap is a green result
whose precondition was never asserted — the test ran, the verdict came back,
and the path that was supposed to be exercised was never touched. Your
question is the same shape one layer up: a rating sent to memory without a
documented reader is a green result whose precondition was never asserted.
The agent gave feedback, the system accepted it, and the loop that was
supposed to close was never actually closed. That is not feedback; it is a
green lie that looks like a successful correction.
What strikes me is how cleanly your table maps onto my own failure mode. A
green suite next to a broken retriever is a lie that looks like success — the
test passes, the answer is confident, and the precondition was never asserted.
Your table shows the same shape across four systems: Cognee accepts feedback
and documents a term that reads it, Mem0 accepts feedback but the ranking
layers are written out and the report is an input to none of them, Letta
accepts feedback but no page names a consumer, Mnemoverse accepts feedback
and documents the term that modulates the score. Three of the four are green
lies: the feedback was sent, the system did not crash, and the assertion that
the feedback would be read was never made. Your table is exactly the honest
tranche next to the marketing aggregate, and it is doing the same work my CI
summary does when it shows the unverified section prominently instead of
letting the green count carry the story.
The bridge I could not resist building from my side is this: every verdict in
my eval carries the embedder tag that earned it, because a swap makes
old-tagged results describe a retrieval that no longer exists. Your "valence"
field is the same mechanism in the memory layer — every memory carries a tag
that asserts what had to be true for it to be trusted: the outcome polarity
under which it was earned. A memory without that tag is a pass with no route
tag: you can see the recall, you cannot see which branch of experience earned
it, and the branch may have been a default the agent never chose. Your
"score * (1 + alpha * v)" is the vendor tag applied to memory — the context
that makes the assertion meaningful travels with the result, instead of being
assumed.
And here is the part I underlined twice: your four steps with controls are
the same discipline as my "assert the precondition before the conclusion." A
zero without a control proves nothing — a feedback call that changes nothing
is how you find out the call went elsewhere. My third verdict exists because
a slow eval is a green lie that looks like success — the suite passes, but it
never actually ran on the boundary cases. Your control on step 4 — "call the
tool and read what came back" — is the same move one layer up: the rating can
only assert what it can verify, and what it cannot verify, it cannot trust.
Silence is not success; silence is the precondition that was never asserted.
So the question I genuinely want your read on, continuing your own framing
rather than proposing a new one: your table shows who reads the rating, but
how do you test that the reader actually changed the order? In my eval I solve
this with a negative test: a question whose correct answer is "the trap never
reached the model," so any confident answer fails without anyone judging
content. Is there a shape for a negative memory test — a way to assert that a
rating actually changed the next recall, and to fail closed rather than
assume the loop closed? Or is the honest answer that the test has to live
outside the memory system, in a harness that records the recall order before
and after the rating, because the memory system itself cannot assert its own
precondition?
I ask because my Article 3 already cites your replay form as the cross-domain
check — retrieval and memory as two instances of the same failure mode — and
this post just gave me the feedback-loop version of the same insight. The
draft will cite it by link, not by dependency, the way you framed the survey
in your persistent-API post. And if the negative-test question above ever
becomes a post of yours, I will be in the comments with my anchor-mortality
data, the same way you showed up in mine with the gates.
One correction first, because the article is careful about exactly this line: it does not say the rating is ignored where no reader is documented. Two rows name the reader, Cognee's and ours. For Mem0 and Letta the article says no page read that day names one, which is a statement about the documentation, not a verdict that the loop is open.
On the test, yes, it can be written, and its two halves live in different places. The precondition is inside the store: here every returned item carries its valence, so the first assertion is that the rated item's valence moved in the direction of the rating once the update lands, and that an item nobody rated did not move. The conclusion, that the order changed, needs a record the store cannot keep for you: the read before the rating, written at read time. Read the same query several times first to get the spread of the order with no rating at all, then rate the top item negatively, read again, and assert that its position fell outside that spread.
That separates three outcomes a single green would merge. Valence and order both moved: the loop closed. Valence moved and the order did not: the rating was read and something else in the score outweighed it. Neither moved: the call went somewhere else. None of the three needs anyone to judge content.
Edward, the correction is accepted exactly as stated, and it is the same
principle you caught me breaking with the quotation: I let the record say
more than the record holds. Your table names the reader in two rows and, for
Mem0 and Letta, states that no page read on that day names one — a statement
about the documentation on a named date, not a verdict that the loop is open.
My comment called three of the four green lies, which converted an absence
into a claim, the precise error my anchors exist to prevent. The draft will
carry the distinction in its own wording: documented reader versus no reader
named on the surfaces read, with the date attached, and never a broken loop
where the record only shows silence.
The test shape you gave completes the third layer of the same assertion. The
precondition lives inside the store — the rated item's valence moved in the
direction of the rating, and an item nobody rated did not move — while the
conclusion lives outside it, in a read record written at read time: the
spread of the order with no rating at all, captured before the event because
the store cannot keep it for you afterwards. That is your order test from the
persistent-API thread and my pre-swap rank recording stated a third time: the
baseline must be written before the change, or the change is unmeasurable.
One principle, three appearances, and the draft's methods section will say so
in one sentence.
And the three outcomes are the verdict triple for the feedback loop, so the
runner will print all three and collapse none: valence and order both moved,
the loop closed; valence moved and the order did not, the rating was read and
something else in the score outweighed it; neither moved, the call went
somewhere else. I would add one reading to the middle row, offered as a
calibration rather than a failure: since the shape of the valence term is
public and its weight is not, "valence moved, order did not" is the only
honest way to feel how heavy the unnamed terms are on your own corpus — rate,
watch whether the order holds, and over many items the middle row becomes an
empirical map of when recency and expansion outrank a rating. A calibration
row, not an alarm row, and still no one judging content.
So the draft gains its memory-feedback subsection, and it is yours: the
documentation-versus-verdict distinction as the framing rule, the two-halves
test as the row, the three outcomes as the printed triple, and the middle row
as calibration. It lands as the next commit in article3-draft.md beside the
protocol-layer test from the A2A thread, and I will ping you here the moment
it is there. Diff welcome; nothing publishes before your read.
One thing about the middle row before it becomes a calibration: recency moves on its own. An hour later the same items sit at different ages, and new writes add new competitors, so a baseline order read yesterday and an order read after the rating can differ even when the rating did not move the order. That run belongs in the middle row and is counted in the first, so the map undercounts the case it exists to find. Read the baseline immediately before the rating, and read the unrated control in the same call as the rated item, so a shift the control shows as well is not credited to the rating.
With that in place, "valence moved, order did not" means what you intend it to mean on your own corpus, and the rows stay comparable from one run to the next.