Memory Consolidation
Besides compiling source material into Wikis, knowledge graphs, daily reports, and other artifacts with a Skill, ov compile has a special mode: memory consolidation. Instead of producing a new knowledge shape, it cleans up the existing memories in OpenViking in place — deduplicating, merging, splitting, and compacting them — while strictly conforming to each memory type's original schema.
Unlike regular compile, memory consolidation does not go through VikingBot; it runs directly inside OpenViking on the memory framework.
When to use it
Memories accumulate session after session, and over time you get:
- Duplicates: the same person or event recorded multiple times with slightly different wording;
- The same entity split across files: extraction in different batches failed to recognize them as one object (e.g. "Ah-Zhen" and "Chen Jingxian" are actually the same person);
- Mixed content: unrelated objects crammed into one memory;
- Verbosity: repetitive phrasing that could be tighter.
Running memory consolidation over a memory directory makes such a collection clean and non-redundant again, without losing facts.
How to use it
Set --skill to the sentinel value memory and point --to at a memories root or memory-type directory:
# Consolidate entities (dedup / merge / normalize in place)
ov compile \
--to viking://user/<user_id>/memories/entities \
--skill memory \
--instruction "Merge clearly duplicate entities, but do not merge distinct ones; keep each entity's unique facts"You can consolidate other memory types too, e.g. preferences:
ov compile \
--to viking://user/<user_id>/memories/preferences \
--skill memoryTo consolidate all existing, enabled memory types in one task and one ExtractLoop:
ov compile --to viking://user/<user_id>/memories --skill memory \
--instruction "Consolidate existing memories without losing facts; keep distinct objects separate"Root-level files such as profile.md, identity.md, and soul.md are included when present. Disabled and unregistered types are skipped. The user's root does not include peers/*/memories; target a peer's memories root explicitly to consolidate that space.
The command returns a task ID immediately. Use ov task status <id> to check the result and ov task cancel <id> to stop it.
Parameters
| Parameter | Description |
|---|---|
--skill memory | The fixed sentinel value that triggers memory-consolidation mode (it is not resolved as a real Skill). |
--to | Required: a memories root (.../memories) or a memory-type directory (e.g. .../memories/entities). User roots are not accepted. |
--from | Not accepted in memory mode — consolidation pulls in no external sources; it only reorganizes memories already under --to. |
--instruction | Optional. Passed to the model as a consolidation instruction (a soft hint). Use it to make merges the model cannot infer on its own, e.g. "Ah-Zhen is Chen Jingxian, please merge them." |
Behavior
- Type scope: a type directory loads only its schema; a memories root loads all existing enabled types in that space into one ExtractLoop, with each type retaining its own schema. If a rename or merge affects existing links/backlinks, the system may still update neighboring memory files of other types to preserve referential integrity.
- In place:
--fromand--toare the same space and no external source is introduced, so there is no cross-identity leakage. The space being consolidated (the current user's own self space, or apeers/{peer_id}space) is determined by the--toURI. - Conservative merging: only memories that are clearly the same identity are merged; distinct entities are kept separate even when they share a topic, category, or attributes. A merge the model cannot infer from content (e.g. two different names that are actually one person) is performed only when
--instructionspells it out. - No fabrication: it only reorganizes existing memories; it never invents new facts.
- Facts preserved: merges and compaction keep every distinct atomic fact and only compress duplicate wording.
- Rename support: when the schema allows a URI-defining field to change (for example an entity's
categoryorname), consolidation writes the new URI, migrates links/backlinks, and then deletes the old URI. The result reports this as the new URI inaddsand the old URI indeletes. - No conflict overwrite: if the rename destination already exists, consolidation reports a conflict instead of overwriting it. The model must read both memories, update the explicit target with every distinct fact, and then delete the source with a replacement relationship.
Result
A memory-mode task result includes the list of changed files for the run, with fields following the same semantics as the archived memory_diff.json:
| Field | Meaning |
|---|---|
adds / total_adds | Newly created memory files (e.g. new entities produced by a split) |
updates / total_updates | Modified memory files (a merge target, an in-place compaction) |
deletes / total_deletes | Removed / merged-away memory files |
trace_id | The trace of this consolidation run, for troubleshooting |
memory_types | Types selected for this run; memory_type is the selected type for a type-directory request, or null for a root request |
The list contains file URIs only, not content — a single run may touch many files, and their bodies are not returned in the result.
If errors is non-empty and no file changes succeeded, the task is failed and retains its result and trace. Partial success remains completed, with successful changes and failures recorded separately in the lists and errors; callers must check errors, not just the task status. A no-op without errors is completed.
A typical merge (folding "Ah-Zhen" into "Chen Jingxian"):
{
"memory_type": "entities",
"trace_id": "…",
"adds": [],
"updates": ["viking://user/xiaomei/memories/entities/person/陈静娴.md"],
"deletes": ["viking://user/xiaomei/memories/entities/person/阿珍.md"],
"total_adds": 0,
"total_updates": 1,
"total_deletes": 1,
"errors": []
}Prerequisites
- A running OpenViking service (memory consolidation runs inside the service process; enabling Bot is not required). The default endpoint is
http://localhost:1933; remote use needs an API Key — see Authentication. - The
ovCLI configured with a connection (~/.openviking/ovcli.conforOPENVIKING_*environment variables). - The memory directory pointed to by
--toalready contains memories (typically extracted from sessions by session commit).
Related docs
- Context Compilation Overview — the overall introduction to
ov compile - Agent Runtime API — full reference for creating, inspecting, and cancelling Compile tasks