Every record carries both event time and ingest time. Why two axes are non-negotiable.
Bi-temporal Model
Every record except Events carries four time fields:
| Field | Meaning |
|---|---|
| valid_from | First moment in the world when the claim is true |
| valid_to | First moment when the claim ceases to be true (exclusive). null = open-ended |
| recorded_from | First moment CortexDB learned the claim |
| recorded_to | First moment CortexDB superseded its own record (exclusive). null = current |
Events have just two: observed_at and recorded_at. Events are atomic in time and never superseded.
Why both axes
The question "what did the system believe about Acme on April 15 when looked at from May 1?" requires:
recorded_from ≤ May 1 AND valid_from ≤ Apr 15 < valid_to
Single-axis systems can answer one or the other, never both. This is why Zep and Mem0 can't reconstruct historical model state — they don't track when they learned a thing.
Temporal queries
Pass temporal: { ... } to /v1/recall, /v1/answer, and the layer-read endpoints:
{
"temporal": {
"as_of": "2026-05-01T00:00:00Z",
"valid_during": { "from": "2026-04-01", "to": "2026-04-30" },
"natural": "last 30 days",
"reference_date": "2026-05-15T00:00:00Z"
}
}
| Field | Semantics |
|---|---|
| as_of | Clips both axes: recorded_* ≤ as_of AND valid_from ≤ as_of < valid_to |
| valid_during | Window on the world-time axis |
| recorded_during | Window on the ingest-time axis |
| natural | Parsed phrase (last week, this quarter, fiscal Q3, ...) |
| reference_date | Anchor for natural phrases; default = request time |
as_of and include_superseded apply conjunctively — as_of clips both axes; include_superseded=true additionally returns historical versions whose recorded_to ≤ as_of.
Supersession chains
When a new fact comes in about a (subject, predicate) already on file, the older fact's valid_to (and possibly recorded_to) is closed. The chain is preserved — query it with GET /v1/facts/timeline:
{
"subject": { "id": "ent_acme_corp" },
"predicate": "deal_stage",
"timeline": [
{ "value": "poc", "valid_from": "...", "valid_to": "2026-04-10T..." },
{ "value": "close", "valid_from": "2026-04-10T...", "valid_to": "2026-05-13T..." },
{ "value": "signed", "valid_from": "2026-05-13T...", "valid_to": null }
]
}
This is also what powers the "why do you think that?" trail on beliefs — supersession chains carry forward as evidence.
Natural-language parsing
Defaults shipped: today, yesterday, last week, this quarter, etc. Register tenant-specific phrases (e.g., "fiscal Q3", "holiday freeze") via POST /v1/temporal/phrases.