Why ZettelForge¶
A narrative log of ZettelForge's first three weeks — March 28 to April 16, 2026. Written April 16, 2026.
Historical snapshot
This essay records the project as it stood on April 16, 2026. The version and feature statements below describe ZettelForge 2.2.0. For current installation and product facts, start with the ZettelForge documentation. ZettelForge 2.8.0 is current and MIT-licensed as of the August 10, 2026 audit.
On the last days of March 2026, Patrick Roland had a problem that most people building with AI agents don't talk about publicly: his agents kept forgetting things.
Not in the dramatic, catastrophic way — not the kind of forgetting where a model hallucinates a customer's name or invents a CVE that doesn't exist. This was the quieter kind. The kind where an agent researches a threat actor on Monday, produces a solid brief, and by Wednesday has no recollection that the research ever happened. The kind where four agents working in parallel duplicate each other's work because none of them can remember what the others have already done.
At the time, Roland ran four AI agents with distinct roles from a workstation in his workspace. They communicated through a gateway called OpenClaw, passing daily syncs and fleet files back and forth like shift workers leaving notes on a clipboard. The memory system underneath all of this was called A-MEM: a JSONL file and a LanceDB vector store. It was, by any honest assessment, a notebook held together with tape.
This is the story of what happened when Roland decided to fix that — not as a side project, not as a weekend experiment, but as the central engineering problem worth solving. It took approximately three weeks. What emerged was ZettelForge, an open-source agentic memory system for cyber threat intelligence, and along the way, the outline of a company.
The inciting incident¶
The first sign that the memory problem was deeper than it looked came from the research missions.
Roland had built a "research loop" — a pattern where an agent reads from a mission queue, executes one mission at a time, and persists its findings. In early April, he started feeding it questions. Not simple ones. Questions like: what does the state of the art look like for agentic memory? What do SOC analysts actually struggle with? What does competitive pricing look like in the threat intelligence market?
The missions worked through them methodically. One analyzed Paperclip's architecture and adopted its SKILLS.md pattern. Another surveyed the academic literature on agentic memory and found Mem0. The Mem0 paper reports a 66.9 LLM-as-a-Judge score on the LOCOMO benchmark and 91% lower p95 latency than the full-context baseline. Other missions mapped the commercial landscape and the lack of connected context in security operations.
The research also surfaced Mem0's two-phase extraction pipeline. Every incoming piece of information would be processed through extraction and then classified as ADD, UPDATE, DELETE, or NOOP. The memory wasn't just a store anymore. It was starting to make decisions about itself.
The open-source turn¶
Around April 9, Roland made the decision that would define the project's character. ZettelForge — the name borrowed from the Zettelkasten method of connected note-taking — would be extracted from the fleet's internal memory system and published as a standalone, MIT-licensed Python library on PyPI. A real thing that other people could use.
This was not an obvious choice. The memory system was deeply entangled with the fleet's infrastructure, with OpenClaw, and with the specific quirks of four agents and their communication patterns. Extracting it meant drawing a clean boundary between what was Roland's and what was everyone's. A repository restructuring mission handled the surgery.
Simultaneously, the commercial picture was taking shape. The company would be called ThreatEngram, LLC, and the managed SaaS product would be ThreatRecall.ai. But Roland made a decision on April 15 that deserves attention because it reveals something about how he thinks: "High OS community adoption is the path to paying customers. The open source repo must not feel like a sales funnel."
He called it the anti-aversion policy. No lock icons in the documentation. No "upgrade to unlock" language. No paid-feature gating visible in the open-source docs. Managed SaaS capabilities would live outside the open-source core. Someone browsing the open-source repo would find a complete, useful tool, not a demo with paywalls.
This is a bet, and it's worth naming it as one. The theory is that developers who adopt ZettelForge for their own agent systems will eventually work at organizations willing to pay for the managed version. The counter-theory is that giving away the core means there's nothing left to sell. Roland chose his side.
The research deepens¶
While the open-source extraction was happening, the literature survey expanded. It was supposed to cover ten to fifteen papers on agentic memory, synthesized into an evolving thesis. It became twenty-two papers and sixteen thesis iterations, and it nearly broke the system along the way.
The thesis evolved like a living document. Version 1.0 covered two papers and identified four gaps. By version 1.1, the research had found MAGMA's causal graph approach and flagged it as the key differentiator for CTI work — not just knowing that two things are related, but knowing that one caused the other. By version 1.3, after ingesting the A-Mem paper, the thesis articulated what would become the project's central insight: "Memory evolution is the missing feature." Existing notes in a memory system never update when new, related notes are added. The memory is append-only in practice, even when the architecture technically supports updates. Information arrives but never integrates.
Then things went sideways. The research discovered that each LanceDB table contained one row instead of thousands. The vector index — the thing that makes semantic search possible, the thing that lets you ask "what do we know about this threat actor?" and get relevant results — was functionally empty.
The debugging saga consumed two days and revealed the kind of compound failure that haunts any system built incrementally. The root cause was three bugs stacked on top of each other: a missing import pyarrow in the indexing function, a logic flaw where only the first note was successfully inserted per batch, and a __bool__ method on the LanceDB connection class that returned False, causing truthiness checks to fail silently. PR #27 addressed the failure, and recall worked again.
This episode matters for the narrative because it's the kind of thing that doesn't appear in launch announcements. Two days of a solo developer staring at row counts, tracing imports, and reading library source code to understand why a connection object evaluates to False. It is the actual texture of building software, and it happened in the middle of what was supposed to be a research sprint.
The research continued. Version 1.5 brought DeltaMem, which revealed cascading information attenuation in multi-agent pipelines — exactly the problem Roland had started with, now given a name and a mechanism. By version 1.7, the thesis had processed twenty-two papers and assembled an architecture that drew on MemArchitect, Governed Memory, MemMachine, and Kumiho's formal AGM belief revision framework. One finding stood out: the CTI-REALM paper reports that seeded, human-authored domain guidance closed 33% of the measured performance gap between GPT-5-Mini and GPT-5 Medium. For a system designed to make smaller models more useful, that result matters.
The sprint¶
April 15 and 16 were the kind of days that justify the preceding weeks of groundwork. Roland shipped with the specific urgency of someone who knows exactly what needs to be built.
On the 15th, a consolidation layer was integrated into the write path, memory evolution was wired into the enrichment queue, and the causal-chain retrieval fix shipped.
On April 16, the StorageBackend contract established the boundary that backends had to fulfill. The SQLiteBackend — more than 800 lines, with WAL mode and transaction-backed writes — replaced JSONL as the default storage layer. A migration script handled the transition. Integration tests went green. The CI matrix tested the real backend path. A VectorRetriever boundary fix resolved the SQLite/LanceDB interaction. A LangChain retriever wrapper shipped. Version 2.2.0.
Then came the reconciliation. An architecture diagram existed in the repository, but it was wrong — it showed TypeDB as the primary graph store even though TypeDB was optional, and it omitted the MCP server, the SQLite backend, the memory evolver, and causal-chain retrieval. A codebase audit generated a new diagram, committed it to the correct repository, and removed the stale copy.
This kind of housekeeping isn't dramatic, but it's diagnostic. A project that audits its own documentation against its actual codebase and corrects the drift is a project that intends to be used by people other than its author.
The state of things¶
ZettelForge 2.2.0 shipped on April 16, 2026. It included a two-phase extraction pipeline, blended retrieval across vector, graph, and intent classification, memory evolution, causal-chain retrieval, cross-encoder reranking, an MCP server, LangChain integration, OCSF audit logging, and an MIT license.
The research thesis, at version 1.7, had designed an architecture ahead of the shipped code. Three gaps defined the project's honest frontier: format stability for open-weight models, saturation-aware benchmarking, and CTI-specific evaluation.
At the close of this April 16 snapshot, the internal A-MEM system was still running, the SaaS repository had early dashboard, API, and infrastructure work, and the open-source code was public. Three weeks was not a long time. It was long enough to turn a fragile internal memory store into a released open-source system with a research foundation and a clear list of what still did not work.