Daniel's been staring at the codebase of something called OpenViking — an open-source project from Volcengine that calls itself a "self-evolving context database for AI agents." He wants us to walk through what it actually is under the hood, because the README is ambitious: it claims to unify memory, RAG, and skills in one substrate. He's asking what the data model looks like, how the layered abstraction works, why that matters for token budgets, what "self-evolving" means in the implementation, and what trade-offs you're making versus the standard stack of a vector database plus flat skill files. He wants the real engineering picture.
So the core thing to understand — and it took me a couple of read-throughs to get this — is that OpenViking is not a vector database with a filesystem metaphor painted on top. It's actually a filesystem. The addressing scheme uses a viking:// URI protocol, and everything inside — memories, documents, skills — lives at a path. You browse it with ls and tree and find. An agent doesn't query a black box. It navigates a directory tree.
Which is either brilliant or completely unhinged, and I'm still not sure which.
I think it's both. The data model has three top-level namespaces under viking://. There's resources, which holds ingested documents, code repos, web pages. There's user, which splits into per-user directories containing memories, skills, and peers — peers being other agents or users that share context. And there's a snapshot namespace for versioned checkpoints.
So the directory tree is the schema. No separate metadata store, no mapping layer between the vector index and the content.
Right. And the directory structure itself encodes relationships. If you have a project doc at viking://resources/my_project/docs/api/auth.md, the parent directories carry semantic meaning — the path tells you what namespace this lives in, what project, what subcategory. Retrieval uses that structure. When you do a vector search, it doesn't just return the top K chunks. It finds the highest-scoring directory first, then drills down layer by layer, so results arrive with their surrounding context intact.
That's the part where I stopped and thought — okay, they actually solved something. The standard RAG pipeline gives you floating chunks with no sense of where they came from. You get a paragraph about authentication and you have no idea if it's from the API docs or the onboarding guide. Here, the path is the provenance.
And they call the retrieval trajectory observable — every query preserves the directory-browsing path it took, so when a result is wrong, you can see which branch produced it. That's not a nice-to-have. That's the difference between debugging a retrieval pipeline and just shrugging.
Walk me through the layered abstraction thing. The README mentions L0, L1, L2.
This is the part that matters for token budgets, and it's genuinely clever. On write — when you add a resource or when a session commits — OpenViking processes every entry into three tiers. L0 is the abstract, roughly a hundred tokens, a one-sentence summary for quick relevance checks. L1 is the overview, about two thousand tokens, with core information and usage scenarios — enough for planning. L2 is the full original content, loaded only when the task actually needs the details.
And every directory gets its own L0 and L1.
Every directory. So the agent can judge relevance at the directory level before pulling any files. It sees viking://resources/my_project/docs/ has an abstract and overview, reads those, decides whether to descend. The token savings come from not loading full documents until the last possible moment.
So the agent is doing something closer to how a human skims a filesystem — read the folder names, read the summaries, open the file only if it looks relevant.
That's exactly the design philosophy. They have a blog post calling it "the database paradigm for context engineering," and the argument is that context should be browsable and deterministic, not retrieved by embedding similarity alone. The vector search is there — it's how you locate the right directory to start from — but after that, you're navigating a tree.
The benchmarks in the README are... striking. LoCoMo accuracy going from twenty-four percent on native agent memory to over eighty percent with OpenViking. Input tokens dropping by thirty-four to ninety-one percent depending on the agent.
And query latency dropping by fifty-eight to sixty-six percent. Those numbers are from version zero point three point twenty-two, tested across three different agent integrations — OpenClaw, Hermes, and Claude Code. The tau2-bench results are more modest but still real: plus seven percentage points on retail tasks, plus twelve on airline tasks, just from adding experience memory.
Let's talk about what's actually in the code. I was looking at the repository structure — it's enormous. Eight and a half million tokens of code across over three thousand files. Rust, Python, C plus plus, TypeScript, Go. This is not a weekend project.
It's a serious engineering effort. The Python layer — the openviking package — handles the server, the SDK, ingestion, retrieval, session management, memory extraction, metrics. The Rust layer — crates/ — has the CLI client, a whole virtual filesystem framework called ragfs, and caching backends for Redis and some custom stores. The C plus plus layer under src/ is the vector index engine with custom scalar and vector indices, including sparse retrieval support.
And then there's a whole bot framework called VikingBot that sits on top — it's a separate agent runtime with its own channels for Discord, Slack, Telegram, WhatsApp, email, DingTalk, Feishu. Plus a web studio in React. This is a platform, not a library.
The integration surface is what makes it interesting for agent builders. They have plugins for Claude Code, Codex, Cursor, OpenCode, Trae, Pi — each one hooks into the agent's session lifecycle. On session start, it injects relevant memories and context. During the session, it captures turns. On session end, it commits the transcript and triggers asynchronous memory extraction.
The Claude Code plugin is instructive. It's a set of hooks — session-start, session-end, pre-compact, subagent-start, subagent-stop — each firing a script that talks to the OpenViking server. The auto-capture hook records every user message and assistant response. The auto-recall hook queries the server for relevant memories before each turn.
And there's an MCP proxy in there — so the agent tools that interact with OpenViking go through the Model Context Protocol. The plugin registers tools like ov-search, ov-read, ov-write, ov-ls, ov-tree. The agent gets a filesystem interface to its own memory.
Which brings us to the unification claim. The README says it unifies three things agent builders usually bolt on separately: memory, RAG, and skills.
Let me take those one at a time, because they're unified differently. Memory — this is the most mature piece. When a session commits, OpenViking asynchronously runs a memory extraction pipeline. There are extractors for different memory types: user preferences, agent experiences, entities, events, trajectories, skills learned during the session. Each extractor is a prompt template — they're in openviking/prompts/templates/memory/ — and the extracted memories are written back into the user's memory tree as structured markdown files.
So the memory isn't a separate database. It's files in a directory.
Correct. viking://user/alice/memories/preferences/writing_style is literally a markdown file that gets updated over time. The "self-evolving" part means these files aren't static — the memory updater can merge new observations into existing memories, resolve contradictions, update confidence. There's a whole merge operation system with strategies like replace, patch, sum, immutable. A new session observation about Alice preferring bullet points doesn't create a duplicate file — it patches the existing preference.
And the extraction is asynchronous — it happens after the session, not during.
Yes, and that's an engineering choice worth noting. They don't try to extract memories in real time during the conversation. The session commits, goes into a queue, and the extraction pipeline processes it. There's a queuefs subsystem that manages this — semantic processing tasks go into named queues, get picked up by workers, results get written back. This avoids adding latency to the agent's response time.
What about RAG? How does that fit into the filesystem model?
RAG — retrieval-augmented generation — is basically the retrieval half of the system. When you add a resource — say a PDF or a GitHub repo — it goes through the ingest pipeline. The openviking/ingest/ module handles this. The resource gets parsed — there are parsers for markdown, PDF, HTML, EPUB, Word, PowerPoint, Excel, code files with AST extraction, audio, video, images. The parsed content gets chunked, embedded, and stored in the vector index.
But the vector index isn't the primary interface. The filesystem is.
Right. The vector index is an implementation detail underneath the viking:// tree. When an agent does ov find "how does authentication work", the system does a vector search to locate the most relevant directory, then returns results as filesystem paths with their L0 and L1 summaries. The agent can then ov read specific paths to get L2 content. The retrieval is hierarchical — it finds the directory first, then drills down.
And skills? That's the third piece.
Skills are interesting because they blur the line between memory and tools. A skill in OpenViking is a markdown file with a SKILL.md convention — it describes a capability the agent has learned. Skills can come from session extraction — the system watches what the agent does successfully and extracts the pattern — or they can be written by developers. They live at viking://user/alice/skills/ and get loaded into the agent's context when relevant.
So if an agent figures out a reliable way to deploy a Docker container during a session, that pattern can become a skill that persists across sessions.
That's the goal. The session/skill/ module handles this — session_skill_context_provider.py and skill_operation_updater.py. There's also a training framework under session/train/ that can optimize skill policies based on rollout trajectories. It's experimental — the design docs are in the repo — but the architecture is there.
Let's talk about the trade-offs versus the conventional stack. Most agent builders today have a vector database — Pinecone or Qdrant or whatever — plus some flat skill files in the project directory, plus maybe a separate memory service like Mem0 or a homegrown solution. Three systems, three APIs, three failure modes.
And the integration burden is real. You have to decide when to query the vector store versus when to read a skill file. You have to manage separate embedding pipelines. You have to figure out how memory updates propagate. The OpenViking bet is that unifying all of this under a filesystem abstraction reduces the surface area the agent has to reason about. One protocol, one addressing scheme, one retrieval pattern.
The trade-off is that you're now running a whole server. This is not a library you import. It's a service you deploy — with its own configuration, its own embedding models, its own storage backends. The ov.conf configuration alone covers vector databases, embedding providers, rerank models, VLM models, encryption, git backends, transaction settings. It's a lot of surface area to manage.
And the storage layer is flexible in a way that's both powerful and complex. The vector database can be local — they have their own C plus plus engine — or Qdrant, or Volcengine's VikingDB. The filesystem backend can be local disk, S3, or a custom multi-backend wrapper that routes writes to multiple stores. There's encryption support, transaction locking, snapshot versioning. For a team that needs all of that, it's infrastructure they'd have to build anyway. For a solo developer, it's a lot of YAML.
The git integration is worth mentioning. Under crates/ragfs/src/git/, there's a full git backend — the filesystem can be versioned with commits, branches, object stores. So you can roll back your agent's memory to a previous state. That's not something you get from a vector database.
Snapshots — the ov snapshot command and the snapshot namespace. You can checkpoint the entire context state, share it, restore it. The snapshot format is an ovpack archive that includes vectors, metadata, and content. It's designed for portability between instances.
The thing I keep coming back to is: who is this for? Reading the code, this feels like infrastructure for teams running agents in production — multi-agent setups, long-running sessions, shared context across users. The multi-tenant support is built in from the start. There's an admin API, API key management, OAuth, usage auditing, Prometheus metrics, Grafana dashboards.
The bot framework — VikingBot — is clearly designed for deployment. It has Docker images, Helm charts, Kubernetes deployment configs, ECS support. You can run it as a persistent agent that lives in your Slack or Discord, accumulating memory across conversations.
But here's what I wonder about. The filesystem metaphor is elegant, but it also constrains what you can express. A vector database lets you do similarity search across arbitrary embeddings. The filesystem forces everything into a hierarchical namespace. What if the relationships between memories don't fit a tree?
That's a real limitation, and I think they know it. There's a relations system — the relations API and the link_relations endpoint — that lets you create cross-references between paths. And the memory graph view under session/memory/graph_view.py builds a graph structure on top of the tree. But the primary organization is still hierarchical. For some use cases — a knowledge graph of interconnected concepts — a pure tree is awkward.
The other trade-off is the write path. Every resource addition triggers parsing, chunking, embedding, L0 and L1 generation. That's computationally expensive. The README says "wait some time for semantic processing" if you don't use the --wait flag. For a large document corpus, that "some time" could be significant.
The embedding pipeline is configurable but not trivial. You need to set up embedding models — they support OpenAI, Cohere, Voyage, Jina, Gemini, DashScope, Volcengine, local models via Ollama. The rerank step is separate. The VLM models for image understanding are separate. Each of these is a provider with its own API key, its own rate limits, its own cost structure.
The operational complexity doesn't disappear. It moves from "I have three separate systems to manage" to "I have one system with fifteen configuration dimensions."
That's a fair summary. Though I'd argue the single-system complexity is easier to reason about than three systems with overlapping responsibilities. When retrieval goes wrong in the unified model, you can trace the path. When it goes wrong across three separate systems, you're correlating logs from different services.
Let's talk about the "self-evolving" claim concretely. What actually happens automatically?
Three things. First, session-to-memory extraction. After each session commits, the system extracts preferences, experiences, entities, events, and potential skills. These get written into the memory tree and are available for future retrieval. Second, memory merging — when new observations arrive, the system tries to merge them with existing memories rather than creating duplicates. The merge operations handle conflicts, updates, and confidence scoring.
And the third?
Skill policy optimization. The training framework under session/train/ can take rollout trajectories — sequences of agent actions and outcomes — and optimize the skill policies that guide future behavior. It's a reinforcement learning loop: the agent acts, the outcomes are evaluated, the skill descriptions are updated to favor successful patterns. This is the most experimental part, but it's in the code — policy_optimizer.py, gradient_estimator.py, rollout_executor.py.
So "self-evolving" means the system updates its own context based on what it observes, without a human manually curating memories or writing skill files.
Yes. Though I'd note that the extraction quality depends heavily on the LLM doing the extraction. If the extraction model hallucinates or misses nuance, the memory degrades.
Which is the same problem every memory system has, to be fair.
It is. But the filesystem model makes the degradation visible. You can open viking://user/alice/memories/preferences/ and read what the system thinks it knows about Alice. If it's wrong, you can edit the file directly. That's harder to do with a vector database where the "memory" is an embedding somewhere.
The integration with Claude Code specifically — Daniel mentioned this in his prompt. What does that actually look like for a developer?
There's an example directory — examples/claude-code-memory-plugin/ — that shows the full setup. You install the plugin, it adds hooks to your Claude Code session. On session start, it queries OpenViking for relevant context and injects it into the system prompt. During the session, every user message and assistant response gets captured. On session end, the transcript is committed. There's also a pre-compact hook that captures context before Claude Code compacts its conversation, and subagent-start and subagent-stop hooks for tracking subagent sessions separately.
The agent can actively query its own memory during the session?
Through the MCP tools. The agent can call ov-search to find relevant memories, ov-read to pull specific files, ov-ls and ov-tree to browse the context tree. It's not just passive injection — the agent can actively explore its memory when it needs to.
That's a different model from the standard "stuff relevant chunks into the prompt and hope." The agent has agency over what context it retrieves.
It can write to its own memory. The ov-write tool lets the agent explicitly store something it wants to remember. There's a skill called ov-experience-memory that teaches the agent when and how to do this — it's a SKILL.md file that gets loaded into context.
What's the verdict for someone building agents today? Is this ready to replace their current stack?
I'd say it depends on scale and complexity. If you're building a single agent with a handful of documents and short sessions, the overhead of running an OpenViking server probably isn't worth it. A simple vector store plus some prompt engineering will get you there faster. But if you're running agents that have long conversations, need persistent memory across sessions, share context between multiple agents, or need to learn from experience — that's where the unified model starts to pay off.
The benchmarks suggest the payoff is real once you cross that threshold. Going from twenty-four percent to eighty-two percent accuracy on long-conversation memory is not incremental. That's the difference between a system that works and one that doesn't.
The token savings matter at scale. If you're paying per token for every agent turn, reducing input tokens by a third to ninety percent is real money. The tiered loading — only pulling L2 when needed — is doing genuine work there.
The thing I'd watch is the operational maturity. The codebase has extensive tests — thousands of them across Python, Rust, TypeScript — and the CI pipeline is serious. But it's a complex system, and complexity means sharp edges. The doctor command and the setup wizard suggest they know this and are trying to smooth the onboarding.
The documentation is unusually thorough for an open-source project at this stage. English and Chinese docs, architecture guides, API references, integration guides for a dozen agent frameworks, deployment guides for Docker, Kubernetes, ECS. Someone is investing heavily in making this usable.
On the record — where do you think this goes in the next year?
I think the "context database" category solidifies. Right now every agent framework is inventing its own memory solution. By mid twenty twenty-seven, I expect at least one major framework — probably Claude Code or a close competitor — will ship with something OpenViking-shaped as the default context layer. Whether it's OpenViking itself or an in-house equivalent, the filesystem-plus-tiered-loading pattern is too obviously correct to stay niche.
I'll go a different direction. I think the training loop — the policy optimization from rollout trajectories — is the part that either breaks out or gets abandoned. It's the most ambitious piece and the least proven. If it works at scale, it changes how we think about agent improvement. If it doesn't, OpenViking is still a very good context database without it.
That's fair. The memory and RAG unification is solid today. The self-evolving skill optimization is a bet on the future.
One open question I'm left with: the filesystem model assumes agents are comfortable navigating hierarchical paths. Current LLMs are okay at this but not great — they make path errors, they get confused by directory depth. Does the abstraction actually reduce cognitive load for the model, or does it just move the complexity to a different kind of reasoning?
That's the right question, and I don't think we know the answer yet. The benchmarks suggest it works better than the alternatives for the tasks tested. But whether that generalizes — whether the tree model is easier for LLMs to reason about than flat retrieval results — that's going to take more research.
We'll find out.
We will. Thanks to Hilbert Flumingtop for producing. This has been My Weird Prompts. You can reach us at show at my weird prompts dot com.
We'll be back soon.