FishMem

Time-aware memory: current truth without deleting history

Time-aware memory: current truth without deleting history
July 22, 2026Engineering11 min read

Why agent memory needs event time, validity intervals, and explicit supersession instead of last-write-wins profile fields.

A user says, “I moved to Berlin last month.” One clock says when the move happened. Another says when the system learned about it. If the record keeps only the insertion timestamp, historical questions and current-state retrieval will eventually disagree.

Time-aware memory does not require predicting every date. It requires representing the dates the evidence actually supports and keeping changes visible instead of overwriting them.

The short version

  • Separate event time from system or transaction time.
  • Represent validity with valid_from and valid_to.
  • Supersede old facts instead of erasing the path that produced earlier decisions.
  • Keep late evidence and corrections in immutable history.
  • Use temporal filters and ranking only after namespace and ownership filters.
  • Do not manufacture precision that the source never provided.

One timestamp answers the wrong question half the time

FieldQuestion it answersExample
Event dateWhen did the described event happen?The move happened on July 3
Valid fromWhen did this fact start being true?Berlin became the current city on July 3
Valid toWhen did this fact stop being true?Lisbon stopped being current on July 3
Created atWhen did the system first store this record?The user mentioned the move on August 12
History eventWhen did the system update its understanding?An operator corrected the date on August 13

Model current state as a validity question

“Where does the user live?” asks for a fact whose validity interval includes now. “Where did the user live in June?” asks for the interval containing a past date. Both queries may reference the same relationship over different periods.

Current retrieval should normally exclude invalidated records unless the query requests history. Historical retrieval should include the old record, its validity range, and the source or superseding record that changed it.

Supersession preserves explanation

When Berlin replaces Lisbon, updating one profile field produces the right current value but destroys the reason an earlier answer mentioned Lisbon. A supersession link closes the old interval and points to the new record while leaving both in history.

This supports:

  • current-state answers that prefer Berlin;
  • historical answers that can still find Lisbon;
  • audit views that explain when and why the change occurred;
  • rebuildable profiles that derive the latest active value;
  • correction without pretending the old record never existed.

Late-arriving evidence changes two timelines differently

Suppose the user says in August that the move happened in July, then clarifies in September that the lease began in June while the physical move happened in July. The application's domain model must decide which event the memory represents. Updating valid_from may change the world-time interpretation, while immutable system history still records that the correction arrived in September.

This is the core of bi-temporal reasoning: what the system currently believes about the world's timeline and how that belief changed over the system's own timeline.

Contradiction is not always replacement

“I prefer dark mode” and “Use light mode for presentations” may both be valid under different metadata or task scopes. Before superseding, compare subject, predicate, object, scope, conditions, and time. A global overwrite can turn a contextual exception into a false contradiction.

Use deterministic rules for well-typed product state where possible. Model inference may propose a relationship, but the persistence layer should enforce interval and ownership invariants.

Unknown time should remain unknown

Relative phrases require a trustworthy reference time. “Last year” can be normalized only if the source event has a known date and timezone assumptions are controlled. “I used to live in Lisbon” supports a past relationship but may not support exact boundaries.

Safe choices include:

  • store a known event date and leave validity open;
  • store a coarse interval only if the schema supports its precision;
  • retain the source phrase and mark normalized time as uncertain;
  • avoid adding a date when evidence is insufficient.

Retrieval needs temporal intent

A similarity score cannot decide whether a query asks for now, a past state, or the history of a change. Route temporal intent explicitly:

  1. detect time expressions and whether the query asks for current, as-of, or change history;
  2. bind namespace and structural scope;
  3. apply validity filters for the requested time;
  4. retrieve semantic, lexical, and association candidates;
  5. complete supersession and provenance context;
  6. render dates with their meanings rather than one unlabeled timestamp.

Failure modes to include in tests

CaseExpected behavior
Current fact replaces an old factCurrent query returns new; as-of query returns old
Correction arrives lateWorld-time changes; system history remains intact
Two facts apply under different conditionsBoth remain valid with explicit scope or metadata
Source has no reliable dateNo invented precision
Old fact ranks higher semanticallyValidity filtering prevents stale current recall
Superseding record is deletedHistory and current-state policy remain explicit

How FishMem represents time

Canonical records expose event_date, valid_from, valid_to, and superseded_by alongside creation time and immutable history. Search supports event-date filters, while state views can project current, as-of, and history answers back to canonical source IDs.

These fields make temporal behavior possible; they do not guarantee that an inference model extracted the right date. Evaluation must inspect the stored record, the retrieved rendering, and the final answer separately.

Further reading

Read next