Skip to main content
Cognee keeps the current state of memory and records how it changed. Every node carries a version counter and created_at / updated_at timestamps. Conflict review keeps outdated facts in the graph and marks them superseded instead of deleting them. An opt-in provenance ledger records when and from which source each entity was written. Cognee does not keep old copies of nodes or documents, so to roll back to an earlier state, export a snapshot first.

What Cognee keeps

Version a memory you write yourself

A DataPoint has a version field that starts at 1. Cognee never increments it on its own. Call update_version() when a change should count as a new revision, then write the DataPoint back. update_version() adds 1 to version and sets updated_at to now. Writing a DataPoint with the same id updates the stored node in place. Here identity_fields derives the id from user and key, so a new value for the same preference updates the same node:
The example needs no LLM or embedding key, because graph_only=True skips embeddings. It prints:
After the second write, the node reads helix at version 2. The earlier value vim is gone: the version counter tells you the node changed, not what it was before. The provenance ledger wouldn’t keep it either: it records when and from where cognify() wrote an entity and its name, not its other property values, and it doesn’t see writes from add_data_points(). To keep earlier values, export a COGX snapshot before changing them.

Update a document

When a document you added with remember() changes, use cognee.update(). It replaces the document under the same data_id, re-extracts what the edit touched and removes relationships that no longer hold. Adding the changed file with remember() again doesn’t create a second copy. If the dataset already holds a file from the same path (or an upload with the same filename) with different content, remember() raises DocumentUpdateRequiredError and points you to update(). Raw text has no file name, so changed text is always added as a new document, with no link to the old one. Adding the exact same content again is a no-op, since Cognee deduplicates documents by content hash.

Keep outdated facts instead of overwriting them

When new data contradicts what Cognee already knows, conflict review keeps both facts and records which one is current. Run it with improve(review_conflicts=True), or set IMPROVE_REVIEW_CONFLICTS=true to run it after every remember(). The date that decides which fact is newer comes from the effective_date in the document’s metadata. Superseded facts stay in the graph and in recall() results. They are sorted after current facts and labelled, for example [superseded; as of 2025-03-01], so the LLM sees what changed and when. See Review Conflicting Facts for a walkthrough.

Keep an audit trail of writes

For an audit trail of what was written, when and from which source, enable the provenance ledger before the first cognify() or remember() call:
Cognee then records every document, chunk, entity and relationship that cognify() (and so remember()) writes in an append-only, hash-chained ledger. Each entry holds the entity’s id, type, name, source and timestamps, not its other property values. Writes from add_data_points() in your own code, improve() and chunk-level update() are not recorded. When an entity is written again, the ledger archives the previous entry and links the new one to it, instead of overwriting it. You can call invalidate() to retire an entity with a tombstone entry; forget() doesn’t do this, and ledger entries stay after the data is deleted. revision_history() returns an entity’s versions oldest first, each with version, valid_from, valid_until and recorded_at, and verify_chain() checks that no entry was edited or removed:
Ledger ids are prefixed with the dataset id, so the same entity keeps a separate chain in each dataset. The ledger is read through cognee.modules.provenance and has no HTTP endpoint. See Provenance ledger for setup and the full ProvenanceManager API.

What Cognee doesn’t keep

  • Previous node values. Writing a node again overwrites its properties in the graph and vector stores. The ledger records that earlier versions existed, but not their values.
  • Previous document content. update() replaces the document’s content and file.
  • Point-in-time queries. recall() reads the current graph. There is no “as of” filter.
  • Deleted data. forget() deletes permanently. There is no soft delete. Provenance ledger entries for the deleted data stay in place.
To keep a restorable copy of a dataset at a point in time, export it as a COGX archive before making changes:

Next steps

DataPoints

Fields, identity and updating custom DataPoints

Review Conflicting Facts

Mark outdated facts as superseded

Update

Replace a document under the same id

Memory Provenance

See where each fact came from