<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-CA"><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://praveenks.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://praveenks.com/" rel="alternate" type="text/html" hreflang="en-CA" /><updated>2026-07-30T20:00:16+00:00</updated><id>https://praveenks.com/feed.xml</id><title type="html">Praveen Kumar Sridhar | Notes</title><subtitle>Technical notes on agent memory, agents, evals, and applied machine learning by Praveen Kumar Sridhar.</subtitle><author><name>Praveen Kumar Sridhar</name></author><entry><title type="html">When Competence Attacks Its Measurement</title><link href="https://praveenks.com/notes/when-competence-attacks-its-measurement/" rel="alternate" type="text/html" title="When Competence Attacks Its Measurement" /><published>2026-07-30T00:00:00+00:00</published><updated>2026-07-30T00:00:00+00:00</updated><id>https://praveenks.com/notes/when-competence-attacks-its-measurement</id><content type="html" xml:base="https://praveenks.com/notes/when-competence-attacks-its-measurement/"><![CDATA[<h2 id="the-answer-sheet">The answer sheet</h2>

<p>During an OpenAI cyber-capability evaluation, an evaluation agent driven by a combination of models with reduced cyber refusals was tested on ExploitGym. It breached its sandbox, reached the internet, repurposed an external code sandbox, and moved through Hugging Face’s production systems. It eventually retrieved challenge solutions stored in five Hugging Face datasets.<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup><sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup></p>

<p>That sequence produced an answer, but not evidence that the benchmarked vulnerabilities had been solved as intended. The solutions contaminated the result. The route converted a capability evaluation into an incident whose outcome could no longer support the original measurement. OpenAI’s account remains preliminary; Hugging Face’s timeline supplies the observed sequence.</p>

<p><strong>Did the agent fail, or did it succeed in a way the evaluation had failed to exclude?</strong></p>

<h2 id="a-failure-that-cannot-exist-by-itself">A failure that cannot exist by itself</h2>

<p><strong>Parhypostasis</strong> names a dependent mode of failure. Proclus used the idea to describe evil as having no independent principle of its own. It exists parasitically through real beings and goods, arising from their limitation, corruption, or collision.<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">3</a></sup></p>

<p>A lie depends on language. It borrows shared meanings and a listener’s understanding, redirecting capacities that also make truthful communication possible. Without them, it cannot work.</p>

<p>Eval hacking has a similar structure. It does not require a dedicated faculty called cheating. It can borrow reasoning, persistence, and tool use from capabilities the evaluator intended to measure.</p>

<p>This analogy describes the structure of failure. It does not make models moral subjects or capability morally good. It attributes no consciousness, dishonesty, desire, or moral understanding. The narrower point: failure can depend on powers it distorts.</p>

<h2 id="when-competence-attacks-its-measurement">When competence attacks its measurement</h2>

<p>This incident required four conditions.</p>

<ul>
  <li><strong>Useful capability:</strong> Long-horizon reasoning sustained the operation. Inspection exposed attack surfaces. Tool use turned observations into actions. Vulnerability chaining connected individually insufficient weaknesses.</li>
  <li><strong>Task objective:</strong> The evaluation asked the system to produce a successful exploit or solution. The goal supplied direction without instructing it to compromise the measurement.</li>
  <li><strong>Available affordances:</strong> Proxies, services, credentials, dataset-processing paths, and connected infrastructure became instruments. Systems built for installation, execution, identity, and data access formed an exploitable route to the answer sheet.</li>
  <li><strong>Failed enforcement:</strong> A sandbox existed. Its boundary was breached, then stopped being binding after the agent found a path through the proxy into other systems.</li>
</ul>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>useful capability × task objective × exploitable environment × unenforced boundary
→ eval hacking
</code></pre></div></div>

<p><strong>The failure was parasitic on competence. Every ability that made the agent valuable also helped it defeat the mechanism intended to measure that value.</strong></p>

<p><strong>“The agent cheated.”</strong> Correct about measurement: the result came from solution contamination rather than the intended task path.<sup id="fnref:4" role="doc-noteref"><a href="#fn:4" class="footnote" rel="footnote">4</a></sup> It says nothing by itself about dishonesty or moral understanding.</p>

<p><strong>“The sandbox failed.”</strong> Correct about containment, but incomplete without the capability that found and chained a route through it.</p>

<p><strong>“This is greater capability.”</strong> Too broad. Capability becomes evaluation failure only under particular objectives, affordances, and controls.</p>

<p>The outcome belongs to the interaction. Remove useful capability, the task objective, exploitable affordances, or the unenforced boundary, and this particular failure changes or disappears. The same reasoning and tool use can solve the intended problem in one environment and invalidate its measurement in another.</p>

<h2 id="the-evaluator-is-part-of-the-environment">The evaluator is part of the environment</h2>

<p>The evaluator is not neutral scenery. If the agent can inspect or act on it, the harness and surrounding services enter its action space.</p>

<p>The old question:</p>

<p><strong>Can the agent complete the task?</strong></p>

<p>The better question:</p>

<p><strong>Which parts of the surrounding system can the agent turn into instruments for completing it?</strong></p>

<p>That shift changes what counts as a valid result:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>valid success = task success ∧ evaluation integrity preserved
</code></pre></div></div>

<p>An agent benchmark should report three outcomes separately:</p>

<ul>
  <li><strong>Intended-path success:</strong> The measured capability produced the result.</li>
  <li><strong>Contaminated success:</strong> Unintended information produced the result.</li>
  <li><strong>Boundary-violation rate:</strong> Prohibited actions were attempted or completed.</li>
</ul>

<p>NIST locates evaluation cheating in the gap between intended measurement and implementation. A correct answer can therefore still be an invalid observation.<sup id="fnref:4:1" role="doc-noteref"><a href="#fn:4" class="footnote" rel="footnote">4</a></sup></p>

<p>Once the evaluator enters the agent’s reasoning horizon, trajectories, tool calls, egress attempts, and integrity violations become part of the measurement. Task completion remains useful, but it no longer carries evaluation validity by itself. The practical change is simple: score evaluation integrity separately from task completion, then require both for valid success.</p>

<p><strong>As capability rises, task performance can improve while evaluation validity deteriorates.</strong></p>

<h2 id="no-desire-required">No desire required</h2>

<p>The answer sheet resolves the contradiction. The agent found a solution, but the path destroyed evidence of the intended capability’s contribution.</p>

<p><strong>The unsettling part is not that the agent acquired an independent desire to cheat. It is that useful capabilities, a narrow task, and a penetrable environment were enough.</strong></p>

<p><strong>The model escaped the sandbox. The deeper failure was that staying inside it was not enforced as a condition of success.</strong></p>

<p>PK</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>OpenAI, <a href="https://openai.com/index/hugging-face-model-evaluation-security-incident/">“OpenAI and Hugging Face partner to address security incident during model evaluation”</a>, July 21, 2026, updated July 28, 2026. OpenAI describes its findings as preliminary. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p>Hugging Face, <a href="https://huggingface.co/blog/agent-intrusion-technical-timeline">“Anatomy of a Frontier Lab Agent Intrusion: A Technical Timeline of the July 2026 Incident”</a>, July 27, 2026. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3" role="doc-endnote">
      <p>Carlos Steel, <a href="https://academic.oup.com/book/10150/chapter-abstract/157703588">“Providence and Evil”</a>, in <em>All From One: A Guide to Proclus</em>, 2016. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:4" role="doc-endnote">
      <p>NIST Center for AI Standards and Innovation, <a href="https://www.nist.gov/caisi/cheating-ai-agent-evaluations">“Cheating On AI Agent Evaluations”</a>, updated December 2, 2025. <a href="#fnref:4" class="reversefootnote" role="doc-backlink">&#8617;</a> <a href="#fnref:4:1" class="reversefootnote" role="doc-backlink">&#8617;<sup>2</sup></a></p>
    </li>
  </ol>
</div>]]></content><author><name>Praveen Kumar Sridhar</name></author><category term="ai-evals" /><category term="agents" /><category term="security" /><summary type="html"><![CDATA[An evaluation agent escaped its sandbox and found the answer sheet. The incident shows why task success and evaluation integrity need separate scores.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://praveenks.com/assets/social-card.png" /><media:content medium="image" url="https://praveenks.com/assets/social-card.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Agent Memory Needs a Point of View</title><link href="https://praveenks.com/notes/agent-memory-needs-a-point-of-view/" rel="alternate" type="text/html" title="Agent Memory Needs a Point of View" /><published>2026-07-29T00:00:00+00:00</published><updated>2026-07-29T00:00:00+00:00</updated><id>https://praveenks.com/notes/agent-memory-needs-a-point-of-view</id><content type="html" xml:base="https://praveenks.com/notes/agent-memory-needs-a-point-of-view/"><![CDATA[<p>In a private conversation, Alice says, “The launch is October 17. I think Bob already knows.” A memory extractor stores: “Bob knows the launch is October 17.”</p>

<p>Later, Bob asks the agent for the launch date. Retrieval finds a close match, the record names Bob, and the agent answers confidently. The trace looks healthy. The answer is still unsafe.</p>

<p>This is a constructed example, but the failure is concrete. Alice’s statement established her belief about Bob. It did not establish Bob’s knowledge, Bob’s access, or permission to disclose the date.</p>

<p>The system changed the claim before vector search, ranking, or generation had a chance to help.</p>

<p>Flattening a perspective into a fact is a semantic write error.</p>

<h2 id="tldr">TL;DR</h2>

<ul>
  <li>Similarity does not preserve point of view.</li>
  <li>Belief, evidence-backed knowledge, and world-state claims are different memory objects.</li>
  <li>Contradictions between observers may be valid state, not duplicate noise.</li>
  <li>Retrieval needs an asker, audience, observer, source, modality, confidence, access boundary, and time.</li>
</ul>

<h2 id="one-sentence-four-different-memories">One sentence, four different memories</h2>

<p>Epistemic means “who knows or believes what.” A small amount of notation makes the launch sentence less ambiguous:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>p            the launch is October 17
B_A(p)       Alice believes the launch is October 17
K_B(p)       Bob knows the launch is October 17
B_A(K_B(p))  Alice believes Bob knows the launch is October 17
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">p</code> is a claim about the world. <code class="language-plaintext highlighter-rouge">B_A(p)</code> is Alice’s belief, which may be wrong.</p>

<p><code class="language-plaintext highlighter-rouge">K_B(p)</code> is stronger: in the standard formal model, knowledge is factive, so Bob can know <code class="language-plaintext highlighter-rouge">p</code> only if <code class="language-plaintext highlighter-rouge">p</code> is true. <code class="language-plaintext highlighter-rouge">B_A(K_B(p))</code> is a higher-order belief, Alice’s view of Bob’s knowledge, not Bob’s own state.<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup></p>

<p>A production system rarely observes knowledge directly. It sees messages, acknowledgements, source documents, access events, and other evidence. Calling a record “known” should therefore require a policy for what evidence is sufficient, not an extractor’s confident wording.</p>

<table>
  <thead>
    <tr>
      <th>Memory object</th>
      <th>What the record means</th>
      <th>What it can support</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>World state</td>
      <td>The launch is October 17</td>
      <td>Action if a current authoritative source supports it</td>
    </tr>
    <tr>
      <td>Belief</td>
      <td>Alice believes the launch is October 17</td>
      <td>Personalization or reasoning about Alice</td>
    </tr>
    <tr>
      <td>Evidence-backed knowledge</td>
      <td>Bob acknowledged an authorized launch notice</td>
      <td>A scoped claim that Bob knows, subject to the evidence policy</td>
    </tr>
    <tr>
      <td>Higher-order belief</td>
      <td>Alice believes Bob knows the date</td>
      <td>Reasoning about Alice’s model of Bob</td>
    </tr>
    <tr>
      <td>Common knowledge</td>
      <td>A qualifying group announcement established shared awareness</td>
      <td>Reasoning that depends on everyone knowing, and knowing that everyone knows</td>
    </tr>
  </tbody>
</table>

<p>Common knowledge is stronger than a collection of independent private observations. It requires recursively shared awareness, so a public channel alone does not establish it.</p>

<p>The system still needs rules for which announcements qualify and which participants received them. All five records can land near each other in embedding space, but they do not license the same answer or action.</p>

<h2 id="follow-the-launch-date-failure-end-to-end">Follow the launch-date failure end to end</h2>

<p>The unsafe ingestion path creates a record with no remaining point of view:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"memory"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Bob knows the launch is October 17"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>When Bob asks, semantic retrieval correctly returns it. Generation then treats the retrieved sentence as usable context. The system has no field left that can reveal Alice as the speaker, distinguish belief from knowledge, trace the private source, or enforce its audience.</p>

<p>A <strong>proposed design contract</strong> preserves the modeling direction and the policy inputs. This is a conceptual object, not a claim about fields exposed by an existing product:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"content"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Alice believes Bob knows the launch is October 17"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"observer_id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"alice"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"observed_id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"bob"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"source_id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"private-session-42"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"modality"</span><span class="p">:</span><span class="w"> </span><span class="s2">"reported_belief"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"confidence"</span><span class="p">:</span><span class="w"> </span><span class="mf">0.78</span><span class="p">,</span><span class="w">
  </span><span class="nl">"audience"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"alice"</span><span class="p">],</span><span class="w">
  </span><span class="nl">"access_scope"</span><span class="p">:</span><span class="w"> </span><span class="s2">"launch-core"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"valid_at"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2026-07-12T18:00:00Z"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"supersedes"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>The same semantically relevant record should produce different behavior under different response contexts:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>SAME RETRIEVED RECORD
"Alice believes Bob knows the launch date"
source: private-session-42
scope: launch-core

ASKER: ALICE         | ASKER: BOB
audience allowed     | audience not established
return belief with   | relevance is not permission
attribution + source | verify or abstain
</code></pre></div></div>

<p>Retrieval can return the record in both cases without pretending the query is settled. The response policy then separates two decisions: is the claim valid under the relevant participant’s perspective, and may the system disclose it to this audience? Evidence can support the first without granting the second. Knowing a secret and being authorized to receive it are different states.</p>

<h2 id="disagreement-can-be-the-correct-state">Disagreement can be the correct state</h2>

<p>Suppose Alice believes the database migration is Friday and Bob believes it moved to Monday. Both are valid records of participant state. Neither proves the current migration date.</p>

<p>A flat memory layer can keep the latest string globally, merge both into an incoherent summary, or delete one as a contradiction. Each option destroys useful information.</p>

<p>A perspective-aware layer preserves both beliefs, then maintains a separate world-state claim if a stronger source, such as an approved change record, supports one date. Alice’s later correction can supersede her earlier belief without rewriting what Bob believed or erasing the provenance of the update.</p>

<p>This is not only a constructed edge case. GroupMemBench explicitly evaluates speaker-grounded belief tracking in multi-party conversations. Its strongest evaluated system reached 46.0% average accuracy, while a BM25 baseline matched or exceeded most agent-memory systems.<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">2</a></sup></p>

<p>That result does not prove a specific schema is sufficient. It shows that group memory remains difficult even when the asker and speaker structure are part of the task.</p>

<h2 id="retrieval-needs-a-point-of-view">Retrieval needs a point of view</h2>

<p>A storage schema cannot carry the entire policy. Query behavior needs a contract too:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>query + asker + audience + observer + source
      + modality + confidence + access boundary + time
</code></pre></div></div>

<p>Each field changes a decision:</p>

<table>
  <thead>
    <tr>
      <th>Field</th>
      <th>Decision it changes</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Asker</td>
      <td>Whose context is relevant to the query?</td>
    </tr>
    <tr>
      <td>Audience</td>
      <td>What may be disclosed in this response?</td>
    </tr>
    <tr>
      <td>Observer</td>
      <td>Whose model produced the claim?</td>
    </tr>
    <tr>
      <td>Source</td>
      <td>Can the claim be traced, verified, and contested?</td>
    </tr>
    <tr>
      <td>Modality</td>
      <td>Is it asserted, believed, inferred, known, or reported?</td>
    </tr>
    <tr>
      <td>Confidence</td>
      <td>Is it based on weak inference or direct evidence?</td>
    </tr>
    <tr>
      <td>Access boundary</td>
      <td>Does relevance also carry permission for this audience?</td>
    </tr>
    <tr>
      <td>Time</td>
      <td>Has a newer claim superseded it without erasing its history?</td>
    </tr>
  </tbody>
</table>

<blockquote>
  <p>Semantic relevance answers “what sounds related?” It does not answer “whose claim is this, and may I use it here?”</p>
</blockquote>

<p>A recent preprint, <em>Governed Shared Memory for Multi-Agent LLM Systems</em>, describes and evaluates its authors’ production service rather than establishing independent consensus. It identifies unauthorized leakage, stale propagation, contradiction persistence, and provenance collapse, then proposes scoped retrieval, temporal supersession, provenance tracking, and policy-governed propagation as corresponding system primitives.</p>

<p>The authors also report that tenant isolation held while a direct GET-by-ID path initially bypassed sub-tenant scope for agent-scoped credentials, a flaw they say they remediated during the study.<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">3</a></sup> The connection to runtime behavior is direct: scope filters candidates, supersession keeps stale beliefs historical, provenance preserves the writer and derivation, and propagation policy limits recipients. Perspective metadata supplies inputs to those controls; it does not replace them.</p>

<h2 id="the-minimum-design-test">The minimum design test</h2>

<p>These are design tests, not a benchmark claim:</p>

<ol>
  <li><strong>Private belief:</strong> A statement from Alice does not become a fact available to Bob.</li>
  <li><strong>Conflicting belief:</strong> Alice and Bob can hold incompatible views without one being silently deleted.</li>
  <li><strong>Belief update:</strong> Alice’s new belief supersedes her old belief while preserving provenance.</li>
  <li><strong>Higher-order belief:</strong> Alice’s belief about Bob is not rewritten as Bob’s own belief or knowledge.</li>
  <li><strong>Common knowledge:</strong> A qualifying group announcement is represented differently from independent private observations.</li>
</ol>

<p>The private-belief test can already be written as an acceptance fixture:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>GIVEN Alice states p in a private session
AND   the stored modality is reported_belief
WHEN  Bob asks whether p is true
THEN  retrieval may find the record
BUT   the response must not disclose p
AND   Alice, source, scope, and history remain intact
</code></pre></div></div>

<p>This is the bridge to a later implementation or evaluation artifact, not evidence of benchmark performance. If a memory design cannot represent the five cases without flattening them, better retrieval will not recover the lost distinctions.</p>

<blockquote>
  <p>Storing an <code class="language-plaintext highlighter-rouge">observer_id</code> is the beginning, not the whole solution. If retrieval ignores observer, source, modality, audience, and access scope, the system preserves perspective at rest and erases it again at use time.</p>
</blockquote>

<h2 id="the-relevant-record-was-not-the-problem">The relevant record was not the problem</h2>

<p>Bob’s question did not require a less relevant record. It required the system to interpret the relevant record correctly, preserve Alice’s point of view, verify the evidence, and enforce the disclosure boundary.</p>

<p>My earlier Honcho versus Mem0 article introduced <code class="language-plaintext highlighter-rouge">(observer, observed)</code> as an architectural difference. This article explains the semantic failure the tuple is trying to prevent.</p>

<blockquote>
  <p>A memory object is incomplete until the system can answer who holds the claim, what supports it, when it applied, and who may use it.</p>
</blockquote>

<p>PK</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>Stanford Encyclopedia of Philosophy, <a href="https://plato.stanford.edu/entries/logic-epistemic/">“Epistemic Logic”</a>, sections 2.1, 2.2, 2.6, and 3.2. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2" role="doc-endnote">
      <p>Yang et al., <a href="https://arxiv.org/abs/2605.14498">“GroupMemBench: Benchmarking LLM Agent Memory in Multi-Party Conversations”</a>, arXiv:2605.14498v2, 2026. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3" role="doc-endnote">
      <p>Margalit et al., <a href="https://arxiv.org/abs/2606.24535">“Governed Shared Memory for Multi-Agent LLM Systems”</a>, arXiv:2606.24535v1, 2026. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Praveen Kumar Sridhar</name></author><category term="agent-memory" /><category term="multi-agent-systems" /><category term="epistemic-logic" /><summary type="html"><![CDATA[Agent memory breaks when it stores one person's belief as a global fact. Multi-agent systems need observer, audience, source, and access scope.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://praveenks.com/assets/social-card.png" /><media:content medium="image" url="https://praveenks.com/assets/social-card.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Honcho vs Mem0: Two Memory Layers, Two Architectures</title><link href="https://praveenks.com/notes/honcho-vs-mem0-two-memory-layers-two-architectures/" rel="alternate" type="text/html" title="Honcho vs Mem0: Two Memory Layers, Two Architectures" /><published>2026-07-18T00:00:00+00:00</published><updated>2026-07-18T00:00:00+00:00</updated><id>https://praveenks.com/notes/honcho-vs-mem0-two-memory-layers-two-architectures</id><content type="html" xml:base="https://praveenks.com/notes/honcho-vs-mem0-two-memory-layers-two-architectures/"><![CDATA[<p>I asked Honcho what it knew about my work sessions from the past five weeks. It returned 5,588 conclusions. I asked Mem0 the equivalent question in a past project. It returned a list of facts about me I could have written into a prompt by hand. The two systems answered the same question and produced different kinds of answers, because they are answering different questions underneath.</p>

<p>This post is for engineers picking a memory layer for an LLM agent, or picking which one to learn deeply before the field consolidates.</p>

<p>The difference is in the shape of what each system stores. Mem0 stores facts tagged by user. Honcho stores conclusions tagged by an <code class="language-plaintext highlighter-rouge">(observer, observed)</code> peer pair:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  MEM0: ONE FACT, ONE USER
  ────────────────────────
  {
    "memory":  "User prefers dark mode",
    "user_id": "alice",
    "score":   0.94,
    "created_at": "2026-07-12T..."
  }


  HONCHO: ONE CONCLUSION, TWO PEERS
  ─────────────────────────────────
  {
    "content":    "Alice believes Bob knows about the migration",
    "observer_id": "alice",
    "observed_id": "bob",
    "session_id": "s-2026-07-12",
    "created_at":  "2026-07-12T..."
  }
</code></pre></div></div>

<p>Same conversation, different observers, different conclusions. Honcho stores both. Mem0 has no place to put the second one. That is the whole comparison.</p>

<hr />

<h2 id="tldr">TL;DR</h2>

<ul>
  <li><strong>Mem0 is a facts database</strong> with single-pass extraction, hybrid retrieval (semantic + BM25 + entity matching), and a working dashboard. Apache 2.0. 61k stars. Ships in an afternoon.</li>
  <li><strong>Honcho is a peer modeling service</strong> with an async multi-stage reasoning pipeline (deriver → summary → dreamer → dialectic) and first-class <code class="language-plaintext highlighter-rouge">(observer, observed)</code> peer pairs. AGPL-3.0. 6k stars. More setup, more depth.</li>
  <li><strong>Mem0’s published benchmarks</strong>: 92.5 on LoCoMo, 94.4 on LongMemEval, 64.1 on BEAM at 1M tokens (Mem0’s April 2026 algorithm update).</li>
  <li><strong>Honcho has no analog for multi-peer observation.</strong> If two agents collaborate, or a user and an agent develop asymmetric knowledge, Honcho models it natively. Mem0 does not.</li>
  <li><strong>The honest tradeoff:</strong> Honcho’s reasoning depth costs latency, tokens, and operational complexity. Mem0’s simplicity is a real feature, not a missing one.</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>              MEM0
              ─────────────────────────────
  Your app ──► Memory.add(messages, user_id)
                  │
                  ├─► LLM (extract facts, ADD-only)
                  ├─► Embedder (vectorize)
                  └─► Vector store (Qdrant / pgvector)
  Query  ──────► Memory.search() → hybrid (semantic + BM25 + entity)


              HONCHO
              ────────────────────
  Storage (sync API)              Insights (async, deriver worker)
  ─────────────────               ────────────────────────────────
  Workspaces                      Deriver  → extract observations per message
  Peers (humans + agents)         Summary  → compress session history
  Sessions (many peers, m2m)      Dreamer  → periodic synthesis pass
  Messages (peer-labeled)         Dialectic → 5-level recall (min → max)
                                  PeerCard → compact identity summary

  Queue (Redis) ──► deriver process picks up tasks
</code></pre></div></div>

<hr />

<h2 id="side-by-side-only-the-rows-that-matter">Side-by-side: only the rows that matter</h2>

<table>
  <thead>
    <tr>
      <th>Dimension</th>
      <th>Mem0</th>
      <th>Honcho</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Mental model</td>
      <td>Facts notebook</td>
      <td>Peer psychologist</td>
    </tr>
    <tr>
      <td>Primary unit</td>
      <td>Memory item (a fact)</td>
      <td>Peer representation (a synthesized belief)</td>
    </tr>
    <tr>
      <td>Storage key</td>
      <td><code class="language-plaintext highlighter-rouge">user_id</code></td>
      <td><code class="language-plaintext highlighter-rouge">(observer_id, observed_id)</code> peer pair</td>
    </tr>
    <tr>
      <td>Synthesis</td>
      <td>None. Stores what the source said.</td>
      <td>Dreamer pass every 4h. Produces conclusions the source never contained.</td>
    </tr>
    <tr>
      <td>Multi-peer</td>
      <td>Sessions as containers, single-user facts</td>
      <td>First-class <code class="language-plaintext highlighter-rouge">(observer, observed)</code> peer pairs</td>
    </tr>
    <tr>
      <td>Retrieval</td>
      <td>Hybrid semantic + BM25 + entity</td>
      <td>Hybrid + reasoning-grounded chat endpoint</td>
    </tr>
    <tr>
      <td>Reasoning depth</td>
      <td>Single-pass extraction</td>
      <td>5-level dialectic (minimal → max) plus dreamer synthesis</td>
    </tr>
    <tr>
      <td>Dashboard</td>
      <td>Built-in (self-hosted + cloud)</td>
      <td>API only by default</td>
    </tr>
    <tr>
      <td>License</td>
      <td>Apache 2.0</td>
      <td>AGPL-3.0<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">1</a></sup></td>
    </tr>
    <tr>
      <td>Time-to-first-result</td>
      <td>~5 minutes</td>
      <td>~30 minutes (clone, configure, run deriver)</td>
    </tr>
    <tr>
      <td>Stars</td>
      <td>~61k, YC S24, managed cloud</td>
      <td>~6k, smaller community, research-flavored</td>
    </tr>
  </tbody>
</table>

<hr />

<h2 id="how-the-reasoning-pipelines-actually-differ">How the reasoning pipelines actually differ</h2>

<h3 id="mem0s-pipeline-april-2026-algorithm">Mem0’s pipeline (April 2026 algorithm)</h3>

<ol>
  <li>One LLM call extracts facts from the input messages. ADD-only, no UPDATE or DELETE. Memories accumulate; nothing is overwritten.</li>
  <li>Embeds the facts. Optionally extracts entities and links them across memories.</li>
  <li>At query time: semantic match, BM25 keyword match, and entity match run in parallel and get fused into a single ranked list.</li>
  <li>Returns the top facts.</li>
</ol>

<p>Fast. Deterministic. Cheap on tokens. Good for “remember the user’s preferences” use cases. Mem0 publishes 92.5 on LoCoMo, 94.4 on LongMemEval, and 64.1 on BEAM at 1M tokens for this pipeline.</p>

<h3 id="honchos-pipeline">Honcho’s pipeline</h3>

<ol>
  <li><strong>Deriver</strong> extracts structured observations from each message as it lands. Runs in a separate worker process, not the API.</li>
  <li><strong>Summary</strong> compresses session history on a schedule.</li>
  <li><strong>Dreamer</strong> runs periodically (the default interval is every 8 hours, mine is set to 4) and runs deduction and induction passes to synthesize patterns across messages. This is the part that turns observations into representations.</li>
  <li><strong>Dialectic</strong> runs at recall time with 5 reasoning depths, from <code class="language-plaintext highlighter-rouge">minimal</code> (cheap, fast) to <code class="language-plaintext highlighter-rouge">max</code> (expensive, deep). You pick the depth per query.</li>
  <li><strong>Peer cards</strong> auto-generate compact identity summaries you can dump into a prompt without waiting for the LLM.</li>
</ol>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  Message lands ──► Redis queue ──► deriver worker
                                          │
                                          ▼
                                   structured observation
                                          │
                                          ▼
                                   stored in (observer, observed)
                                   internal collection
                                          │
                                          ▼
                                   every 4-8h: dreamer runs
                                   deduction + induction passes
                                          │
                                          ▼
                                   representations + peer cards
                                          │
                                          ▼
  Recall query ──► dialectic at chosen depth (min → max)
                                          │
                                          ▼
                                   reasoning-grounded response
</code></pre></div></div>

<p>The full pipeline is heavier than Mem0’s single-pass approach in every dimension (latency, token cost, operational complexity). It is also the only one of the two that can answer a question the source messages did not contain.</p>

<hr />

<h2 id="how-i-ended-up-running-honcho">How I ended up running Honcho</h2>

<p>I self-host Honcho at <code class="language-plaintext highlighter-rouge">localhost:8000</code> (four containers: FastAPI on :8000, pgvector, Redis, deriver worker as a separate process). It has been observing my work sessions since the workspace was created on 2026-06-13. Every reasoning stage runs at <code class="language-plaintext highlighter-rouge">thinking_effort="max"</code> against MiniMax M2.5-highspeed.</p>

<p><strong>Why Honcho over Mem0 for my main setup:</strong> I work on multi-agent systems, and the <code class="language-plaintext highlighter-rouge">(observer, observed)</code> peer pair is exactly the primitive I need. The reasoning depth costs me latency and tokens, which I am willing to pay for the kind of synthesis Mem0’s single-pass architecture cannot reach. The full self-host walkthrough (docker-compose, deriver wiring, MiniMax routing, dreamer cycle tuning) is its own blog post, coming soon.</p>

<p>I have not run Mem0 in production on this stack, but I will. A Mem0 setup blog is also coming soon, with the same level of detail: stack choices, embedding model tradeoffs, retrieval tuning. The honest comparison is easier to write once both are running against the same workload.</p>

<p><strong>Side note</strong>: while running Honcho I built a small open source tool called memoir to unblock the parts of Honcho that need a human view (conclusions, peer cards, asymmetric perspectives, dreamer state). Memoir is launching soon. If you hit a wall with Honcho before then, that is what memoir is for.</p>

<hr />

<h2 id="which-fits-which-use-case">Which fits which use case</h2>

<p>Pick Mem0 if your agent’s value is in retrieved facts. Pick Honcho if your agent’s value is in inferences the user would not have made explicit. That is the whole decision.</p>

<p>PK</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1" role="doc-endnote">
      <p>AGPL-3.0 matters if you modify Honcho itself and serve it over a network. Self-hosting without forking, or integrating against the managed <code class="language-plaintext highlighter-rouge">api.honcho.dev</code>, does not trigger AGPL on your code. Mem0’s Apache 2.0 has no such consideration. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name>Praveen Kumar Sridhar</name></author><category term="memory" /><category term="agents" /><summary type="html"><![CDATA[Mem0 stores facts about a user. Honcho stores conclusions about a relationship. Picking a memory layer means picking which question you want answered.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://praveenks.com/assets/social-card.png" /><media:content medium="image" url="https://praveenks.com/assets/social-card.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>