Graphiti: A Temporal Graph for What Was True When
Stand up the bi-temporal context-graph engine behind Zep on a local FalkorDB, with indices built and ready for episodes.
Run this workflow
CI-verified, 2/2 fixtures passing.
Build this with your agent
One copy-paste hands Claude Code, Codex, or Cursor the full recipe, steps included, nothing to fetch.
Intended Use
Tracking facts that change over time: Graphiti invalidates rather than deletes, so 'what was true last month' is queryable. CI starts a real FalkorDB container, installs graphiti-core, connects, and builds indices and constraints, none of which needs a model (a dummy key proves it). Ingesting episodes runs an LLM, OpenAI by default, so it's fenced.
Not for
- Setups without a graph database, Graphiti needs one (FalkorDB is the one-command Docker option)
- Expecting CI to verify episode ingestion, that's the model-driven step
The Stack
Tested Against
graphiti-core@latestfalkordb@latest (Docker)python@3.12Side effects & data flow
- Network
- PyPI + Docker Hub, install only
- Writes
- ./.venv/, a throwaway FalkorDB container
- Credentials
- LLM key, for the fenced episode-ingest step only
Prerequisites
- Docker
- Python 3.10+
- An OpenAI (or compatible) key for the fenced ingest step
Steps
- 1
Start FalkorDB, install graphiti-core, connect, and build indices
FalkorDB runs in one Docker command. CI then installs graphiti-core[falkordb], waits for the port, connects with FalkorDriver, and builds indices and constraints. A deliberately-dummy OPENAI_API_KEY proves no model is involved in this spine. The container is torn down either way.
docker rm -f wf-falkordb >/dev/null 2>&1 || true docker run -d --name wf-falkordb -p 16379:6379 falkordb/falkordb:latest python3 -m venv .venv .venv/bin/pip install -q "graphiti-core[falkordb]" OPENAI_API_KEY="dummy-key-proves-no-model-call" .venv/bin/python - <<'EOF' import asyncio, socket, time # wait for FalkorDB to accept connections for _ in range(30): try: socket.create_connection(("localhost", 16379), timeout=1).close() break except OSError: time.sleep(1) else: raise SystemExit("FalkorDB never came up on :16379") from graphiti_core import Graphiti from graphiti_core.driver.falkordb_driver import FalkorDriver async def main(): g = Graphiti(graph_driver=FalkorDriver(host="localhost", port=16379)) await g.build_indices_and_constraints() print("graphiti OK: connected to FalkorDB and built indices (no model call)") asyncio.run(main()) EOF rc=$? docker rm -f wf-falkordb >/dev/null 2>&1 || true exit $rc - 2
Ingest episodes (the model step, not checked by CI)
Add episodes with a real key and Graphiti extracts entities and relations with an LLM (OpenAI by default, best with structured-output models). Non-deterministic, so CI never claims it.
Eval, 2 fixtures
Last passed: verified todayindices-builtcontainstimeout 900s · max $0Expected:
graphiti OK: connected to FalkorDB and built indices (no model call)clean-exitexit_codetimeout 900s · max $0Expected:
0
Results
Bi-temporal facts: when a fact changes the old one is invalidated, not deleted, so you can query any past point in time.
Did this work for you?
Our CI checks the setup runs. You tell us if the whole thing worked. Tell us straight.
Liked this workflow?
Get new verified workflows in WebAfterAI, three issues a week (Tue, Thu, Sat).