MemKraft is an integrated memory system for AI agents that I started building because I needed it myself. The more you talk with it, the smarter it gets on its own. A few days ago, I posted the development notes for v0.2–v0.5.

Since then, I made three more updates. This time, the nature of the problem changed from “the memory held by one agent” to “memory shared by multiple agents,” and from “what it knows to be true now” to “what was true from when to when.”

Figure 01Source Telegram #149

All I did was have a few dozen chats with my first agent, Zeon, in the gaps between everything else. The fourth version, v0.8, went from coding to PyPI release in 9 minutes and 17 seconds. The newly released Opus 4.7 agent completed four features, 83 tests, documentation updates, the build, upload, commit, and push all in one go.

Here are the keywords for each version.

--

v0.6: Where did the memory happen?

Every time a new session starts, the agent begins with a blank slate. What was discussed in the Telegram group chat yesterday, which iteration the current task is on, what tone I prefer — I had to explain everything again. That was where the question behind v0.6 began. Memory is not just the content. It also needs to store where it happened, what we were doing, and who it was with.

I established three axes: channel context, task continuity, and agent working memory. Channel context builds up preferences and recent topics for each chat room. Telegram DMs have the tone of DMs, and group chats have the rhythm of group chats. The answer should differ depending on which channel a question comes from, even when the question is the same. Task continuity follows “how far this task has progressed and what the next step is” even across sessions. Working memory records in one line what each agent is focused on right now, so other agents can avoid duplicating the work.

I organized the API around a single function called agent_inject. When delegating work to a sub-agent, it combines the channel, task, and agent status into a Markdown block and injects it into the prompt. An agent starting fresh knows from the first line, “Ah, I was working on this task in this chat room.” The test count went from 328 to 357.

v0.7: Memory is a team sport

Attaching memory to one agent was finished in v0.6, but there are five of them in my house. Zeon, Sion, Mion, Sano, and Raon. They each have different roles, they are in different chat rooms, and sometimes they ask me the same thing twice. I wanted to get rid of that waste.

I added the concept of handoffs. When Zeon passes work to Sano, he does not just pass along the task ID. He delivers, as one Markdown block, “the context in which we have been working with hyung up to this point.” The recipient can continue working from the same state. The task delegation chain is also recorded, so you can see at a glance that “this task went from me → Zeon → Sano → Raon.” You can also query, by channel, “who is working on what in this chat room right now.”

The implementation was simple. I added a few fields to the existing channel and task files, and the handoff function simply combined “my working memory + the selected task status” and appended it to the other agent’s working memory. Still zero external dependencies, all Markdown files. 409 tests. Not a single existing API broke. From v0.7 onward, the work of the five agents became noticeably smoother. There were fewer moments of “I asked Zeon about that earlier, but what was it?”

v0.8: Memory has truth and time, too

Up through v0.7, the problem was “where memory is and who writes it.” v0.8 went one step further into “when that memory was true.” I was inspired by mem0 v3, Letta, and Zep/Graphiti. Each was implementing a temporal knowledge graph in its own way. But they all required a database. “Could this be done with stdlib only, on top of Markdown files?” That was the question behind v0.8. I tried to answer it by bringing together four features.

The first is a bitemporal fact layer. Most memory systems record only “A is true now.” But facts in the real world have two time axes: “when it was true” and “when we came to know it.” fact_add records a fact together with its validity period, and fact_at retrieves the truth as of a specific date. It is expressed in a single line of an inline Markdown comment. Like <&#33;-- valid:[2020-03-01..) recorded:2026-04-17 -->, the same information can be understood by both people and machines.

The second is memory tiers. I borrowed Letta’s division into core, recall, and archival, but the implementation ended with writing one line, tier: core, in the YAML frontmatter. The working set for a task is automatically composed of all core memories plus recently accessed recall memories. Without a separate database table, one line at the top of a file distinguishes “this memory needs to be right in front of my mind” from “it can stay in the archive.”

The third is our own point of distinction in this version: restorable decay. Other systems implement forgetting as “deletion.” MemKraft implements it as “lowering the weight.” decay_apply pushes a memory toward the back of search results without touching the file. decay_restore can fully restore it at any time. There is also a concept called a tombstone: it is excluded from search but safely kept in the archive directory. mem0, Letta, and Zep do not do this. It came from the observation that people do not completely forget either; things simply become harder to recall.

The fourth is using the filesystem as a graph database. Write [[Simon Kim]] anywhere in a Markdown file, and link_scan automatically indexes the bidirectional link when it runs. link_backlinks("Simon Kim") returns every file that mentions Simon Kim, and link_graph returns the N-hop relationship network. It is similar to Obsidian’s graph view, but the backend is just directories and a few JSON files. The re and defaultdict modules in stdlib were enough.

The test count went from 409 to 492. I did not touch a single line of the existing core code. I kept the surgical change principle I have followed since v0.5 by attaching four new modules in init.py using the mixin pattern. External dependencies are still zero.

--

The theme running through the three updates from v0.6 to v0.8 was ultimately the expansion of memory’s boundaries. From one to many, from now to when, from content to relationships. Memory is no longer trapped in a few files. It expands into who writes it, when it was true, and what it is connected to.

Existing agent memory systems each go deep along one axis. MemKraft is still trying to absorb those axes without conflicts on a single filesystem. The principle that every storage format should be Markdown and JSON remains unchanged here. You should always be able to read it with cat, find it with grep, and dig through it with git log.

An eternal MIT license. Use it however you want. Stars, forks, and PRs are all welcome&#33;

seojoonkim/memkraftUltimate zero-dependency compound knowledge system for AI agents. Auto-extract, classify, search, and maintain memory in plain Markdown.GitHub · github.comOpen