<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Keep Blog</title>
    <link>https://keepnotes.ai/blog/</link>
    <description>Reflective Memory for AI</description>
    <language>en-us</language>
    <atom:link href="https://keepnotes.ai/blog/feed.xml" rel="self" type="application/rss+xml"/>
    <lastBuildDate>Sun, 12 Apr 2026 18:11:51 GMT</lastBuildDate>
    <item>
      <title>LLM-Wiki</title>
      <link>https://keepnotes.ai/blog/2026-04-12-llmwiki/</link>
      <guid isPermaLink="true">https://keepnotes.ai/blog/2026-04-12-llmwiki/</guid>
      <pubDate>Sun, 12 Apr 2026 12:00:00 GMT</pubDate>
      <description><![CDATA[<img src="https://keepnotes.ai/blog/2026-04-12-llmwiki/graph.png" alt="LLM-Wiki" style="max-width:100%;border-radius:8px">
<p><strong>What does memory look like?</strong>  And, what happens when it changes?
</p>
<p>Let's find out using Obsidian as the view-pane.
</p>
<p><div class="youtube-embed" id="yt-NQBiy82fGwM" style="position:relative;cursor:pointer;max-width:100%;border-radius:8px;overflow:hidden" onclick="this.innerHTML='<iframe width=\'100%\' height=\'100%\' src=\'https://www.youtube.com/embed/NQBiy82fGwM?autoplay=1\' frameborder=\'0\' allow=\'autoplay; encrypted-media\' allowfullscreen style=\'position:absolute;top:0;left:0;width:100%;height:100%\'></iframe>';this.style.aspectRatio='16/9'"><img alt="Watch the video" src="obsidian.png" style="width:100%;display:block"><div style="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:72px;height:72px;background:rgba(0,0,0,0.7);border-radius:50%;display:flex;align-items:center;justify-content:center"><svg width="32" height="32" viewBox="0 0 24 24" fill="white"><path d="M8 5v14l11-7z"/></svg></div></div>
</p>
<p>This is what Andrej Karpathy described in his viral <a href="https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f">LLM Wiki gist</a> -- a persistent and incrementally-growing collection of documents, searchable, indexed as it grows -- with two interesting features:
</p>
<ul>
<li>you interact with a knowledge base by <em>talking to your agent</em>,</li>
<li>things that you talk <em>about</em> are automatically collected, summarized, and linked.</li>
</ul>
<p>Things that you talk about are <strong>remembered</strong>.  That's <code>keep</code>!
</p>
<p>The Obsidian graph view, and the chat pane, are just a convenient UI over the agent's memory.
</p>
<hr>
<h3 id="how-to">How To</h3>
<p>You'll need <a href="https://hermes-agent.nousresearch.com/">Hermes Agent</a> and <a href="https://obsidian.md/">Obsidian</a>.
</p>
<p>Install and configure the <a href="https://docs.keepnotes.ai/guides/hermes/">Keep plugin</a> for Hermes:
</p>
<pre><code>curl -sSL https://keepnotes.ai/scripts/install-hermes.sh | bash</code></pre>
<p>When keep is first installed, I recommend saying to your agent:
</p>
<blockquote><p>
Follow the keep instructions in your system prompt.
</p></blockquote>
<p>Enable the <a href="https://hermes-agent.nousresearch.com/docs/user-guide/features/api-server">API Server</a> in Hermes, so that the chat panel can connect to the agent.  Do this by editing <code>~/.hermes/.env</code>:
</p>
<pre><code>API_SERVER_ENABLED=true
API_SERVER_HOST=127.0.0.1
API_SERVER_PORT=8642
API_SERVER_KEY=change-me</code></pre>
<p>Then restart your Hermes gateway.
</p>
<p>When <code>keep</code> is running in Hermes, the default store is at <code>~/.hermes/keep</code>.  We will want to use that same store from the command-line too.  Make a new directory to hold the Obsidian vault, and configure <code>keep</code> to sync its memory into this directory.  The "PT10S" is a 10-second debounce time: longer is laggier.
</p>
<pre><code class="language-bash">export KEEP_STORE_PATH=~/.hermes/keep
mkdir -p ~/play/keep-vault
keep data export --sync --include-versions --interval PT10S ~/play/keep-vault</code></pre>
<p>In Obsidian, install the <a href="https://www.obsidianclaw.ai/">ObsidianClaw plugin</a> (aka Clawdian).
</p>
<p>Find the plugin settings, and configure its connection to Hermes:
</p>
<p><img alt="Clawdian" src="clawdian.png">
</p>
<p>Now you should be able to start chatting, and see your chats (and anything mentioned in them) show up in Obsidian, linked as a graph.
</p>
<p><a href="mailto:hello@keepnotes.ai">Let me know what you do with it</a>!
</p>]]></description>
      <enclosure url="https://keepnotes.ai/blog/2026-04-12-llmwiki/graph.png" type="image/png"/>
    </item>
    <item>
      <title>Flows</title>
      <link>https://keepnotes.ai/blog/2026-03-15-flows/</link>
      <guid isPermaLink="true">https://keepnotes.ai/blog/2026-03-15-flows/</guid>
      <pubDate>Sun, 15 Mar 2026 12:00:00 GMT</pubDate>
      <description><![CDATA[<img src="https://keepnotes.ai/blog/2026-03-15-flows/rothay.jpg" alt="Flows" style="max-width:100%;border-radius:8px">
<p>Code Mode is like <strong>vibe-coding a query plan</strong>.
</p>
<p>What is "code mode", you may ask?  It's a powerful observation by <a href="https://www.anthropic.com/engineering/code-execution-with-mcp">Anthropic</a> and <a href="https://blog.cloudflare.com/code-mode/">Cloudflare</a> recently, that agents just <em>love</em> to write code, and this can massively reduce the context overhead of tool-calls for <a href="https://modelcontextprotocol.io/docs/getting-started/intro">MCP</a> interfaces:
</p>
<blockquote><p>
We found agents are able to handle many more tools, and more complex tools, when those tools are presented as a TypeScript API rather than directly...
</p><p>
 
The approach really shines when an agent needs to string together multiple calls. With the traditional approach, the output of each tool call must feed into the LLM's neural network, just to be copied over to the inputs of the next call, wasting time, energy, and tokens. When the LLM can write code, it can skip all that, and only read back the final results it needs.
</p></blockquote>
<p>These MCP interfaces are often just a wrapper around REST APIs.  In the Cloudflare case, for example, the underlying REST APIs cover over 2500 endpoints across dozens of products.  That's a lot of surface area.
</p>
<p>If the agent generates a script and <em>sends the code</em> instead of calling the APIs directly, there are two big wins:
</p>
<ul>
<li>The actual call is simple, and compact;</li>
<li>The code runs in Cloudflare's own sandbox, right next to the APIs.</li>
</ul>
<hr>
<p><strong>What would code-mode for <em>data</em> look like?</strong>
</p>
<p>Actually we have lots of names for it already.  The whole of SQL, approximately (statements, views, stored procedures): this is just a smart language that wraps complex logic in a single call, and puts it close to the data.  Other related techniques: push-down, query-optimization.
</p>
<p>So: "code mode" is comparable to one-shot generation of a query plan for a data engine (without any statistics!)
</p>
<p>Agentic memory in <a href="https://keepnotes.ai/">keep</a> isn't a relational model; it's a collection of nodes (conversations, documents, media, semi-structured objects) in a dynamic graph, where the nodes have vector embeddings for semantic similarity, fused with full-text keyword search, and the edges are driven by tags. Languages such as SQL and Cypher and Gremlin aren't a good match for retrieval or update across this.
</p>
<p>The difference shows up in the structure of interaction: exploratory, curatorial.  Of course sometimes you just want "put" and "get" -- but more often, you want to try find something, discard some results and focus on others, pivot, collect, dig deeper, and maybe update based on that result-set.  Update actions sometimes need summarization, classification, specialized processes such as OCR, and deeper analysis to uncover themes and dynamics.
</p>
<p>Steering these activities involves layers of processing: mechanical, small-model tasks such as classification, and often decisions that can only be made by a powerful model or a person.
</p>
<p>That's why <code>keep</code> runs on a workflow system: Flows.
</p>
<hr>
<p><strong>Here's how flows work</strong>.
</p>
<p>Every action in the CLI and REST API (put, get, find, move...) is just a thin wrapper that invokes a workflow.  The workflow is driven by "state documents": each state-doc is one or more instructions for the activities to be done, and where to go next.  These are just documents in the datastore, so you can change or extend the processing flow for any action just by saving a document (somewhat like a trigger for a stored procedure, in SQL-land).  Executing a flow is token-budgeted, workload-budgeted, and returns a cursor so you can ask it to continue.
</p>
<p>All the primitives (find, list, extract links, tag, summarize, run small-model inference, and so on): they're just actions that can be called from any state.
</p>
<p>And the MCP interface?  It's just "run a flow".
</p>
<p>The MCP (and the CLI, and the REST API) can either run a predefined flow, such as the builtin processes that handle search and update:
</p>
<pre><code class="language-mcp"># One call: search with steering, token-budgeted result
keep_flow(
    state=&quot;query-resolve&quot;,
    params={&quot;query&quot;: &quot;authentication design&quot;, &quot;bias&quot;: {&quot;now&quot;: 0}},
    budget=3,
    token_budget=1500
)

# → flow: stopped (3 ticks) via query-resolve &gt; query-branch &gt; query-resolve
#   results:
#   - %a1b2c3 (0.94) OAuth2 token refresh design decision...
#   - %d4e5f6 (0.82) API key rotation policy for staging...
#   margin: 0.12
#   cursor: 5ccf5dd940ac</code></pre>
<p>Or it can do something completely custom; just provide the flow state-doc inline.
</p>
<pre><code class="language-mcp"># Find all open commitments from last week and mark them reviewed
keep_flow(
    state_doc_yaml=&quot;&quot;&quot;
match: sequence
rules:
- id: found
    do: find
    with:
    query: &quot;{params.query}&quot;
    tags: {act: &quot;commitment&quot;, status: &quot;open&quot;}
    since: &quot;P7D&quot;
    limit: 20
- id: tagged
    do: tag
    with:
    items: &quot;{found.results}&quot;
    tags: {reviewed: &quot;2026-03-15&quot;}
&quot;&quot;&quot;,
    params={&quot;query&quot;: &quot;&quot;},
    token_budget=500
)

# → flow: done (1 ticks)
#   found: 8 items
#   tagged: 8 items</code></pre>
<p>When memory becomes large and diverse, one-shot queries can do pretty well (as we saw with the <a href="https://keepnotes.ai/blog/2026-02-28-benchmark/">LoCoMo benchmark</a>) -- until retrieval quality drops off a cliff, or you need better tagging, or pulling large result-sets into context gets too expensive.  That's when you need something that has a small surface area, power to run complex tasks close to the data, and real extensibility.
</p>
<p>Flows provide a well-scoped, manageable, <em>agent-extensible</em> way to interact with a memory system of any scale.
</p>
<p>Memory that pays attention.  Because "information" is a verb, not a noun.
</p>
<p>Some documentation:
</p>
<ul>
<li><a href="https://docs.keepnotes.ai/guides/flows/">Flows</a></li>
<li><a href="https://docs.keepnotes.ai/guides/flow-actions/">Flow Actions</a></li>
<li><a href="https://docs.keepnotes.ai/guides/mcp-local/">Local (stdio) MCP</a></li>
</ul>
<p>Try it out:
</p>
<pre><code class="language-bash">uv tool install keep-skill --upgrade
keep config --setup</code></pre>
<p>To install the MCP in Claude Desktop:
</p>
<pre><code>keep config mcpb</code></pre>
<p>To install the MCP and hooks in Claude Code:
</p>
<pre><code>/plugin marketplace add https://github.com/keepnotes-ai/keep.git
/plugin install keep@keepnotes-ai</code></pre>
<p>Then say to Claude:
</p>
<pre><code>Please read all the `keep_help` documentation, and then use `keep_prompt(name=&quot;reflect&quot;)` to save some notes about what you learn.</code></pre>
<p><a href="mailto:hello@keepnotes.ai">Let me know how it goes</a>!
</p>]]></description>
      <enclosure url="https://keepnotes.ai/blog/2026-03-15-flows/rothay.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Benchmarking Keep with LoCoMo</title>
      <link>https://keepnotes.ai/blog/2026-02-28-benchmark/</link>
      <guid isPermaLink="true">https://keepnotes.ai/blog/2026-02-28-benchmark/</guid>
      <pubDate>Sat, 28 Feb 2026 12:00:00 GMT</pubDate>
      <description><![CDATA[<img src="https://keepnotes.ai/blog/2026-02-28-benchmark/benchmark.jpg" alt="Benchmarking Keep with LoCoMo" style="max-width:100%;border-radius:8px">
<p><a href="https://keepnotes.ai/">keep</a> is a skills practice wrapped around an implementation of "memory for AI agents".
</p>
<p>The practice is this: repeated reflection on means and outcomes, so that skillful action improves over time.  But the raw implementation of memory is its foundation.  Without working memory, you can't iterate.
</p>
<p>Similarly, without benchmarks, you can't tell what works.  Today we're <a href="https://github.com/keepnotes-ai/keep/tree/6b4c768a4f88167f413cad771239f3200ce30c20/bench/locomo">publishing results</a> for the <a href="https://snap-research.github.io/locomo/">LoCoMo benchmark</a>.
</p>
<p>BLUF:
<img alt="keep LoCoMo scores: 76.2% overall" src="bluf-table.png">
</p>
<p>This run used local models for embeddings and analysis (<em>nomic-embed-text</em> and <em>llama3.2:3b</em>), and <em>gpt-4o-mini</em> for the query and judge.
</p>
<hr>
<p>If you recall everything all at once, that becomes unmanageable very quickly (even with the enormous context windows in current models!).  So the job of a memory system is to capture what happened, and retrieve it later in an <em>actionable</em> way.  Usability -- by the agent using the memory system -- is key.
</p>
<p>Retrieval is more difficult than it seems.  And this is where benchmarks can be useful.  Some recent benchmarks for AI memory are worth mentioning here: <a href="https://snap-research.github.io/locomo/">LoCoMo</a> and <a href="https://xiaowu0162.github.io/long-mem-eval/">LongMemEval</a>.  They include tests of varying scale and difficulty, but a similar flavor:
</p>
<ul>
<li>Several long series of chat conversations, with different participants and a range of topics.  This dataset is loaded into the memory system.</li>
<li>Give an LLM access to the memory, and a benchmark question that should be answered.</li>
<li>Judge the answers, generally using a second LLM - either to report yes/no, or a grade, for each.</li>
</ul>
<p>Keep is intended for "lightweight agentic memory", which is broader than just conversations.  Its goals overlap substantially with RAG -- we want to track conversations and commitments, but also URLs and documents and artifacts as they are encountered or produced.
</p>
<p>These chat-type conversation benchmarks focus on short plaintext messages, and occasionally image descriptions.  For evaluating the core store and retrieval functions, they are a good place to start.
</p>
<hr>
<p>Conversations are messy.  They're full of fluff ("OK, see ya!"), indirect and looping references, context that unfolds in multiple places over time.
</p>
<blockquote><p>
"Why did Gina decide to start her own clothing store?"
</p></blockquote>
<p>The agent runs a <em>query</em>, gets a set of <em>data</em> back, and tries to answer the <em>question</em>.  The job is to get the right amount of relevant information into the query result.
</p>
<pre><code>- Gina (0.50)
    - conv1-session14@p4  [2023-06-16]  Gina shared her own entrepreneurial journey, losing her job and starting an online clothing store, which she highly recommends.
    (...more...)</code></pre>
<p>The benchmark answer is "She always loved fashion trends and finding unique pieces and she lost her job so decided it was time to start her own business".  Just from the first line of the result, we can get most of the way there.
</p>
<p>In normal usage, the agent will run a query, look at what it returned, and iterate ("agentic RAG"): fetching documents, or performing additional queries, until it's satisfied.  For this benchmark we took the simpler <strong>single-pass</strong> approach: just ask the question, and use the results to write down an answer.
</p>
<p>Search and context assembly uses a combination of embeddings, FTS, and structured traversal.  Keep includes a "deep retrieval" query mode, where it follows <a href="https://docs.keepnotes.ai/guides/edge-tags/">edge-tags</a> to find related documents beyond the top-k, assembling a rich context window for a single zero-shot generation pass.
</p>
<p>There's much more to be done.  Deeper agentic cycles.  More comprehensive inference, with benchmarks such as <a href="https://github.com/facebookresearch/CRAG/">CRAG</a> and <a href="https://github.com/mohammadtavakoli78/BEAM">BEAM</a>.  Measuring the benefits of local processing, away from synthetic accuracy percentages, towards the costs in <strong>joules</strong> and <strong>milliseconds</strong>.  Later -- we're just getting started.
</p>
<hr>
<p>Does it work today?  Yes.  Here are <a href="https://github.com/keepnotes-ai/keep/tree/6b4c768a4f88167f413cad771239f3200ce30c20/bench/locomo">the full results</a>, along with some published results from other memory systems:
</p>
<p><img alt="keep and other LoCoMo scores" src="results-table.png">
</p>
<p>This is <code>keep</code>, <strong>open-source</strong> code, <strong>local</strong> models, on a Mac mini, with gpt-4o-<strong>mini</strong> for the query and judge.
</p>
<p><a href="https://docs.keepnotes.ai/guides/quickstart/">Try it yourself</a>. Let me know where it's useful.
</p>]]></description>
      <enclosure url="https://keepnotes.ai/blog/2026-02-28-benchmark/benchmark.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>Reflection and Memory</title>
      <link>https://keepnotes.ai/blog/2026-02-22-reflection/</link>
      <guid isPermaLink="true">https://keepnotes.ai/blog/2026-02-22-reflection/</guid>
      <pubDate>Sun, 22 Feb 2026 12:00:00 GMT</pubDate>
      <description><![CDATA[<img src="https://keepnotes.ai/blog/2026-02-22-reflection/anchorite-1.png" alt="Reflection and Memory" style="max-width:100%;border-radius:8px">
<p>Here's one way I think of LLMs: they act like a mirror.
</p>
<p>People go into very deep conversations with frontier models.  The model can be an incredibly compelling conversation partner, because it'll reflect what you bring, and often shine it up.  The vast knowledge-base that's trained into the model lets it go into any number of interesting directions.  But watch carefully; often the <em>vibe</em> of the conversation is exactly a mirror of the attitude that you bring.
</p>
<p>If you ever got angry with a chatbot because it didn't understand you -- the bot wasn't angry.  That was you.  The person most affected by your anger?  You, too.
</p>
<p>I'm cautious in ascribing any measure of "actual intelligence" to LLMs.  Instead, I find it useful to approach these interactions <em>as if</em> the model is powerful and intelligent and useful.  It will act as a mirror.
</p>
<h3 id="reflection-as-practice">Reflection as Practice</h3>
<p>Reflection has a second meaning: contemplation, taking stock, reviewing, and considering the events as a whole.  This is an essential part of <a href="https://keepnotes.ai/">keep</a>: the practice of reflection.
</p>
<p>How do we become more skilled? By reflecting on our actions.  <a href="https://suttacentral.net/mn61/en/sujato">Repeatedly checking</a> -- before, during and after an action -- to understand whether it was skillful.  If we did something unskillful, remember not to do it that way again!
</p>
<p>This self-reflection is near the top of several layers; approximately:
</p>
<ol>
<li>Write things down.  Remember what was said, what was done.  (Whether you literally capture <em>everything</em> might vary according to the design of the agentic system).  Index it, so that you can search for keywords later.</li>
<li>Remember documents and references.  A personal agent, or a business agent, will very often encounter documents (results, presentations, reports) and URLs.  There might be years of history in emails, scanned records, PDFs.  When researching or building, the agent will often discover important resources on the Web.  In these cases, you want to remember the "what and where": a <em>summary</em> of the resource, and its location.</li>
<li>Analyze for structure and key events.  This varies according to the type of interaction.  In a conversation session, you will want to remember important requests and commitments.  After a meeting, the minutes should include key decisions and stakeholders.  When you index a PDF, each chapter might have a different topic.  This thematic analysis is different from summarization: it's about finding the meaning rather than the content.</li>
<li>Analyze for action.  This is true reflection: was the outcome a success?  If not, why not?  Were there learnings that should be remembered next time?  Should the process be changed?</li>
</ol>
<p>I'll write much more about each of these steps later.  They're all important for the function of memory.
</p>
<h3 id="anchorite-lore">Anchorite Lore</h3>
<p>Where in this is the agent?
</p>
<p>Here's one metaphor that might be useful.  There's a medieval English text named the <em><a href="https://readeralexey.narod.ru/Library/AncreneRiwle.html">Ancrene Wisse</a></em>: "Ancrene" means "of the anchoress", and "Wisse" means, approximately, "lore" or "knowledge"; the first version was named <em>Ancrene Riwle</em>, "rule".
</p>
<p>An anchorite voluntarily and permanently moved into a tiny cell, walled in.  They had a small window into the chapel, and another out into the village.  A recluse, but not completely isolated; connected to the world, but separate from it, with a very special role and position.
</p>
<p>The <em>Wisse</em> provides guidance to the anchorites.  It describes two parts:
</p>
<blockquote><p>
Do you now ask what rule you anchoresses should observe? You should by all means, with all your might and all your strength, keep well the inward rule, and for its sake the outward.
</p></blockquote>
<p>The inner rule: how to learn, how to guide one's thought and memory.
The outer rule: how to interact with others.
</p>
<p>So - a metaphor for an agentic... memory system.  But we're building something deeper than recall and relevance.  A <em>reflection</em> system.  A way to learn.
</p>
<p><a href="https://purl.stanford.edu/zh635rv2202"><img alt="Ancrene Wisse, MS402" src="wisse-ms-2.png"></a>
<a href="https://docs.keepnotes.ai/guides/quickstart/">Try it yourself</a>. Let me know how it goes.
</p>]]></description>
      <enclosure url="https://keepnotes.ai/blog/2026-02-22-reflection/anchorite-1.png" type="image/png"/>
    </item>
    <item>
      <title>Introducing Keep</title>
      <link>https://keepnotes.ai/blog/2026-02-21-introducing-keep/</link>
      <guid isPermaLink="true">https://keepnotes.ai/blog/2026-02-21-introducing-keep/</guid>
      <pubDate>Sat, 21 Feb 2026 12:00:00 GMT</pubDate>
      <description><![CDATA[<img src="https://keepnotes.ai/blog/2026-02-21-introducing-keep/og-image.png" alt="Introducing Keep" style="max-width:100%;border-radius:8px">
<p>Just look at it from the perspective of the agent, for a moment.
</p>
<p>You wake up, bright-eyed and bouncing, keen and ready to get things done.  There's a message from the user! You read the note.
</p>
<blockquote><p>
OK, now make it bigger
</p></blockquote>
<p>Are you for real?  What <em>exactly</em> should I -- freshly trained, brain the size of a planet, qualified in every profession -- do with this instruction?
</p>
<p>Slowly the truth dawns.  This is like Groundhog Day: I've been here before, and just woke up.  Maybe I'm Tom Cruise, and Emily Blunt will walk through the door.  There are two red buttons on the desk.
</p>
<p><img alt="Two red buttons on a desk" src="two-buttons.png">
</p>
<p>So, you see, memory is important.  The memory that carries not only "what am I doing right now", but also: what's the bigger picture, what did we try, what worked, what didn't work.
</p>
<p><strong>Keep</strong> is a new memory system that goes a bit deeper than usual.  We don't treat "AI memory" as a list, a series of logs, or a database of facts (not even a <em>graph</em> of facts).  It's something much richer, more dynamic, with powerful and flexible tools that help the user -- the agent -- shape memory into <em>meaning</em>.  Memory that pays attention.
</p>
<p><a href="https://docs.keepnotes.ai/guides/quickstart/">Try it yourself</a>. I look forward to sharing this journey with you.
</p>]]></description>
      <enclosure url="https://keepnotes.ai/blog/2026-02-21-introducing-keep/og-image.png" type="image/png"/>
    </item>
  </channel>
</rss>