<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Majid Fekri</title>
    <description>The latest articles on DEV Community by Majid Fekri (@mjfekri).</description>
    <link>https://dev.to/mjfekri</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4003014%2Fe82aa9a8-f82d-4c03-afcf-c498b9258076.png</url>
      <title>DEV Community: Majid Fekri</title>
      <link>https://dev.to/mjfekri</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mjfekri"/>
    <language>en</language>
    <item>
      <title>Your Agent's Memory Is a Markdown File. Let's Audit It.</title>
      <dc:creator>Majid Fekri</dc:creator>
      <pubDate>Thu, 30 Jul 2026 12:30:00 +0000</pubDate>
      <link>https://dev.to/mjfekri/your-agents-memory-is-a-markdown-file-lets-audit-it-4l2n</link>
      <guid>https://dev.to/mjfekri/your-agents-memory-is-a-markdown-file-lets-audit-it-4l2n</guid>
      <description>&lt;p&gt;Quick check: does your agent stack have a &lt;code&gt;memory.md&lt;/code&gt; in it somewhere? An &lt;code&gt;AGENTS.md&lt;/code&gt;? A notes file the agent appends to when something seems worth keeping?&lt;/p&gt;

&lt;p&gt;Thought so. Mine did too. It's the pattern everyone converges on, it takes twenty minutes to build, and it genuinely works — right up until the day it hands a customer a fact that stopped being true in March.&lt;/p&gt;

&lt;p&gt;This post does three things: shows you exactly &lt;em&gt;why&lt;/em&gt; the pattern rots (with a real-shaped sample file we'll dissect), gives you a small script to audit your own file tonight, and walks through the architecture change that actually fixes it. No vendor required for any of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pattern we all built
&lt;/h2&gt;

&lt;p&gt;Strip away the framework and every self-managed memory loop looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;MEMORY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory.md&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MEMORY&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;          &lt;span class="c1"&gt;# 1. dump everything in
&lt;/span&gt;    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SYSTEM&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 2. do the actual job
&lt;/span&gt;
    &lt;span class="n"&gt;note&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;                           &lt;span class="c1"&gt;# 3. agent grades its own homework
&lt;/span&gt;        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What from this interaction is worth remembering? &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Reply with one line, or NONE.&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;note&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NONE&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;MEMORY&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;       &lt;span class="c1"&gt;# 4. append forever
&lt;/span&gt;            &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;- &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;note&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Be fair to it first: this is human-readable, versionable, greppable, zero-infrastructure. For &lt;strong&gt;one agent, one job, small working set&lt;/strong&gt; — it's honestly hard to beat.&lt;/p&gt;

&lt;p&gt;Now look at what it &lt;em&gt;doesn't&lt;/em&gt; do. Step 4 is the entire lifecycle. Nothing in this loop ever updates, merges, expires, or questions a line once written. The file has exactly one behavior: it grows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dissecting a six-month-old memory file
&lt;/h2&gt;

&lt;p&gt;Here's a condensed, realistic slice of what that loop produces by month six. Read it the way retrieval reads it — every line equally true:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt; Customer Acme runs their workload in us-east1
&lt;span class="p"&gt;-&lt;/span&gt; Acme prefers Slack over email for escalations
&lt;span class="p"&gt;-&lt;/span&gt; Acme's staging env uses the legacy auth flow
&lt;span class="p"&gt;-&lt;/span&gt; Acme contact is Priya (prefers email)
&lt;span class="p"&gt;-&lt;/span&gt; The feature flag &lt;span class="sb"&gt;`beta_router`&lt;/span&gt; must stay ON for Acme
&lt;span class="p"&gt;-&lt;/span&gt; Acme migrated to europe-west2 for compliance
&lt;span class="p"&gt;-&lt;/span&gt; Acme staging is on the new auth flow as of the migration
&lt;span class="p"&gt;-&lt;/span&gt; Reminder: beta_router was removed from the codebase
&lt;span class="p"&gt;-&lt;/span&gt; Acme runs in us-east1 (confirmed)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nine lines. Let's count the damage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Two live contradictions.&lt;/strong&gt; &lt;code&gt;us-east1&lt;/code&gt; vs &lt;code&gt;europe-west2&lt;/code&gt; (lines 1, 6, 9 — and note the stale fact got &lt;em&gt;re-confirmed&lt;/em&gt; after the migration, because the agent trusted its own notes). Legacy vs new auth flow (lines 3, 7).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One zombie.&lt;/strong&gt; &lt;code&gt;beta_router&lt;/code&gt; must stay ON... for a flag that no longer exists (lines 5, 8).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One soft conflict.&lt;/strong&gt; Slack vs email preference (lines 2, 4) — maybe both true (channel vs person), maybe not. Nothing will ever decide.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero dates, zero sources, zero supersession.&lt;/strong&gt; Line 9 looks &lt;em&gt;more&lt;/em&gt; authoritative than line 6. It's newer and it says "confirmed." It's also wrong.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This file isn't remembering. It's &lt;strong&gt;accumulating&lt;/strong&gt; — and retrieval over an accumulation returns everything the agent ever believed, in every version, including the dead ones. Which is how an agent politely, fluently tells a customer their data lives in a region they left months ago.&lt;/p&gt;

&lt;h2&gt;
  
  
  Audit your own file (runnable, ~40 lines)
&lt;/h2&gt;

&lt;p&gt;Run this against your memory file. It flags undated entries, near-duplicates, and &lt;em&gt;candidate&lt;/em&gt; contradictions (negation pairs and entries sharing a subject):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;itertools&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;difflib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SequenceMatcher&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;

&lt;span class="n"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;- &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;read_text&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;splitlines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
         &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; memory entries&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 1. Undated entries (no ISO date, no month name)
&lt;/span&gt;&lt;span class="n"&gt;dated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\d{4}-\d{2}|\bJan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;undated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;dated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[FRESHNESS] &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;undated&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; entries carry no date. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
      &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;None of these can expire.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 2. Near-duplicates (same fact, drifted wording)
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;itertools&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;combinations&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nc"&gt;SequenceMatcher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;ratio&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[DUPLICATE?]&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;  &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;  &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 3. Contradiction candidates (shared subject, different claims)
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[A-Z][a-z]+|\b\w+_\w+\b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

&lt;span class="n"&gt;by_subject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;by_subject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setdefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[]).&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;subj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;by_subject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;subj&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[REVIEW &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;subj&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;] &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; entries share this subject &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
              &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;— read them side by side:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  - &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it on the sample above and it flags the &lt;code&gt;us-east1&lt;/code&gt;/&lt;code&gt;europe-west2&lt;/code&gt; cluster, the duplicate region claims, and reports 9/9 entries undated.&lt;/p&gt;

&lt;p&gt;But here's the part that matters more than the script: &lt;strong&gt;notice what it can't do.&lt;/strong&gt; It can surface that lines 1 and 6 share a subject. It cannot tell you which one is &lt;em&gt;true&lt;/em&gt; — that requires knowing that a migration supersedes a location, that "confirmed" from a self-referencing agent means nothing, that line 8 kills line 5. Detecting contradiction candidates is string matching. &lt;strong&gt;Resolving them is judgment.&lt;/strong&gt; Judgment is not a regex. Judgment is a &lt;em&gt;job&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Which is the whole point.&lt;/p&gt;

&lt;h2&gt;
  
  
  The job nobody in your stack has
&lt;/h2&gt;

&lt;p&gt;Go back to the loop at the top. Steps 3–4 quietly assign the working agent a second occupation: memory manager. Every "is this worth keeping?" decision is paid in tokens and attention out of the task budget — and the curator is grading its own homework, keeping whatever felt important mid-task. Multiply by a fleet of agents, each with its own file, and you have N diaries, zero reconciliation, and no component anywhere whose &lt;em&gt;job&lt;/em&gt; is to notice when they disagree.&lt;/p&gt;

&lt;p&gt;Write out what the job actually requires and it stops looking like a file API:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Verb&lt;/th&gt;
&lt;th&gt;Engineering requirement&lt;/th&gt;
&lt;th&gt;Your &lt;code&gt;memory.md&lt;/code&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Curate&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Decide keep vs. noise, with criteria, outside the task loop&lt;/td&gt;
&lt;td&gt;The busy agent, mid-task&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Reconcile&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Detect + resolve contradictions across &lt;em&gt;all&lt;/em&gt; agents' knowledge&lt;/td&gt;
&lt;td&gt;Nobody&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Consolidate&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Merge duplicates, supersede stale facts, keep the estate compact&lt;/td&gt;
&lt;td&gt;Nobody&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Brief&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Deliver per-task relevant context — not the whole file&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;read_text()&lt;/code&gt; (the whole file)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Provision&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Bootstrap a new agent with what the fleet already knows&lt;/td&gt;
&lt;td&gt;Copy-paste, if you remember&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Five verbs, mostly unstaffed. That's not a storage gap. It's a &lt;strong&gt;staffing&lt;/strong&gt; gap.&lt;/p&gt;

&lt;h2&gt;
  
  
  The architecture change
&lt;/h2&gt;

&lt;p&gt;The fix is division of labor: pull the management loop &lt;em&gt;out&lt;/em&gt; of the working agents and give it to a specialist — a &lt;strong&gt;Memory Agent&lt;/strong&gt; whose entire function is managing the memories of the other agents. The working agents' interface collapses to two calls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# working agent — memory is no longer its problem
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;memory_agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;brief&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agent_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# relevant slice only
&lt;/span&gt;    &lt;span class="n"&gt;result&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SYSTEM&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;memory_agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;agent_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;interaction&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# raw material, not decisions
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# memory agent — runs its own loop, on its own budget, fleet-wide
&lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;curate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inbox&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;          &lt;span class="c1"&gt;# keep vs. noise — with criteria, not vibes
&lt;/span&gt;    &lt;span class="nf"&gt;reconcile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;estate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="c1"&gt;# cross-agent contradictions surfaced &amp;amp; resolved
&lt;/span&gt;    &lt;span class="nf"&gt;consolidate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;estate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    &lt;span class="c1"&gt;# merge, supersede, expire
&lt;/span&gt;    &lt;span class="c1"&gt;# brief() / provision() served on demand
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note what changed. The working agent spends &lt;strong&gt;zero tokens&lt;/strong&gt; on memory decisions. Curation criteria live in one place instead of N prompts. Contradictions have an owner. And the memory estate becomes a first-class system you can scope per-agent, audit, and export — instead of a text file with commit history.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it honestly
&lt;/h2&gt;

&lt;p&gt;The honest carve-out first: &lt;strong&gt;one agent, small working set, no compliance surface → keep your markdown file.&lt;/strong&gt; Sincerely. This architecture earns its keep at &lt;em&gt;fleet&lt;/em&gt; scale — several agents, shared knowledge, contradictions that reach users.&lt;/p&gt;

&lt;p&gt;If that's you, two paths:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Build the loop yourself.&lt;/strong&gt; The pseudocode above is genuinely enough to start — the hard parts you'll hit (contradiction resolution policy, decay, briefing relevance) are exactly the parts that make this a discipline. Instructive either way.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run one that exists.&lt;/strong&gt; This is the problem we work on: &lt;strong&gt;Memanto&lt;/strong&gt; is an open-source (MIT, free) Memory Agent that runs alongside whatever agents and framework you already have — grab it at &lt;code&gt;github.com/moorcheh-ai/memanto&lt;/code&gt; and point it at your fleet. Its estate is stored in an open format (OKF) with a shipped &lt;code&gt;memanto migrate&lt;/code&gt; CLI, so trying it doesn't marry you to it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Either way, run the audit script first. Then ask the one question your stack should be able to answer and probably can't:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What does your fleet believe today?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the answer is a 3,000-line file — memory is a job, not a dump. Staff it.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devops</category>
      <category>architecture</category>
      <category>testing</category>
    </item>
    <item>
      <title>Your agent memory probably isn't portable. Here's the test that proves it.</title>
      <dc:creator>Majid Fekri</dc:creator>
      <pubDate>Mon, 27 Jul 2026 17:05:10 +0000</pubDate>
      <link>https://dev.to/mjfekri/your-agent-memory-probably-isnt-portable-heres-the-test-that-proves-it-7lj</link>
      <guid>https://dev.to/mjfekri/your-agent-memory-probably-isnt-portable-heres-the-test-that-proves-it-7lj</guid>
      <description>&lt;p&gt;There's a question every developer building with agent memory eventually asks, usually around month three, usually at an inconvenient hour:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where do my memories actually live, and what happens if I need them somewhere else?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It never arrives as a design review. It arrives as an incident. A framework ships a breaking change. Your embedding model gets deprecated. A second agent needs the ninety days of context the first one accumulated. Someone asks for a list of everything the system currently believes about a named user.&lt;/p&gt;

&lt;p&gt;You go looking. You find a table of vectors keyed to a model version you already moved off, a JSON dump of raw turns, and extraction rules that lived inside a prompt.&lt;/p&gt;

&lt;p&gt;This post is the test I'd run before you get there, and the reasoning behind it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Table of contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The debate is about reading&lt;/li&gt;
&lt;li&gt;Memory is a write problem: five decisions no index makes&lt;/li&gt;
&lt;li&gt;Three tiers of export&lt;/li&gt;
&lt;li&gt;The embedding trap&lt;/li&gt;
&lt;li&gt;The fleet makes it worse&lt;/li&gt;
&lt;li&gt;What OKF gets right&lt;/li&gt;
&lt;li&gt;Where OKF stops&lt;/li&gt;
&lt;li&gt;The round-trip test&lt;/li&gt;
&lt;li&gt;The full checklist&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The debate is about reading
&lt;/h2&gt;

&lt;p&gt;Since Google Cloud published the Open Knowledge Format in June, everything has been OKF vs RAG. Curated markdown for authoritative facts, retrieval for the sprawling archive.&lt;/p&gt;

&lt;p&gt;There's real work in there. Satvik Singh benchmarked curated docs against a knowledge graph, BM25 retrieval, and plain agentic grep across twelve on-call questions on two production services, and found that question type picked the winner rather than tooling ideology — grep took every code-detail question, curated docs took every architecture question, and every retrieval win was the retriever surfacing chunks of the curated docs.&lt;/p&gt;

&lt;p&gt;But every entry in this debate starts from a corpus that already exists and asks how to find the right part of it.&lt;/p&gt;

&lt;p&gt;That's a reading problem. Memory is a &lt;strong&gt;writing&lt;/strong&gt; problem that later becomes a reading problem, and nearly all the difficulty is upstream of retrieval.&lt;/p&gt;




&lt;h2&gt;
  
  
  Memory is a write problem
&lt;/h2&gt;

&lt;p&gt;A document is authored once and read many times. A memory is never authored at all — it accretes sideways, out of interactions that were about something else.&lt;/p&gt;

&lt;p&gt;That produces five decisions no index makes for you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Salience.&lt;/strong&gt; Of 400 turns this week, which mattered? Most implementations answer with a heuristic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# the shape almost everyone starts with
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;turn_count&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;summarize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;recent_turns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That heuristic is your quality ceiling. Keep too much and you've rebuilt the transcript with extra steps. Keep too little and the agent is confidently amnesiac about the one thing that mattered.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Supersession.&lt;/strong&gt; In March the user lives in Toronto. In June they mention Berlin. That's not two facts — it's one fact with a history:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# what you usually get
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fact&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user lives in Toronto&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2026-03-04&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fact&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user lives in Berlin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2026-06-19&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;# both retrievable, both scored, nothing encoding that one replaced the other
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now do it for a fact asserted by three agents across three sessions, two of which were wrong.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Consolidation.&lt;/strong&gt; &lt;code&gt;"frustrated by the export flow on Tuesday"&lt;/code&gt; is an event. &lt;code&gt;"cares about export fidelity"&lt;/code&gt; is a memory. The promotion between them is a judgment call, made continuously, on evidence that arrives in pieces.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Provenance and time.&lt;/strong&gt; Who asserted it, when, on what basis, whether it expires. Without those fields you can't reconcile, can't audit, can't honor a deletion request, and can't distinguish staleness from disagreement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Forgetting.&lt;/strong&gt; Least discussed, most legally consequential. A memory system that can't forget cleanly is a compliance problem wearing a feature's clothes.&lt;/p&gt;

&lt;p&gt;Every one is a &lt;em&gt;decision&lt;/em&gt;, not a lookup and not a similarity score. That's why memory is an agentic problem rather than a retrieval one — and why the answer keeps looking like infrastructure when it's actually behavior.&lt;/p&gt;




&lt;h2&gt;
  
  
  Three tiers of export
&lt;/h2&gt;

&lt;p&gt;Ask any memory product for an export and you'll get something. The useful question is which of three things.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;th&gt;What you get&lt;/th&gt;
&lt;th&gt;What it costs you&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bytes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Tarball of raw turns, vendor-shaped&lt;/td&gt;
&lt;td&gt;Re-run your whole extraction pipeline. That's a rebuild, not a migration.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Schema&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Structured records with mappable fields&lt;/td&gt;
&lt;td&gt;You can write an importer, but you can't recover &lt;em&gt;why&lt;/em&gt; a record exists&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Semantics&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Memories as memories: provenance, time bounds, supersession chain&lt;/td&gt;
&lt;td&gt;Nothing — this is the tier where "portable" means what it sounds like&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Almost everything on the market ships tier one and markets tier three.&lt;/p&gt;




&lt;h2&gt;
  
  
  The embedding trap
&lt;/h2&gt;

&lt;p&gt;Worth calling out on its own, because it's subtle and expensive.&lt;/p&gt;

&lt;p&gt;If the durable form of your memory is an embedding, your memory is bound to an embedding model.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# this is not a format conversion&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;./migrate.sh &lt;span class="nt"&gt;--re-embed&lt;/span&gt; &lt;span class="nt"&gt;--model&lt;/span&gt; text-embedding-v3
✓ 148,291 memories re-embedded
✓ 0 errors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Zero errors, and retrieval quality has silently changed. Re-embedding is a &lt;strong&gt;lossy re-derivation&lt;/strong&gt; whose failures are invisible — nothing throws, recall just degrades in ways that show up as vibes three weeks later.&lt;/p&gt;

&lt;p&gt;Vectors are a cache. Treating a cache as your system of record is exactly how you end up unable to leave.&lt;/p&gt;




&lt;h2&gt;
  
  
  The fleet makes it worse
&lt;/h2&gt;

&lt;p&gt;The single-agent version is annoying. The fleet version is the one that costs money.&lt;/p&gt;

&lt;p&gt;Real deployments end up with several agents against the same memory estate — one in the IDE, one on support tickets, one doing analysis, one running scheduled work nobody has reviewed in a month. Each learns things, into its own store, in its own shape, under its own rules.&lt;/p&gt;

&lt;p&gt;So you get divergence with no reconciliation mechanism, because reconciliation was never a cross-agent operation to begin with. The user corrects the support agent; the coding agent believes the old thing indefinitely.&lt;/p&gt;

&lt;p&gt;Singh's framing lands hard here: &lt;strong&gt;derived layers are caches without a TTL.&lt;/strong&gt; His knowledge graph, built five days earlier, scored 0/3 on a two-week-old feature sitting in the working tree it was derived from. The curated docs had zero coverage of the same feature. Neither artifact signals that it's behind.&lt;/p&gt;

&lt;p&gt;Multiply that by every agent you run, each derived independently, each lagging on its own schedule.&lt;/p&gt;




&lt;h2&gt;
  
  
  What OKF gets right
&lt;/h2&gt;

&lt;p&gt;Worth being precise, because the format is less than the hype and considerably more useful than the skepticism.&lt;/p&gt;

&lt;p&gt;OKF v0.1 was published by Google Cloud's Data Cloud team on June 12, 2026. A bundle is a directory of markdown files with YAML frontmatter, one concept per file, cross-linked. Exactly one field is required (&lt;code&gt;type&lt;/code&gt;). No runtime, no SDK, no registry, no account. It renders on GitHub, ships as a tarball, mounts on any filesystem.&lt;/p&gt;

&lt;p&gt;A memory expressed in that shape looks roughly like this — &lt;code&gt;type&lt;/code&gt; is the spec requirement, the rest are conventional or extension fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;preference&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Export&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;fidelity"&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;consistently&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;prioritizes&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;lossless&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;export&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;over&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;speed."&lt;/span&gt;
&lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2026-07-14T09:22:00Z&lt;/span&gt;
&lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;product&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;ux&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;# extension fields carrying the memory semantics&lt;/span&gt;
&lt;span class="na"&gt;asserted_by&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;support-agent&lt;/span&gt;
&lt;span class="na"&gt;evidence&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;session&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;8813#turn42&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;session&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;9002#turn17&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;supersedes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;span class="na"&gt;confidence&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.86&lt;/span&gt;
&lt;span class="na"&gt;expires&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# Export fidelity&lt;/span&gt;

Raised in three separate sessions between May and July. In each case the user
declined a faster path that would have dropped metadata.

&lt;span class="gu"&gt;## Related&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Export flow friction&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;export-flow-friction.md&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Account: workspace tier&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;workspace-tier.md&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the ownership problem, the properties are exactly right:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A human can read it at 3am.&lt;/strong&gt; During an incident that's the difference between checking what the system believes and guessing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Git already knows what to do with it.&lt;/strong&gt; Diffs, blame, PRs, review. Curation becomes a reviewable change rather than an opaque mutation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It outlives your stack.&lt;/strong&gt; No SDK, no version pin, no vendor whose roadmap becomes your roadmap.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Producer and consumer are decoupled by design.&lt;/strong&gt; Which is the definition of portable, stated as a spec instead of promised in a docs page.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Where OKF stops
&lt;/h2&gt;

&lt;p&gt;Here's the honest limitation, and skipping it would be dishonest given what the measurements show.&lt;/p&gt;

&lt;p&gt;Singh found three confidently wrong facts in the curated docs he benchmarked, each contradicted by code that had been settled for &lt;strong&gt;over two years before the docs were written&lt;/strong&gt;. Not stale — born wrong, in an AI generation pass, into the layer agents are told to trust. Then retrieval amplified one of them: top results repeated the wrong answer 26 times against 2 mentions of the correct one.&lt;/p&gt;

&lt;p&gt;A bundle is a snapshot. Memory is a process. Adopt OKF and stop there and you've built a beautifully portable cache with no TTL.&lt;/p&gt;

&lt;p&gt;He also names why nobody solves this with discipline: nobody hand-writes and hand-maintains bundles for forty repos. Substitute "forty agents." Manual curation doesn't survive contact with scale — which means curation has to be done by something that doesn't get tired, held to a verification standard, because automated curation's failure mode is precisely the one he measured.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The false dichotomy:&lt;/strong&gt; it isn't curated knowledge &lt;em&gt;versus&lt;/em&gt; active retrieval. Active accumulating memory is how you take in the world — fast, lossy, where new things arrive. Curated committed knowledge is what you've decided is true — slow, durable, auditable. Every functioning system has both.&lt;/p&gt;

&lt;p&gt;The real question: &lt;em&gt;what promotes a fact from one to the other, how often, on what evidence — and what demotes it when it stops being true?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That's a job. Formats don't curate. Retrievers don't decide.&lt;/p&gt;




&lt;h2&gt;
  
  
  The round-trip test
&lt;/h2&gt;

&lt;p&gt;This is the one to run this week. It takes an afternoon and it's the single test that separates a portability claim from a portability guarantee.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. export from your current system&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;your-memory-tool &lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nt"&gt;--out&lt;/span&gt; ./snapshot-a

&lt;span class="c"&gt;# 2. import into a clean instance — no prior state&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;your-memory-tool init &lt;span class="nt"&gt;--fresh&lt;/span&gt; ./clean
&lt;span class="nv"&gt;$ &lt;/span&gt;your-memory-tool import &lt;span class="nt"&gt;--in&lt;/span&gt; ./snapshot-a &lt;span class="nt"&gt;--target&lt;/span&gt; ./clean

&lt;span class="c"&gt;# 3. export again from the clean instance&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;your-memory-tool &lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nt"&gt;--from&lt;/span&gt; ./clean &lt;span class="nt"&gt;--out&lt;/span&gt; ./snapshot-b

&lt;span class="c"&gt;# 4. diff&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;diff &lt;span class="nt"&gt;-r&lt;/span&gt; ./snapshot-a ./snapshot-b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What you're looking for isn't byte equality — timestamps and ids will move. You're looking for &lt;strong&gt;semantic loss&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Did supersession chains survive, or did the importer flatten them into independent facts?&lt;/li&gt;
&lt;li&gt;Did provenance survive, or is &lt;code&gt;asserted_by&lt;/code&gt; now null on everything?&lt;/li&gt;
&lt;li&gt;Did confidence and expiry survive, or did they get defaulted?&lt;/li&gt;
&lt;li&gt;Did cross-references survive, or are they dangling?&lt;/li&gt;
&lt;li&gt;Count the units. If B has fewer than A, something was dropped silently.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most systems fail at least three of those. Almost nobody checks until the migration, at which point it's a rewrite with a deadline attached.&lt;/p&gt;




&lt;h2&gt;
  
  
  The full checklist
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Canonical form a human can read.&lt;/strong&gt; If answering "what does the system currently believe about X" requires a query and eyeballing cosine scores — no.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provenance and time on every unit.&lt;/strong&gt; Who, when, on what basis, when it expires.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supersession recorded, not overwritten.&lt;/strong&gt; You should see that Toronto was replaced by Berlin, and when.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Durable form is model-independent.&lt;/strong&gt; If a new embedding model means a lossy re-derivation, embeddings are your system of record. Fix that first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Export round-trips.&lt;/strong&gt; See above.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verification against source.&lt;/strong&gt; Every curated fact checkable against the thing it describes, on a schedule.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It can abstain.&lt;/strong&gt; Fareed Khan's pipeline work makes this point well: when evidence is missing, the correct output isn't a fluent guess. A memory system that can't say "I don't have that" will invent it — and inventions inherit the authority of the curated layer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deletion actually deletes.&lt;/strong&gt; Including from every derived index, cache, summary, and agent that copied it.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;You shouldn't have to choose between memory that's alive and memory that's yours. The accumulating side and the committed side are two tempos of the same process. The thing worth building isn't another place to put memories — it's the thing that decides what moves between them.&lt;/p&gt;




&lt;h3&gt;
  
  
  Disclosure
&lt;/h3&gt;

&lt;p&gt;This is what I work on, so weight it accordingly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/moorcheh-ai/memanto" rel="noopener noreferrer"&gt;&lt;strong&gt;Memanto&lt;/strong&gt;&lt;/a&gt; is an open-source companion memory agent that helps other agents manage their memories. As of &lt;strong&gt;v0.2.8&lt;/strong&gt; it ships native Open Knowledge Format integration — memories consolidate into OKF bundles you can read, diff and review in git — and migration from other memory systems built in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;memanto
&lt;span class="nv"&gt;$ &lt;/span&gt;memanto migrate &lt;span class="nt"&gt;--from&lt;/span&gt; &amp;lt;&lt;span class="nb"&gt;source&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;--out&lt;/span&gt; ./memory-bundle
&lt;span class="nv"&gt;$ &lt;/span&gt;memanto &lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt; okf &lt;span class="nt"&gt;--out&lt;/span&gt; ./okf-bundle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As far as I know it's the only Memory Agent shipping both. MIT licensed, which is the only license under which a claim about portability is worth making.&lt;/p&gt;

&lt;p&gt;Recall: 89.8% on &lt;a href="https://arxiv.org/abs/2604.22085" rel="noopener noreferrer"&gt;LongMemEval&lt;/a&gt;, 87.1% on &lt;a href="https://arxiv.org/abs/2601.11557" rel="noopener noreferrer"&gt;LoCoMo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Run the round-trip test against it before you believe me. Run it against whatever you're using now either way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your agents focus. Memanto remembers.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>architecture</category>
      <category>agents</category>
    </item>
    <item>
      <title>Your AI Agent's Memory Should Live in Git: A Practical Intro to the Open Knowledge Format</title>
      <dc:creator>Majid Fekri</dc:creator>
      <pubDate>Mon, 20 Jul 2026 14:20:14 +0000</pubDate>
      <link>https://dev.to/mjfekri/your-ai-agents-memory-should-live-in-git-a-practical-intro-to-the-open-knowledge-format-14eh</link>
      <guid>https://dev.to/mjfekri/your-ai-agents-memory-should-live-in-git-a-practical-intro-to-the-open-knowledge-format-14eh</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fldfywhowg53ul2v7ckqy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fldfywhowg53ul2v7ckqy.png" alt="An infographic representation of Google's Open Knowledge Format" width="800" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's a test you can run on your agent stack today: try to read one of your agent's memories with &lt;code&gt;cat&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you can't — if the answer involves a vendor dashboard, an API call, or exporting JSON from a vector database — your agent's accumulated knowledge is in a format that only one tool on Earth can fully interpret. That's fine right up until you switch tools, need an audit trail, want a backup you can actually inspect, or try to share knowledge between two agents built on different frameworks.&lt;/p&gt;

&lt;p&gt;This post is about a fix that's been quietly gaining traction: the Open Knowledge Format (OKF), an open spec Google Cloud published in June for representing agent knowledge as plain markdown files with YAML frontmatter. I'll skip the industry commentary and focus on what it looks like, why plain files beat proprietary stores for a surprising number of jobs, and five concrete workflows you can set up this week.&lt;/p&gt;

&lt;h2&gt;
  
  
  The anatomy of an OKF memory
&lt;/h2&gt;

&lt;p&gt;An OKF bundle is just a directory of markdown files. Each file is one unit of knowledge, with metadata in YAML frontmatter and the content in the body. A memory exported from a real system looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;preference&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;prefers&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;TypeScript&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;examples"&lt;/span&gt;
&lt;span class="na"&gt;created&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2026-05-14T09:32:00Z&lt;/span&gt;
&lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;coding-style&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;typescript&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;x_memanto&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;provenance&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;session-8f3a&lt;/span&gt;
  &lt;span class="na"&gt;valid_from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2026-05-14&lt;/span&gt;
  &lt;span class="na"&gt;recall_count&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;23&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

The user has consistently asked for TypeScript over Python
in code examples. Confirmed explicitly on 2026-05-14.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three things worth noticing:&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;spec is minimal by design&lt;/strong&gt;. It defines the interoperability surface — how a file declares what it is — without dictating your content model. There's essentially one required field (&lt;code&gt;type&lt;/code&gt;); everything else is convention. This restraint is why it has a chance of sticking where heavier standards haven't.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;&lt;code&gt;x_&lt;/code&gt; namespace pattern&lt;/strong&gt; handles tool-specific data. Anything your memory system tracks beyond the base spec (provenance, temporal validity, retrieval stats) goes under a namespaced block like &lt;code&gt;x_memanto&lt;/code&gt; above. Other tools ignore what they don't understand but preserve it, so round trips through foreign tools don't destroy data. If you've worked with HTTP &lt;code&gt;X-&lt;/code&gt; headers or Kubernetes annotations, this is the same idea.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;whole thing is text&lt;/strong&gt;. Which means the entire Unix toolbox — and git — works on your agent's brain. That's where it gets fun.&lt;/p&gt;

&lt;h2&gt;
  
  
  Workflow 1: Version-controlled memory
&lt;/h2&gt;

&lt;p&gt;The most immediately useful pattern: sync your agent's memory into a git repo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# with a tool that supports OKF sync (Memanto shown; adapt to yours)&lt;/span&gt;
memanto memory &lt;span class="nb"&gt;sync&lt;/span&gt; &lt;span class="nt"&gt;--okf&lt;/span&gt; ./agent-memory
&lt;span class="nb"&gt;cd &lt;/span&gt;agent-memory &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git init &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git add &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"baseline"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From here, standard git answers questions that are otherwise painful or impossible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# What did my agent learn this week?&lt;/span&gt;
git log &lt;span class="nt"&gt;--since&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"1 week ago"&lt;/span&gt; &lt;span class="nt"&gt;--stat&lt;/span&gt;

&lt;span class="c"&gt;# What exactly changed in its understanding of the billing module?&lt;/span&gt;
git diff HEAD~5 &lt;span class="nt"&gt;--&lt;/span&gt; knowledge/billing/

&lt;span class="c"&gt;# It learned something wrong on Tuesday. Undo it.&lt;/span&gt;
git revert &amp;lt;commit&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That last one deserves a pause. In most memory systems, correcting a bad memory means hunting it down through an API and hoping nothing else derived from it. With file-based memory under version control, a wrong learning event is a commit, and commits are revertible. Memory debugging becomes source control, a skill your whole team already has.&lt;/p&gt;

&lt;h2&gt;
  
  
  Workflow 2: Pull-request review for what your agent learns
&lt;/h2&gt;

&lt;p&gt;Once memory is files in a repo, you can gate changes the same way you gate code. Run sync on a branch, open a PR, and a human reviews the diff of what the agent picked up before it's merged into canonical memory.&lt;/p&gt;

&lt;p&gt;This sounds heavyweight until you need it. If your agent operates in a regulated domain — finance, health, anything with compliance officers — "show me exactly what the system learned and who approved it" stops being an impossible question. The answer is a PR history. You can even wire up CODEOWNERS so changes to certain memory types (say, anything tagged &lt;code&gt;policy&lt;/code&gt;) require review from a specific team.&lt;/p&gt;

&lt;h2&gt;
  
  
  Workflow 3: CI checks on memory quality
&lt;/h2&gt;

&lt;p&gt;Files in a repo means CI runs on them. A few checks that pay for themselves quickly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# .github/workflows/memory-lint.yml (sketch)&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Validate frontmatter&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python scripts/validate_okf.py ./agent-memory&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Useful validations: every file parses as YAML+markdown, every file declares a &lt;code&gt;type&lt;/code&gt;, no two files make contradictory claims with overlapping validity windows, timestamps are timezone-aware, and no memory references a session ID that doesn't exist in your logs. A 50-line validation script catches entire classes of memory corruption before they reach production — the kind of silent drift you'd otherwise discover months later through weird agent behavior.&lt;/p&gt;

&lt;p&gt;(Speaking from experience: temporal metadata is where the bugs hide. Date-only timestamps that resolve to midnight instead of covering the full day, naive-vs-aware timezone mismatches, duplicates from delete-and-recreate flows. Lint for these specifically.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Workflow 4: One knowledge base, many agents
&lt;/h2&gt;

&lt;p&gt;Multi-agent setups usually grow parallel memory silos — the support agent knows things the sales agent doesn't, and keeping them consistent means custom glue. With an open format, the shared knowledge is just a bundle both agents import:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# hand-curated or exported from any OKF-speaking tool&lt;/span&gt;
memanto migrate support-agent &lt;span class="nt"&gt;--okf&lt;/span&gt; ./shared-knowledge
memanto migrate sales-agent   &lt;span class="nt"&gt;--okf&lt;/span&gt; ./shared-knowledge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because the bundle is markdown, non-engineers can maintain it. A product manager editing a markdown file in the GitHub web UI is now updating agent knowledge — no admin panel, no ticket to the AI team. Progressive-disclosure conventions (an &lt;code&gt;index.md&lt;/code&gt; that points into detail files) keep large bundles navigable for both humans and models.&lt;/p&gt;

&lt;h2&gt;
  
  
  Workflow 5: Real backups and real exits
&lt;/h2&gt;

&lt;p&gt;The dull one, and the one you'll be gladdest to have. An OKF export is a backup you can inspect without a running service — five years from now, those markdown files will still open, whatever happened to the tool that wrote them. And if you change memory systems, an open bundle is your migration path: export from tool A, import into tool B, without writing a bespoke ETL script against two proprietary APIs.&lt;/p&gt;

&lt;p&gt;When you evaluate memory tooling, test the round trip, not the export checkbox: export, re-import, and diff. If data is missing after the round trip — temporal fields dropped, provenance gone — the export is lossy, and lossy export isn't portability, it's a screenshot. The &lt;code&gt;x_&lt;/code&gt; namespace exists precisely so implementations have no excuse for this. (This was the hard requirement we set when adding OKF support to Memanto, and I'd hold any tool, ours included, to it.)&lt;/p&gt;

&lt;h2&gt;
  
  
  When plain files are the wrong answer
&lt;/h2&gt;

&lt;p&gt;Educational honesty requires the counter-case. File-based memory is not a retrieval engine: at scale you'll still want an index or embedding layer on top for semantic search — the bundle is the source of truth, not the query path. High-write-frequency working memory (per-turn scratch state) doesn't belong in git; commit-per-token is nobody's idea of fun. And OKF v0.1 is young — it deliberately doesn't standardize your memory taxonomy, so two tools can both "speak OKF" while modeling memories quite differently. The format guarantees you can &lt;em&gt;read&lt;/em&gt; everything; semantic interoperability is still maturing.&lt;/p&gt;

&lt;p&gt;A reasonable architecture treats OKF as the durable, auditable at-rest layer, with whatever retrieval and working-memory machinery you like above it. The format's job is to make sure the machinery is replaceable.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;The agent ecosystem is repeating a pattern the software industry has run many times: capabilities first, interoperability later, and the teams who adopted open formats early skipped a painful migration era. You don't need to bet on any particular tool to benefit. Start with one habit: get your agent's memory into files you can &lt;code&gt;cat&lt;/code&gt;, &lt;code&gt;diff&lt;/code&gt;, and &lt;code&gt;git log&lt;/code&gt;. Everything else in this post follows from that.&lt;/p&gt;

&lt;p&gt;If you try any of these workflows — especially the PR-review or CI-lint patterns — I'd genuinely like to hear how they hold up in your stack. Drop a comment.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The examples above use Memanto (open source, MIT — &lt;code&gt;pip install memanto&lt;/code&gt;), which supports OKF export, sync, and import natively, but every workflow here works with any tool that reads and writes OKF bundles — or with a bundle you build by hand in a text editor. That's rather the point.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>opensource</category>
      <category>discuss</category>
    </item>
    <item>
      <title>The Open-Weight Cliff</title>
      <dc:creator>Majid Fekri</dc:creator>
      <pubDate>Wed, 08 Jul 2026 17:38:03 +0000</pubDate>
      <link>https://dev.to/mjfekri/the-open-weight-cliff-460</link>
      <guid>https://dev.to/mjfekri/the-open-weight-cliff-460</guid>
      <description>&lt;p&gt;When the model becomes free, the only thing left that's yours is the record of how you used it.&lt;/p&gt;

&lt;p&gt;For two years the industry argued about which frontier API was smartest. That argument is quietly ending — not because one lab won, but because the floor came up to meet the ceiling.&lt;/p&gt;

&lt;p&gt;Look at where tokens actually flow. On OpenRouter, the largest neutral model router, open-weight models from Chinese labs crossed from a rounding error to the majority of all tokens processed between late 2024 and mid-2026 — around 61% by May 2026, with four of the five most-used models open-weight and Meta's Llama, the open leader two years ago, fallen off the top rankings entirely. Alibaba's Qwen passed one billion cumulative downloads on Hugging Face in January 2026. And on Artificial Analysis's intelligence index, the strongest open-weight model now sits a handful of points below the best closed systems — the "open tax" at the top of the market has largely vanished, at roughly a tenth to a thirtieth of the per-token price.&lt;/p&gt;

&lt;p&gt;Microsoft's Satya Nadella has a phrase for the shift: the economy now divides into "human capital and token capital." Tokens — raw intelligence — are getting cheap and abundant. When an input gets cheap and abundant, it stops being a moat. As one widely shared framing put it this year: as models commoditize, value moves to serving them, and to the proprietary data around them.&lt;/p&gt;

&lt;p&gt;Here's the part most builders haven't internalized. If the model is no longer the differentiator, then your differentiator has to be something the model doesn't come with. And the one thing no downloadable checkpoint contains — the one asset that is unambiguously, unforgeably yours — is the accumulated record of your own agents at work. Your codebase conventions. Your domain's edge cases. The specific way your team frames problems, the fixes you accept, the ones you reject, and every mistake your agent made on the way to getting it right.&lt;/p&gt;

&lt;p&gt;That record is your fingerprint. In a world of commodity intelligence, it's arguably your only durable IP.&lt;/p&gt;

&lt;p&gt;Which reframes the build decision. Swapping models is now nearly free — the leading open-weight engines all expose OpenAI-compatible endpoints, so migrating is mostly changing a base URL and a model string. If the model is that portable, you should be treating it as a swappable part and pouring your defensibility into the layer that can't be swapped: the memory of everything your agents have learned in your service, and the interface and infrastructure that let you keep it.&lt;/p&gt;

&lt;p&gt;Use the cheap, excellent, commoditizing models. All of them. But don't confuse renting intelligence with owning an advantage. The intelligence is falling toward free. The fingerprint is yours — right up until you let it accumulate somewhere you don't control.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>opensource</category>
      <category>news</category>
    </item>
  </channel>
</rss>
