Note
This originated as a hackathon project. Inspired by Animesh Koratana's post.
AI agents can read documents, but they can't reason about how those documents change over time.
When your company updates its remote work policy from 2 days to 3 days per week, a typical RAG system treats both versions as equally true. It can't tell you what the policy was last March. It doesn't notice the contradiction. It has no idea which source to trust.
Context Graph solves this by extending knowledge graphs with three things traditional triples lack: when a fact was valid, where it came from, and what happens when facts conflict.
Knowledge graphs store facts as triples: (Remote Work, ALLOWS, 2 days per week). This works until you ingest a second document that says (Remote Work, ALLOWS, 3 days per week). Now you have two contradictory facts and no way to know:
- Which one is current?
- When did the change happen?
- Which source is more authoritative?
- What was true at a specific point in the past?
For AI agents operating in enterprise environments -- where policies change, regulations get updated, and multiple sources disagree -- this is a fundamental gap. The agent needs situational awareness, not just facts.
Context Graph replaces triples with contextual quadruples: the same (head, relation, tail) fact, plus a metadata envelope that tracks confidence, temporal validity, provenance, and lifecycle status.
(Remote Work, ALLOWS, 3 days per week)
+ confidence: 0.95
+ valid_from: 2024-01-01
+ source: HR Handbook v2024
+ status: ACTIVE
+ supersedes: "2 days per week" (from HR Handbook v2023, now marked SUPERSEDED)
This enables three capabilities that standard knowledge graphs can't provide:
Ask what was true at any point in time. The graph returns only facts that were valid at that timestamp, including facts that have since been superseded.
Query: "What is the remote work policy?" (as of 2023-06-15)
Answer: "2 days per week" (from HR Handbook v2023)
Query: "What is the remote work policy?" (as of 2024-06-15)
Answer: "3 days per week" (from HR Handbook v2024)
When new facts are ingested, the engine checks them against existing knowledge and classifies conflicts:
| Conflict Type | Example |
|---|---|
| Value Conflict | PTO changed from 15 to 20 days, overlapping validity windows |
| Direct Contradiction | One policy ALLOWS remote work, another PROHIBITS it |
| Supersession | Document explicitly states "supersedes March 2024 policy" |
| Temporal Overlap | Same fact from two sources with overlapping validity |
Conflicts are resolved automatically using configurable strategies: recency wins (default), confidence wins, branch as disputed (keep both for human review), or manual review.
The CGR3 (Retrieve-Rank-Reason) pipeline answers questions by:
- Retrieving relevant facts via multi-hop graph traversal
- Ranking them by a composite score:
(0.3 x recency) + (0.4 x confidence) + (0.3 x authority) - Reasoning over the ranked facts using chain-of-thought (via DSPy)
Recency uses exponential decay (365-day half-life). Authority is inferred from source type (official policy > regulation > guideline > informal). Disputed facts are penalized with a 0.7x multiplier.
┌──────────────────────────────────────────────────────────────┐
│ Ingestion Pipeline │
│ ┌──────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ Chunker │→ │ Entity │→ │ Relation │→ │ Conflict │ │
│ │ │ │ Extractor │ │ Extractor │ │ Resolver │ │
│ │ (text, │ │ (DSPy + │ │ (DSPy + │ │ (rule- │ │
│ │ markdown)│ │ GPT-4o) │ │ GPT-4o) │ │ based) │ │
│ └──────────┘ └───────────┘ └───────────┘ └───────────┘ │
├──────────────────────────────────────────────────────────────┤
│ Storage Layer │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ FalkorDB (Redis-based graph database, OpenCypher) │ │
│ │ Entity nodes + relationship edges with temporal │ │
│ │ validity, provenance, confidence, lifecycle status │ │
│ └────────────────────────────────────────────────────────┘ │
├──────────────────────────────────────────────────────────────┤
│ CGR3 Reasoning Pipeline │
│ ┌──────────┐ ┌───────────┐ ┌──────────┐ │
│ │ Retrieve │→ │ Rank │→ │ Reason │ │
│ │ (multi- │ │ (recency, │ │ (DSPy │ │
│ │ hop) │ │ authority)│ │ CoT) │ │
│ └──────────┘ └───────────┘ └──────────┘ │
└──────────────────────────────────────────────────────────────┘
- Python 3.10+
- Docker (for FalkorDB)
- uv package manager
- OpenAI API key
git clone https://github.com/williebsweet/context-graph.git
cd context-graph
uv sync
# Start FalkorDB
docker run -d --name falkordb -p 6379:6379 falkordb/falkordb
# Configure environment
cp .env.example .env
# Edit .env with your OpenAI API keyuv run python scripts/demo_interactive.pyWalk through a conflict detection scenario:
context-graph> load hr_policy_2023 # Load 2023 HR policies (4 facts)
context-graph> show # See what's in the graph
context-graph> load hr_policy_2024 # Load 2024 policies — conflicts detected!
context-graph> conflicts # Inspect the 4 value conflicts
context-graph> query "Remote Work" 2023-06-15 # → "2 days per week"
context-graph> query "Remote Work" 2024-06-15 # → "3 days per week"
context-graph> reset # Clear and start over
Other commands: create (build a dataset interactively), load <file> (load any JSON dataset), export <file>, status, help.
uv run python scripts/demo_conflict_resolution.pyIngests two versions of a travel policy, detects conflicts, resolves them with the recency-wins strategy, and runs temporal queries — all non-interactively.
uv run python scripts/web_demo.py
# Open http://localhost:8000Load datasets, view facts, ask questions, inspect disputes, and switch resolution strategies through a browser UI.
from datetime import datetime
from context_graph.config import Settings
from context_graph.storage.client import FalkorDBClient
from context_graph.extraction.pipeline import ContextFactory
from context_graph.reasoning.reasoner import CGR3Engine
# Connect
settings = Settings()
client = FalkorDBClient(settings)
client.connect()
# Ingest a document
factory = ContextFactory(client, settings)
result = factory.ingest("path/to/policy.txt", {"title": "HR Handbook 2024"})
print(f"{result.relationships_added} facts extracted, {result.conflicts_found} conflicts detected")
# Ask a temporal question
engine = CGR3Engine(client, settings)
answer = engine.query(
question="What is the remote work policy?",
valid_at=datetime(2024, 6, 15),
)
print(f"{answer.answer} (confidence: {answer.confidence})")
client.close()Create your own datasets as JSON files in the datasets/ directory:
{
"name": "HR Policy 2024",
"effective_date": "2024-01-01",
"source_uri": "policies/hr_handbook_2024.pdf",
"facts": [
{
"head": "Remote Work",
"head_label": "Policy",
"relation": "ALLOWS",
"tail": "3 days per week",
"tail_label": "Value",
"confidence": 0.95,
"excerpt": "Employees may work remotely up to 3 days per week."
}
]
}Included datasets: hr_policy_2023.json, hr_policy_2024.json (conflicts with 2023), security_policy.json, and text-based remote work policies across three versions.
src/context_graph/
├── models/ # Pydantic schemas: Entity, Source, Evidence, ContextualQuadruple
├── extraction/ # DSPy signatures, document chunking, ingestion pipeline
├── storage/ # FalkorDB client, CRUD repository, conflict detection/resolution
└── reasoning/ # Graph retriever, evidence ranker, CGR3 reasoning engine
scripts/ # Interactive CLI demo, automated demo, web demo
datasets/ # Sample policy documents (JSON and plain text)
tests/ # Unit tests (models, chunker, ranker) and integration tests
uv run pytest tests/unit/ # Unit tests (no database required)
uv run pytest tests/integration/ # Integration tests (requires FalkorDB)
uv run ruff check . # Lint
uv run ruff format . # Format| Component | Technology | Role |
|---|---|---|
| LLM orchestration | DSPy | Structured extraction and chain-of-thought reasoning via typed signatures |
| Graph database | FalkorDB | Redis-based graph store with OpenCypher queries |
| Data validation | Pydantic | Schemas for quadruples, provenance, and configuration |
| Web demo | FastAPI | Interactive browser UI for exploration |
| Package management | uv | Fast dependency resolution and virtual environments |
| Variable | Default | Description |
|---|---|---|
OPENAI_API_KEY |
(required) | OpenAI API key for GPT-4o extraction and reasoning |
FALKORDB_HOST |
localhost |
FalkorDB hostname |
FALKORDB_PORT |
6379 |
FalkorDB port |
MIT