CortexDB Docs
Core Concepts

Bi-temporal Model

How CortexDB tracks two independent time axes — when something was true in the world, and when the system learned it.

CortexDB records two time axes on every derived record, so you can ask both "what was true on 2026-04-15?" and "what did we know on 2026-04-15?"

  • Valid timevalid_from / valid_to: when the fact was true in the world.
  • Recorded timerecorded_from / recorded_to: when CortexDB learned it.

null on a *_to field means "open / still current." Events carry only observed_at and recorded_at; the four-field bi-temporal shape appears on derived layers (Facts, Beliefs, …).

Querying a point in time

Pass a temporal block to /v1/recall, /v1/answer, or the layer-read endpoints:

{
  "scope": "org:acme/dept:eng/user:alice",
  "query": "seat count",
  "temporal": {
    "as_of": "2026-04-15T00:00:00Z",
    "natural": "last 30 days",
    "reference_date": "2026-05-01T00:00:00Z"
  }
}

valid_during / recorded_during are 2-element arrays

Range filters take a two-element array [start, end], not an object. This is enforced — an object returns 422 INVALID_BODY: "invalid type: map, expected an array of length 2".

// correct
"valid_during": ["2026-04-01T00:00:00Z", "2026-04-30T00:00:00Z"]

// WRONG → 422
"valid_during": { "from": "2026-04-01", "to": "2026-04-30" }

Dates may be RFC-3339 datetimes or YYYY-MM-DD (end date inclusive). Applies to recorded_during too.

Supersession

When a newer fact arrives for the same (subject, predicate), the prior fact's valid_to (or recorded_to) closes rather than being overwritten — the full history is retained. Walk it with GET /v1/facts/timeline.

Verified against v0.9.9

temporal.as_of, temporal.natural, and temporal.reference_date all accepted (200); the array-shape rule confirmed live. See ../CORTEXDB_DOCS_AUDIT.md for the repro.

On this page