Skip to content

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:

bash
# 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:

bash
ov compile \
  --to viking://user/<user_id>/memories/preferences \
  --skill memory

To consolidate all existing, enabled memory types in one task and one ExtractLoop:

bash
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 ​

ParameterDescription
--skill memoryThe fixed sentinel value that triggers memory-consolidation mode (it is not resolved as a real Skill).
--toRequired: a memories root (.../memories) or a memory-type directory (e.g. .../memories/entities). User roots are not accepted.
--fromNot accepted in memory mode — consolidation pulls in no external sources; it only reorganizes memories already under --to.
--instructionOptional. 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: --from and --to are 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 a peers/{peer_id} space) is determined by the --to URI.
  • 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 --instruction spells 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 category or name), consolidation writes the new URI, migrates links/backlinks, and then deletes the old URI. The result reports this as the new URI in adds and the old URI in deletes.
  • 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:

FieldMeaning
adds / total_addsNewly created memory files (e.g. new entities produced by a split)
updates / total_updatesModified memory files (a merge target, an in-place compaction)
deletes / total_deletesRemoved / merged-away memory files
trace_idThe trace of this consolidation run, for troubleshooting
memory_typesTypes 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"):

json
{
  "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 ov CLI configured with a connection (~/.openviking/ovcli.conf or OPENVIKING_* environment variables).
  • The memory directory pointed to by --to already contains memories (typically extracted from sessions by session commit).

Open source under the AGPL-3.0 License. Font licenses