Skip to main content
A minimal guide to Cognee’s temporal mode. Use it when your data contains dates and you want to ask time-scoped questions — before, after, or between two points in time — answered from an event timeline rather than embedding similarity alone.

Before You Start

  • Complete Quickstart to understand basic operations
  • Ensure you have LLM Providers configured
  • Read Recall for how querying memory works
  • No data is required up front — the script ingests its own dated sample text, but it starts with cognee.forget(everything=True), which wipes all existing Cognee data; run it against a setup you can afford to reset

Code in Action

What Just Happened

Step 1: Remember Data with Temporal Mode

The script starts from a clean state, then ingests TEXT into the timeline_demo dataset. Because temporal_cognify=True, remember() extracts events and timestamps and builds the timeline during ingestion, so there is no separate cognify() step. This example uses one string treated as a single document; multiple documents, files, or entire datasets are processed the same way.

Step 2: Ask Time-aware Questions

The loop runs the three query shapes temporal mode is built for — a before query, an after query, and one bounded by a pair of dates — using SearchType.TEMPORAL, imported from the cognee package at the top of the script. Each call is scoped with datasets=["timeline_demo"] so it only searches the timeline it just ingested; drop the argument to search every dataset you have access to. The answer for each query is results[0].text.
  • If the query has clear dates, the retriever filters events by time and ranks them
  • If no dates are detected, it falls back to event or entity retrieval and still answers
  • Increase top_k to inspect more candidate events

How Events and Timestamps Are Stored

Temporal ingestion adds three DataPoint types to the graph: An event is anything that happened in time: a dated milestone, but also any action or verb in the text — so a few sentences typically yield many events. Each extracted event is attached to its source chunk through the chunk’s contains edge, and the entities mentioned in it become Entity nodes linked to the event by the relationship the extractor found (for example transferred_to). How time attaches depends on what the text gives:
  • A single moment → the event points at one Timestamp node through at.
  • A span → the event points at an Interval through during, and the interval points at a start and an end Timestamp.
  • Only the year is mandatory in a timestamp. Unknown month and day default to 1, and unknown hour, minute, and second to 0, so "In 2001 version 1.0 shipped" is stored as 2001-01-01 00:00:00.
  • A Timestamp node’s id is derived from its time_at value, so every event resolving to the same instant shares one timestamp node. Resolved times are also appended to the event description as a Time data: ... line, which is what the answer is generated from.
At query time the retriever turns your question into a time range, matches Timestamp nodes whose time_at falls inside it, and collects the events within two hops of those nodes — one hop for at, two for during. Those candidates are then ranked by embedding similarity to your query and cut to top_k.

Relative and vague time expressions

Extraction only timestamps events it can place on a calendar. A phrase such as “when I was young, I loved running” or “when I was at primary 2, I transferred school” still produces an Event node with its entities and its chunk link, but with no at or during — and therefore no Timestamp node:
  • The event remains fully retrievable through event and entity search, including the fallback path inside SearchType.TEMPORAL.
  • It is invisible to time-range filtering, so a “before 2005” query will not surface it.
On the query side, the time range is resolved against the current UTC date, so references like “today” or “now” resolve to a concrete bound. A phrase with no calendar anchor leaves both bounds unset; the retriever then logs that no timestamps were identified and falls back to triplet search over events and entities, which is also what happens when a range does resolve but no events fall inside it.
To make a relative phrase queryable by time, give the calendar date in the ingested text — "In 2003, when I was in primary 2, I transferred school" produces an event anchored to 2003, while the bare phrase does not.

Using the HTTP API

If your server is running, you can run temporal search via the API by setting search_type to "TEMPORAL":
The Python example above is still the easiest way to enable temporal ingestion because it lets you pass temporal_cognify=True directly to remember().

Full Examples

Additional examples about temporal awareness are available on our GitHub.
  • An advanced script running temporal search over real documents is on our GitHub. Instead of the inlined four-sentence timeline above, it ingests two bundled biographies as separate documents with temporal_cognify=True, then mixes before / after / between range queries with person-centric questions that carry no dates — exercising the entity-retrieval fallback described in the tip above.

Fact Validity

Close superseded facts and check staleness with is_valid()

Core Concepts Overview

Understand how Cognee builds and stores knowledge graphs.

API Reference

Explore the search endpoint behind temporal queries.