Skip to main content

Introduction to Temporal Knowledge

Most knowledge graphs treat time as a simple timestamp—when a fact was added to the database. Graphiti takes a more sophisticated approach with a bi-temporal model that distinguishes between:
  1. Valid Time: When a fact was true in the real world
  2. Transaction Time: When the system learned about the fact
This dual perspective enables accurate point-in-time queries and proper handling of late-arriving information.

The Bi-Temporal Model

Graphiti implements bi-temporality through two sets of timestamps on edges and nodes:

Valid Time Dimension

Tracks when facts were actually true in the real world:
Example: “Kamala Harris served as California Attorney General from 2011 to 2017”
  • valid_at: January 3, 2011
  • invalid_at: January 3, 2017

Transaction Time Dimension

Tracks when the system learned about facts:
Example: You add the Attorney General fact on March 15, 2025
  • created_at: March 15, 2025
  • expired_at: None (edge is still current in the graph)
The distinction between valid time and transaction time allows Graphiti to answer questions like “What did the system know about X on date Y?” versus “What was actually true about X on date Y?”

Why Bi-Temporality Matters

Handling Contradictions

When new information contradicts existing knowledge, Graphiti invalidates old edges without deleting them:
Graphiti uses temporal edge invalidation rather than deletion, preserving the complete history of what the system knew and when.

Late-Arriving Information

Bi-temporality elegantly handles information that arrives out of chronological order:
This separation allows:
  • Historical accuracy: Query “Who worked at Acme in 2020?” → Correct answer: Alice
  • Audit trails: Query “What did we know on March 1, 2025?” → We didn’t know about Alice yet

Temporal Queries

Graphiti’s temporal model enables sophisticated queries:

Point-in-Time Retrieval

Find facts that were valid at a specific time:

Time Range Queries

Find all facts valid during a period:

Recent Updates Query

Find what the system learned recently:

Temporal Data on Nodes

Episodic Nodes

Episodes have both dimensions of time:
Example: Processing a 2020 email in 2025

Entity Nodes

Entities only track transaction time (when first created):
Why? Because entities represent persistent objects that can have multiple changing relationships over time. The temporal validity is tracked at the edge level, not the node level.

Episode Time vs Edge Time

Understanding the relationship between episode time and edge time is crucial:
The reference_time parameter in add_episode() becomes the valid_at timestamp for extracted edges. This ensures that facts are temporally anchored to when they occurred, not when they were processed.

Temporal Edge Invalidation

When Graphiti detects contradictory information, it uses temporal invalidation:

How It Works

  1. New episode arrives with contradicting information
  2. LLM analyzes the contradiction during edge resolution (see graphiti_core/utils/maintenance/edge_operations.py:484)
  3. Old edge is updated:
    • invalid_at ← new fact’s valid_at
    • expired_at ← current timestamp
  4. New edge is created with the updated information

Code Example from Source

Real-World Example

Temporal Awareness in Retrieval

Graphiti’s search automatically considers temporal validity:

Implementation Details

Timestamp Sources

Date Parsing

Graphiti uses parse_db_date() to handle various database date formats:
This ensures consistent temporal handling across Neo4j, FalkorDB, Kuzu, and Neptune backends.

Best Practices

1. Always Set reference_time Accurately

2. Use Temporal Filters for Historical Queries

When you need point-in-time information, always use SearchFilters:

3. Preserve Episode Metadata

When processing documents, preserve original timestamps:

Comparison with Other Systems

Graphiti’s bi-temporal model is particularly valuable for AI agents that need to reason about how knowledge evolved over time and handle late-arriving or contradictory information gracefully.

Next Steps

Episodes

Learn how episodes carry temporal information

Nodes and Edges

Explore the complete graph schema

Search & Retrieval

Use temporal filters in search queries

Add Episodes

Set reference_time correctly when adding data