ArticlesExplainer

Bi-Temporal Memory: Why AI Agents Must Know When a Fact Was True

An AI agent that has been running for six months will, at some point, confidently tell you something that used to be true. It will cite a pricing tier…

July 202612 min read
bi-temporal memorytemporal knowledge graphai memory consistencytemporal consistency ai

An AI agent that has been running for six months will, at some point, confidently tell you something that used to be true. It will cite a pricing tier that changed in Q2. It will reference a teammate's role after they've moved teams. It will pull a customer's contract terms from a version that was superseded eleven weeks ago. None of this is a hallucination in the technical sense. The model is retrieving a real fact from a real document. The failure is temporal: the agent has no concept of when that fact stopped being true, or when the system found out it stopped being true. It just knows the fact exists somewhere in its retrieval index, so it says it.

This is the core limitation of nearly every production RAG and agent memory system today. Vector stores index text. Knowledge graphs index entities and relationships. Almost none of them index time correctly, and the ones that try usually only track one dimension of it. That single gap is responsible for a disproportionate share of the "confidently wrong" outputs teams see from long-running agents, and it gets worse, not better, the longer an agent runs and the more documents accumulate in its context.

The fix is bi-temporal memorya modeling approach that tracks not just what was true, but when it was true in the world, and separately, when the system learned it was true. This article explains the mechanism in depth, why single-timestamp systems fail, and how a bi-temporal context graph like Sentra's resolves it at write time instead of leaving it as a runtime guessing game.

The two clocks problem: valid time versus transaction time

Bi-temporal modeling comes from database theory, originally used in financial systems and healthcare records where "what did we believe, and when" is a compliance requirement. It rests on tracking two independent timelines for every fact:

Valid time is the period during which a fact was actually true in the real world. A customer's contract had a 12-month term valid from March 1 to February 28. A teammate held the title "Senior Engineer" from January through September before being promoted.

Transaction time is the period during which the system recorded that fact as true. This is when the document was ingested, when the field was written to the database, or when the agent's memory graph absorbed the update.

These two clocks are almost never in sync, and the gap between them is exactly where agents get things wrong. Consider a real scenario: a pricing page changes on April 3rd, reflecting a decision that was made and took effect on April 1st. If your agent ingested the old page on March 15th and does not re-ingest until May 1st, there is a 47-day window (April 3 to May 1) where the world already changed but the system does not know it, and a separate 2-day window (April 1 to April 3) where the change was valid before it was even published anywhere the agent could see.

A single-timestamp system, meaning one that just stores "last updated" or "created at," collapses both of these clocks into one number. It cannot tell you which gap you are in. It cannot tell you whether a fact is stale because the world changed, or stale because ingestion lagged, or actually still current. Bi-temporal memory keeps both clocks explicit, which means an agent (or the humans debugging it) can always ask two separate questions: "was this true then?" and "did we know it at the time?"

Why single-timestamp memory breaks agents in production

Most vector databases and even many "knowledge graph" products attach a single timestamp, typically ingestion time, to each chunk or node. This works fine for static corpora. It fails predictably in any environment where facts change, which is every real business.

Here is the specific failure chain:

1. A fact changes in the source system (Salesforce, Notion, a contract repository, an HR tool). 2. The old fact and the new fact both exist as embeddings in the vector store, often with similar semantic content, because "contract term: 12 months" and "contract term: 24 months" are close in embedding space. 3. At query time, retrieval ranks by semantic similarity to the question, not by validity. Both chunks score similarly. 4. The agent's context window ends up with both the old and new fact, with no structural signal indicating which one superseded the other. 5. The LLM, faced with two contradictory chunks and no temporal ordering, either merges them into a confused answer or picks the one that happened to appear first in context.

This is not a rare edge case. In any org with normal document churn (contract renewals, org changes, pricing updates, policy revisions), the density of superseded-but-still-indexed facts grows continuously. A six-month-old agent memory is not six months of facts. It is six months of facts plus every prior version of every fact that changed, all competing for retrieval relevance with no temporal arbitration.

Some teams try to patch this at query time: adding a "please prioritize recent information" instruction to the prompt, or reranking by ingestion date. This helps marginally but does not solve the underlying problem, because ingestion date is transaction time only. It tells you when the system learned something, not when that something stopped being valid in the world. A document ingested last week can still describe a policy that expired two months ago.

Resolving meaning at write time instead of guessing at query time

This is the architectural decision that separates a bi-temporal context graph from a patched vector store. The question is not "how do we rank conflicting facts better at query time." It is "why are we letting conflicting facts reach query time unresolved at all."

Sentra's approach is to resolve temporal meaning once, at write time, when new information enters the graph. When a new fact arrives, whether from a document, an API sync, a Slack message, or a CRM update, the ingestion pipeline does not just embed and store it. It checks the fact against existing nodes in the org's context graph, identifies whether it contradicts, updates, or extends an existing fact, and writes the correct temporal relationship immediately: closing the valid-time range on the superseded fact, opening a new valid-time range on the current one, and stamping both with accurate transaction time.

The practical effect is that by the time an agent queries the graph, there is no ambiguity left to resolve. There is exactly one fact marked as currently valid for any given entity and attribute, plus a full, queryable history of what was valid before, with clean boundaries. The agent does not need a clever prompt to figure out which contract term is current. There is only one node marked current, and it is the correct one, because the resolution work already happened during ingestion.

This matters enormously for token economics as well as correctness. A query-time guessing system has to stuff multiple candidate versions of a fact into context and hope the model sorts it out, burning tokens on redundant, contradictory information. A write-time-resolved graph returns one clean, current answer (plus history only if the query asks for it), which is a meaningful part of why Sentra customers see roughly 70% lower token spend on comparable agent workloads. Sentra also does better on the actual reasoning, scoring approximately 88% on Terminal-Bench 2.1, a benchmark that specifically stresses multi-step agent tasks where stale or contradictory context causes cascading errors.

What a bi-temporal fact actually looks like

It helps to be concrete about the data model. A bi-temporal fact is not just a row with a timestamp. It is a record with at minimum four temporal boundaries plus the fact payload itself:

FieldExample valueMeaning
Entitycontract:acme-corp-2024What the fact is about
Attributeterm_lengthWhat property is being described
Value24 monthsThe fact itself
Valid from2024-03-01When this became true in the world
Valid to2026-03-01 (or null if current)When this stopped (or will stop) being true
Recorded at2024-03-04T09:12:00ZWhen the system learned this
Superseded bynull or a pointer to the next fact nodeExplicit link to the fact that replaced it

That "superseded by" pointer is what makes the graph genuinely bi-temporal rather than just timestamped. It turns a flat list of dated facts into a traversable history where every fact knows its own successor and predecessor. An agent asking "what is Acme's current contract term" traverses to the node with valid_to: null. An agent asking "what did we tell Acme's account manager the term was in April" traverses to whichever node had a valid range covering April, regardless of what the current node says.

Query patterns a bi-temporal graph enables

The practical value of this structure shows up in query types that are simply impossible to answer reliably with a single-timestamp system.

"What is true right now?" This is the default query, and it is trivial in a bi-temporal graph: filter for valid_to: null on the relevant entity. No ranking, no reranking, no ambiguity.

"What did we believe at time X, even if it was wrong?" This is critical for auditing agent behavior. If an agent gave a customer incorrect information on June 10th, you need to reconstruct exactly what the graph said was current on June 10th, not what is current now. Bi-temporal storage answers this by filtering on recorded_at <= June 10 and finding whichever fact had the widest valid range as of that transaction time. Systems with only one timestamp cannot answer this at all; they have already overwritten the old value.

"What was actually true during period Y, regardless of when we found out?" This is the valid-time-only query, useful for retroactive corrections. Legal and compliance teams ask this constantly: "what were the actual terms in effect during Q2, even accounting for the late invoice correction we processed in Q3."

"When did we find out X changed, and how long was the lag?" This compares valid time to transaction time directly and surfaces operational risk. A 60-day lag between a policy changing and the system recording it is a process problem worth flagging on its own, independent of any specific query an agent runs.

A single-timestamp system can approximate the first query type and cannot reliably answer the other three at all, because the information needed to answer them was never captured in the first place.

Comparing memory architectures directly

CapabilitySentra (bi-temporal context graph)Standard vector RAGSingle-timestamp knowledge graph
Tracks valid time (when fact was true in the world)Yes, explicit valid_from/valid_to on every factNoRarely, and usually inferred, not stored
Tracks transaction time (when system learned it)Yes, explicit recorded_at with full historyOnly as generic "ingested_at" metadataSometimes, as last-updated field
Resolves conflicts at write timeYes, contradiction detection during ingestionNo, conflicts persist until query timePartial, usually just overwrites old value
Can reconstruct "what we believed on date X"YesNoNo
Token cost for retrieving current factLow, single resolved node returnedHigh, multiple candidate chunks often retrievedMedium
Org-wide shared context across agentsYes, single graph shared by all agents and teamsNo, typically per-application indexNo, typically per-application
Compliance postureSOC 2 and ISO 27001, self-hosting availableVaries by vendorVaries by vendor
Benchmark performance (Terminal-Bench 2.1)~88%Not designed for this class of taskNot designed for this class of task

The verdict across every row that matters for long-running agent reliability favors resolving temporal state structurally rather than statistically. Vector similarity is a good tool for finding semantically related content. It is the wrong tool for determining which of two contradictory facts is currently authoritative, because similarity and correctness are unrelated axes.

The org-wide context graph as a shared source of truth

A subtlety that often gets missedtemporal consistency is not just a per-agent problem, it is an org-wide problem. If your sales agent, your support agent, and your internal ops agent each maintain separate memory stores, you can end up with three different agents holding three different beliefs about the same fact, each internally consistent but mutually contradictory. A customer asks support about a contract term and gets one answer, then asks sales and gets another, and both agents are technically citing "current" information from their own isolated index.

This is why Sentra is built as a single org-wide bi-temporal context graph, a shared company brain that every agent and every team draws from, rather than siloed memory per application. When the contract term updates, it updates once, in one place, and every agent querying that entity afterward sees the same current fact and the same history. This also means the write-time resolution work (contradiction detection, supersession linking) happens exactly once per fact change, rather than being duplicated across N separate ingestion pipelines for N separate agents, which is both a correctness win and a cost win.

For regulated environments, this shared graph runs under SOC 2 and ISO 27001 controls, and self-hosting is available for teams that need the context graph inside their own infrastructure perimeter rather than a third-party cloud, which matters when the facts in question include contract terms, HR records, or customer PII.

Implementation patterns for teams building this themselves

Teams evaluating whether to build bi-temporal handling in-house versus adopting a platform should know the specific engineering lift involved, because it is substantial and easy to underestimate:

Contradiction detection at ingestion requires an entity resolution layer that can recognize "24 month term" and "term_length: 24mo" as the same attribute before it can even ask whether they conflict. This is nontrivial NLP and schema-matching work, not a database feature.

Supersession linking requires deciding, for every entity type, what counts as "the same fact updating" versus "a new, separate fact." A contract term changing is clearly an update. A customer having two concurrent contracts for different products is not a conflict at all and should not be merged. Getting this distinction wrong in either direction either loses history or falsely merges facts that were never actually competing.

Query-time filtering on two temporal dimensions instead of one means every retrieval call needs to specify not just "what" but "as of when, on which clock," and application code calling the memory layer has to be written with that in mind from day one, since retrofitting it later means auditing every existing query.

Most teams that attempt this in-house get as far as single-timestamp overwriting (the vector RAG or basic knowledge graph rows in the table above) and stop there, because full bi-temporal modeling with write-time contradiction resolution is a multi-quarter engineering investment on top of whatever the actual product is supposed to do.

Closing takeaway

An agent that has been running for months is not just accumulating knowledge, it is accumulating versions of knowledge, and without a structural way to track which version was true when and which version the system knew about when, that accumulation guarantees eventual confident wrongness. Bi-temporal memory solves this by tracking valid time and transaction time as separate, explicit dimensions on every fact, and by resolving contradictions once, at write time, rather than leaving the LLM to guess at query time from a context window full of competing versions. Sentra implements this as a single org-wide context graph shared across agents and teams, cutting token spend by roughly 70% on comparable workloads, scoring around 88% on Terminal-Bench 2.1, and running under SOC 2 and ISO 27001 controls with self-hosting available for teams that need the graph inside their own perimeter. The question worth asking about any agent memory system is not "does it have timestamps." It is "does it know the difference between when something was true and when it found out."

What is bi-temporal memory in AI systems?
Bi-temporal memory is a data modeling approach that tracks two independent timelines for every fact an AI system stores: valid time, meaning the period during which the fact was actually true in the real world, and transaction time, meaning the period during which the system recorded or believed that fact. Most AI memory systems, including standard vector RAG setups, only track a single ingestion timestamp, which makes it impossible to distinguish between a fact that is stale because the world changed and a fact that is stale because ingestion lagged behind reality.
How is a temporal knowledge graph different from a regular knowledge graph?
A regular knowledge graph stores entities and relationships, often with a single "last updated" timestamp per node. A temporal knowledge graph, specifically a bi-temporal one, stores explicit valid-time ranges and transaction-time ranges on every fact, along with supersession links connecting old versions of a fact to the new versions that replaced them. This lets the system answer queries like "what was true during this specific period" or "what did we believe on this specific date," which a single-timestamp graph structurally cannot answer because it only ever keeps the current value.
Why do AI agents give outdated answers even when using retrieval-augmented generation?
RAG retrieves based on semantic similarity between the query and stored text chunks, not based on temporal validity. If a document was updated, both the old and new versions often remain in the vector index with similar embeddings, and retrieval has no structural signal for which one is current. The result is that an agent's context window can contain contradictory information with no way to arbitrate between them, so the model either merges the contradiction into a confused answer or picks whichever version happened to rank slightly higher or appear first in the prompt.
Does resolving temporal conflicts at write time actually reduce cost, or just improve accuracy?
Both. Resolving contradictions at write time means only one current, correct fact is stored per entity and attribute, so a query returns a single clean node instead of multiple competing candidate chunks that the model has to read through and reconcile. Because retrieval no longer needs to pull in redundant or contradictory versions of the same fact to be safe, context windows shrink meaningfully, which is a significant contributor to the roughly 70% lower token spend Sentra customers see compared to query-time-resolved retrieval approaches.
Can bi-temporal memory work across multiple agents and teams, or is it per-application?
It should be org-wide. If each agent or application maintains its own isolated memory index, different agents can end up holding different, contradictory beliefs about the same underlying fact, each internally consistent but inconsistent with each other. Sentra addresses this by maintaining a single shared, bi-temporal context graph across an entire organization, a company brain that every agent and team queries, so a fact updated once is current for every agent immediately, rather than requiring separate updates propagated across N separate memory stores.

Sentralize your company.

Remember what matters.

Resources
Articles
Preferences

Subprocessors include Amazon Web Services, GitHub, Slack, Google Cloud Platform, and OpenAI.

© 2026 Dynamis Labs Inc. All rights reserved.