{"id":23727,"date":"2026-09-04T17:43:19","date_gmt":"2026-09-04T17:43:19","guid":{"rendered":"https:\/\/scannn.com\/give-your-coding-agents-a-memory-you-own\/"},"modified":"2026-09-04T17:43:19","modified_gmt":"2026-09-04T17:43:19","slug":"give-your-coding-agents-a-memory-you-own","status":"publish","type":"post","link":"https:\/\/scannn.com\/lv\/give-your-coding-agents-a-memory-you-own\/","title":{"rendered":"Give Your Coding Agents a Memory You Own"},"content":{"rendered":"\n<div><!----><br \/>\n<!--]--><!--]-->I work across several machines, and I switch coding agents depending on the task.<br \/>\nEvery one of them meets my projects as a stranger. The reasoning from \u201clast Tuesday\u201d<br \/>\ndisappears when the session ends. Each new agent, on each new host, starts from zero.<\/p>\n<p>Earlier this year, <a href=\"https:\/\/huggingface.co\/blog\/huggingface\/agent-traces-as-memory\"><em>Software Forgets: Agent Traces Are the<br \/>\nMemory<\/em><\/a> made the case<br \/>\nthat coding agents already produce the record we keep losing. As they search a<br \/>\ncodebase, try approaches, hit errors, read documentation, and change direction, they<br \/>\nleave behind a dense account of not just <em>what<\/em> changed, but <em>why<\/em>.<\/p>\n<p>While the diagnosis is correct, traces are only potential memory. The session logs of<br \/>\nan agent are still just an archive. You cannot <code>grep<\/code> your way to <em>\u201cwhy did we move<br \/>\noff the streaming parser?\u201d<\/em> across ten thousand turns. For an agent to use those traces<br \/>\nwhile it works, they need indexing, retrieval, ranking, and exact provenance.<\/p>\n<p>That is what <a href=\"https:\/\/github.com\/huggingface\/funes\" rel=\"nofollow\">funes<\/a> provides. It is a durable<br \/>\nmemory layer for your agents (Claude Code, Codex, pi, and Hermes). It is built from the<br \/>\nsessions already on your machine. It works locally and becomes part of your agent&#8217;s<br \/>\nnormal workflow with one command. When you want it to, it can also travel to a Hugging<br \/>\nFace dataset you own, private by default.<\/p>\n<h2 class=\"relative group flex items-baseline\">\n\t<a id=\"add-memory-to-the-agent-you-already-use\" class=\"block pr-1.5 text-lg md:absolute md:p-1.5 md:opacity-0 md:group-hover:opacity-100 md:right-full\" href=\"#add-memory-to-the-agent-you-already-use\" rel=\"nofollow\"><\/p>\n<p>\t<\/a><br \/>\n\t<span><br \/>\n\t\tAdd memory to the agent you already use<br \/>\n\t<\/span><br \/>\n<\/h2>\n<p>funes is a single binary. Its default inference backend has no ML runtime dependency,<br \/>\nand embedding and reranking happen <em>on your machine<\/em>. Install it:<\/p>\n<pre><code class=\"language-bash\">curl -fsSL https:\/\/huggingface.co\/buckets\/huggingface\/funes\/resolve\/install.sh | sh\n<\/code><\/pre>\n<p>Then add it to an agent:<\/p>\n<pre><code class=\"language-bash\">funes add claude    \n<\/code><\/pre>\n<p>That one <code>add<\/code> command builds the first index, gives the agent <code>recall<\/code> and <code>get<\/code><br \/>\ntools, and installs the automation that indexes each completed turn. Indexing is<br \/>\nincremental, with new runs adding new turns rather than embedding the whole history<br \/>\n again. The older and deeper content can backfill in bounded steps.<\/p>\n<p>From there, you just work. When a task touches a past decision, rationale, or finding,<br \/>\nthe agent can reach for <code>recall<\/code> itself. You do not need to remember the old session or<br \/>\npaste its context into the new one.<\/p>\n<p><a href=\"https:\/\/huggingface.co\/datasets\/huggingface\/documentation-images\/resolve\/main\/blog\/funes\/recall.gif\" rel=\"nofollow\"><\/a><\/p>\n<blockquote class=\"note\">\n<p>With funes added, recall happens inside the conversation. The agent reaches for its<br \/>\nmemory on its own and names the session behind its answer.<\/p>\n<\/blockquote>\n<p><code>recall<\/code> returns the original text, not a summary, and shows exactly where it came from<br \/>\n(the agent, timestamp, session, and turn). Each result includes a <code>get<\/code> command that<br \/>\nopens the full turn and its surrounding context.<\/p>\n<p>Underneath, one deterministic pipeline parses every supported trace into the same<br \/>\nturn-and-block shape, chunks it, embeds it with a pinned local model, and writes it to<br \/>\na local <strong>Lance<\/strong> dataset. A query combines vector and BM25 search, fuses their<br \/>\nrankings, reranks the candidates with a cross-encoder, reweights them by recency, and<br \/>\nattaches neighboring chunks.<\/p>\n<p>That design gives funes three important properties:<\/p>\n<ul>\n<li><strong>One memory across agents:<\/strong> Claude Code, Codex, pi, and Hermes all write to the<br \/>\nsame shape. <code>recall<\/code> spans their histories, and every hit says which agent produced<br \/>\nit.<\/li>\n<li><strong>Raw evidence stays intact:<\/strong> Nothing is distilled into a fact at write time. A<br \/>\nresult can always lead back to the turn that produced it.<\/li>\n<li><strong><code>recall<\/code> is local by default:<\/strong> No account or Hub repository is required. A hosted<br \/>\nmodel does not process your sessions for indexing; embedding and reranking run on<br \/>\nyour machine, and your coding agent does the reasoning.<\/li>\n<\/ul>\n<p>The <em>agent as a stranger<\/em> problem is already solved on one machine. But memory gets<br \/>\nmore useful when the next agent is running somewhere else.<\/p>\n<h2 class=\"relative group flex items-baseline\">\n\t<a id=\"a-memory-is-a-dataset-not-a-service\" class=\"block pr-1.5 text-lg md:absolute md:p-1.5 md:opacity-0 md:group-hover:opacity-100 md:right-full\" href=\"#a-memory-is-a-dataset-not-a-service\" rel=\"nofollow\"><\/p>\n<p>\t<\/a><br \/>\n\t<span><br \/>\n\t\tA memory is a dataset, not a service<br \/>\n\t<\/span><br \/>\n<\/h2>\n<p>To make a memory follow your work, bind one when you add funes to an agent:<\/p>\n<pre><code class=\"language-bash\">funes add codex acme\/funes-memory\n<\/code><\/pre>\n<p>The bind publishes your current memory there. funes then keeps it current, indexing<br \/>\neach turn locally and publishing at session boundaries. The agent recalls from it<br \/>\nthroughout. Run the same command on another machine and the memory follows you there.<\/p>\n<p>Underneath, the local memory is a Lance dataset, and the shared memory is a Hugging<br \/>\nFace dataset (private by default) you own.<\/p>\n<p>Before anything reaches the Hub, credentials have already been redacted during<br \/>\nindexing. Publishing then scans every chunk again and withholds anything that still<br \/>\nlooks like a secret. The scanner behind this is documented in<br \/>\n<a href=\"https:\/\/github.com\/huggingface\/funes\/blob\/main\/SECURITY.md\" rel=\"nofollow\"><code>SECURITY.md<\/code><\/a>, including<br \/>\nwhat it does and doesn&#8217;t cover.<\/p>\n<p>When an agent reads a remote memory, funes caches the dataset files locally, so warm<br \/>\nqueries return to local speed. The Hub supplies the ownership, access control,<br \/>\nversioning, and distribution it already supplies for other datasets. Your memory does<br \/>\nnot become an account in a separate memory service, and you do not rent it back<br \/>\nthrough an API.<\/p>\n<h2 class=\"relative group flex items-baseline\">\n\t<a id=\"ask-first-wire-later\" class=\"block pr-1.5 text-lg md:absolute md:p-1.5 md:opacity-0 md:group-hover:opacity-100 md:right-full\" href=\"#ask-first-wire-later\" rel=\"nofollow\"><\/p>\n<p>\t<\/a><br \/>\n\t<span><br \/>\n\t\tAsk first, wire later<br \/>\n\t<\/span><br \/>\n<\/h2>\n<p><code>recall<\/code> is shaped for agents. When you want to put a question to a memory yourself,<br \/>\nuse <code>ask<\/code>. It reads your local memory by default:<\/p>\n<pre><code class=\"language-bash\">funes ask claude <span class=\"hljs-string\">\"what did we decide about the streaming parser\"<\/span>\n<\/code><\/pre>\n<p>Or point it at a shared memory. We published a<br \/>\n<a href=\"https:\/\/huggingface.co\/datasets\/huggingface\/funes-memory\">memory<\/a> of funes development,<br \/>\nso you can ask why funes works the way it does without creating a memory of your own:<\/p>\n<pre><code class=\"language-bash\">funes ask claude <span class=\"hljs-string\">\"why is funes append-only\"<\/span> --memory huggingface\/funes-memory\n<\/code><\/pre>\n<p><a href=\"https:\/\/huggingface.co\/datasets\/huggingface\/documentation-images\/resolve\/main\/blog\/funes\/ask.gif\" rel=\"nofollow\"><img decoding=\"async\" src=\"https:\/\/huggingface.co\/datasets\/huggingface\/documentation-images\/resolve\/main\/blog\/funes\/ask.gif\" alt=\"Asking the published funes memory why it is append-only; funes retrieves the relevant sessions and a coding agent answers from them\"\/><\/a><\/p>\n<blockquote class=\"note\">\n<p><code>funes ask<\/code> is the read-only, one-question sibling of <code>funes add<\/code>. It recalls the<br \/>\npassages, hands them to a coding agent, and returns a grounded answer that names its<br \/>\nsources. It does not install an integration or change the agent&#8217;s persistent setup.<\/p>\n<\/blockquote>\n<p>A retrieval miss is not papered over. If the passages do not support an answer, the<br \/>\nagent says so. You can rephrase the question or add funes to the agent so it can search<br \/>\nthe memory iteratively during normal work.<\/p>\n<h2 class=\"relative group flex items-baseline\">\n\t<a id=\"switching-agents-without-losing-the-thread\" class=\"block pr-1.5 text-lg md:absolute md:p-1.5 md:opacity-0 md:group-hover:opacity-100 md:right-full\" href=\"#switching-agents-without-losing-the-thread\" rel=\"nofollow\"><\/p>\n<p>\t<\/a><br \/>\n\t<span><br \/>\n\t\tSwitching agents without losing the thread<br \/>\n\t<\/span><br \/>\n<\/h2>\n<p>A shared memory is not tied to the agent or model that created it. Start a task in<br \/>\nClaude Code, continue it in Codex next week, and the second agent can recall the first<br \/>\nagent&#8217;s reasoning. Use pi with a local model or one served through the Hugging Face<br \/>\nrouter, then return to Claude.<\/p>\n<p><a href=\"https:\/\/huggingface.co\/datasets\/huggingface\/documentation-images\/resolve\/main\/blog\/funes\/cross-agents.gif\" rel=\"nofollow\"><img decoding=\"async\" src=\"https:\/\/huggingface.co\/datasets\/huggingface\/documentation-images\/resolve\/main\/blog\/funes\/cross-agents.gif\" alt=\"Claude Code chooses an embedding model, then Codex recalls that decision in a separate session\"\/><\/a><\/p>\n<p><em>Claude makes a decision; a hook indexes it; Codex recalls it in another session. The<br \/>\nolder hits in the demo are earlier recordings of the same experiment: an append-only<br \/>\nmemory remembered the rehearsals too.<\/em><\/p>\n<p>This matters in a few different scopes:<\/p>\n<ul>\n<li><strong>Across your machines:<\/strong> Bind each agent to one memory and recall the history from<br \/>\nwhichever host you are using.<\/li>\n<li><strong>Across a team:<\/strong> A new teammate&#8217;s agent can retrieve months of decisions on day<br \/>\none, including dead ends and rationale that never made it into a pull request.<\/li>\n<li><strong>Alongside an open-source project:<\/strong> A maintainer can publish the sessions behind a<br \/>\nrelease, naming them on the push. Think of it as a searchable <code>CLAUDE.md<\/code> that holds<br \/>\nthe history of why the project is the way it is, instead of a page someone must keep<br \/>\nrewriting. Anyone can read a public memory with <code>--memory<\/code>.<\/li>\n<\/ul>\n<p>Published memories carry a dataset card and the funes tag, making them recognizable<br \/>\nand <a href=\"https:\/\/huggingface.co\/datasets?other=funes\">discoverable on the Hub<\/a>. The Hub<br \/>\nalready hosts open weights and datasets. funes adds open working memory. It holds<br \/>\nthe decisions, failed approaches, and rationale behind a project, queryable by another<br \/>\nagent and traceable to the sessions that produced them.<\/p>\n<h2 class=\"relative group flex items-baseline\">\n\t<a id=\"the-cheapest-way-out-of-a-long-session\" class=\"block pr-1.5 text-lg md:absolute md:p-1.5 md:opacity-0 md:group-hover:opacity-100 md:right-full\" href=\"#the-cheapest-way-out-of-a-long-session\" rel=\"nofollow\"><\/p>\n<p>\t<\/a><br \/>\n\t<span><br \/>\n\t\tThe cheapest way out of a long session<br \/>\n\t<\/span><br \/>\n<\/h2>\n<p>A long investigation bloats a session until each turn costs more to carry the context<br \/>\nthan to do the work. The usual answers are to let the agent compact and carry on, or to<br \/>\nwrite a handoff and start fresh. Recall is a third, so we measured them against each<br \/>\nother on the <a href=\"https:\/\/huggingface.co\/datasets\/dacorvo\/funes-handoff-recall-benchmark\/blob\/main\/results\/README.md\">handoff-vs-recall<br \/>\nbenchmark<\/a>:<br \/>\ntwo tasks whose answer cannot be reconstructed without the session prior knowledge.<\/p>\n<p>Compaction is what most agents do by default, and it was the only one of the three whose<br \/>\nresult divided: it arrived on one task and never arrived on the other. Where it failed,<br \/>\nits summary had flattened the findings that mattered. Recall returns the passages<br \/>\nthemselves, so a finding does not have to survive summarization.<\/p>\n<p>Recall was the cheapest of the three on both tasks, 8x cheaper than a written handoff on<br \/>\none and 4x on the other.<\/p>\n<p><a href=\"https:\/\/huggingface.co\/datasets\/huggingface\/documentation-images\/resolve\/main\/blog\/funes\/handoff-recall-cost.jpg\" rel=\"nofollow\"><img decoding=\"async\" src=\"https:\/\/huggingface.co\/datasets\/huggingface\/documentation-images\/resolve\/main\/blog\/funes\/handoff-recall-cost.jpg\" alt=\"Weighted tokens per successful task for five channels across two tasks, with recall the shortest bar on both\"\/><\/a><\/p>\n<p><em>The lighter segment of each bar is the one-time charge for preparing the channel, the<br \/>\nhandoff or the compaction, paid before the first question is asked and counted once. A<br \/>\ncross marks a channel that never arrives, and so has no cost per success.<\/em><\/p>\n<h2 class=\"relative group flex items-baseline\">\n\t<a id=\"stop-starting-from-zero\" class=\"block pr-1.5 text-lg md:absolute md:p-1.5 md:opacity-0 md:group-hover:opacity-100 md:right-full\" href=\"#stop-starting-from-zero\" rel=\"nofollow\"><\/p>\n<p>\t<\/a><br \/>\n\t<span><br \/>\n\t\tStop starting from zero<br \/>\n\t<\/span><br \/>\n<\/h2>\n<blockquote>\n<p><em>\u201cTo think is to forget differences, generalize, make abstractions.\u201d<\/em><br \/>\n\u2014 Jorge Luis Borges, <em>Funes the Memorious<\/em><\/p>\n<\/blockquote>\n<p>Your agents already wrote the record. funes lives at<br \/>\n<a href=\"https:\/\/github.com\/huggingface\/funes\" rel=\"nofollow\"><code>github.com\/huggingface\/funes<\/code><\/a>, one command away<br \/>\nfrom turning that record into a memory the next agent can read, on whichever machine you<br \/>\nhappen to be on.<\/p>\n<h2 class=\"relative group flex items-baseline\">\n\t<a id=\"built-on-open-source\" class=\"block pr-1.5 text-lg md:absolute md:p-1.5 md:opacity-0 md:group-hover:opacity-100 md:right-full\" href=\"#built-on-open-source\" rel=\"nofollow\"><\/p>\n<p>\t<\/a><br \/>\n\t<span><br \/>\n\t\tBuilt on open source<br \/>\n\t<\/span><br \/>\n<\/h2>\n<p>funes invents little of this. It leans on open-source embedding models good enough to<br \/>\nrun locally, on <a href=\"https:\/\/github.com\/lancedb\/lance\" rel=\"nofollow\">Lance<\/a>&#8216;s append-only datasets with<br \/>\ncheap incremental writes, and on the Hub&#8217;s caching and content-dedup for datasets. The<br \/>\nwork is in fitting them into a memory an agent can actually use.<\/p>\n<p>funes is open source too. <a href=\"https:\/\/github.com\/huggingface\/funes\/issues\" rel=\"nofollow\">Open an issue<\/a><br \/>\nfor anything from an install snag to a recall that missed, or an agent you&#8217;d like<br \/>\nsupported.<\/p>\n<p><!----><\/div>\n<p><a href=\"https:\/\/huggingface.co\/blog\/funes?utm_source=tldrai\">Source link <\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I work across several machines, and I switch coding agents depending on the task. Every one of them meets my projects as a stranger. The reasoning from \u201clast Tuesday\u201d disappears when the session ends. Each new agent, on each new host, starts from zero. Earlier this year, Software Forgets: Agent Traces Are the Memory made [&hellip;]<\/p>\n","protected":false},"author":16,"featured_media":23728,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[143],"tags":[],"class_list":["post-23727","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai"],"_links":{"self":[{"href":"https:\/\/scannn.com\/lv\/wp-json\/wp\/v2\/posts\/23727","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/scannn.com\/lv\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/scannn.com\/lv\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/scannn.com\/lv\/wp-json\/wp\/v2\/users\/16"}],"replies":[{"embeddable":true,"href":"https:\/\/scannn.com\/lv\/wp-json\/wp\/v2\/comments?post=23727"}],"version-history":[{"count":0,"href":"https:\/\/scannn.com\/lv\/wp-json\/wp\/v2\/posts\/23727\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/scannn.com\/lv\/wp-json\/wp\/v2\/media\/23728"}],"wp:attachment":[{"href":"https:\/\/scannn.com\/lv\/wp-json\/wp\/v2\/media?parent=23727"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/scannn.com\/lv\/wp-json\/wp\/v2\/categories?post=23727"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/scannn.com\/lv\/wp-json\/wp\/v2\/tags?post=23727"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}