FalkorDB Knowledge Graph¶
FalkorDB is a Redis-compatible graph database that powers the Aegis knowledge graph via Graphiti.
Overview¶
- Image:
falkordb/falkordb:latest - Container:
falkordb - Protocol: Redis-compatible (port 6379)
- Web UI: Port 3001 (FalkorDB Browser)
- Storage: Named volume
falkordb_data - Network:
traefik_proxy
Architecture¶
┌─────────────────────────────────────────────┐
│ Aegis Memory System │
├─────────────────────────────────────────────┤
│ episodic_memory (PostgreSQL) │
│ ↓ │
│ TranscriptDigester (Python) │
│ ↓ │
│ GraphitiClient (Python) │
│ ↓ │
│ Graphiti-Core (Entity Extraction) │
│ ↓ │
│ FalkorDB (Graph Storage) │
│ - Entities (nodes) │
│ - Relationships (edges) │
│ - Episode metadata │
└─────────────────────────────────────────────┘
Configuration¶
Docker Compose¶
falkordb:
image: falkordb/falkordb:latest
container_name: falkordb
command: ["redis-server", "--loadmodule", "/var/lib/falkordb/bin/falkordb.so", "TIMEOUT", "30000"]
ports:
- "6379:6379" # Redis protocol
- "3001:3000" # Web UI
volumes:
- falkordb_data:/data
restart: unless-stopped
networks:
- traefik_proxy
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 30s
timeout: 10s
retries: 3
Command Options¶
--loadmodule /var/lib/falkordb/bin/falkordb.so- Load FalkorDB module into RedisTIMEOUT 30000- Query timeout (30 seconds)
Connection Details¶
- Host:
localhost(on host machine) - Host:
host.docker.internal(from containers) - Port:
6379 - Protocol: Redis wire protocol (RESP3)
Usage in Aegis¶
GraphitiClient¶
Location: /home/agent/projects/aegis-core/aegis/memory/graphiti_client.py
The GraphitiClient wraps Graphiti-Core to provide knowledge graph operations:
from aegis.memory.graphiti_client import GraphitiClient
# Initialize client
client = GraphitiClient()
await client.initialize()
# Add an episode (auto-extracts entities and relationships)
await client.add_episode(
name="deployment-event",
content="Deployed nginx service to production at 10.10.10.103",
source_description="deployment log"
)
# Search for entities (semantic search)
entities = await client.search_nodes("nginx deployment", limit=5)
# Search for facts/relationships
facts = await client.search_facts("deployed to production", limit=5)
Entity Extraction¶
Uses GLM-4.7 (via Z.ai) for LLM-based entity extraction:
Configuration:
Extracted entities: - People (engineers, users) - Systems (services, containers, hosts) - Actions (deployed, configured, tested) - Locations (servers, regions, networks) - Technologies (languages, frameworks, tools)
Embeddings¶
Uses Ollama nomic-embed-text for local embeddings:
Connection: http://host.docker.internal:11434 (Ollama on host)
Model: nomic-embed-text (768-dimensional vectors)
Purpose: Semantic search over entities and relationships
Reranking¶
Uses BGE Reranker v2-m3 for cross-encoder reranking:
Model: BAAI/bge-reranker-v2-m3 (568M params, multilingual)
Purpose: Improve search result relevance after semantic search
Alternatives:
- BAAI/bge-reranker-base (278M, faster but lower quality)
- BAAI/bge-reranker-large (560M, English-only)
Data Model¶
Graph Schema¶
FalkorDB stores a labeled property graph:
Nodes (Entities):
- Entity type with properties:
- uuid - Unique identifier
- name - Entity name (extracted from text)
- type - Entity type (Person, System, Action, etc.)
- created_at - Timestamp
- embedding - 768-dim vector (for semantic search)
Edges (Relationships):
- Typed relationships connecting entities:
- DEPLOYED_TO - System deployed to location
- CONFIGURED_BY - System configured by person
- USES - System uses technology
- RELATES_TO - Generic relationship
Episodes:
- Metadata nodes tracking original text:
- episode_id - Unique identifier
- name - Episode name (e.g., "deployment-event")
- content - Original text
- source - Source description
- timestamp - When episode occurred
Example Graph¶
After ingesting "Deployed nginx to production at 10.10.10.103":
[nginx:System] --DEPLOYED_TO--> [production:Location]
[nginx:System] --RUNS_ON--> [10.10.10.103:Host]
[deployment-event:Episode] --MENTIONS--> [nginx:System]
Transcript Digester¶
Automated ingestion of Claude sessions and journals into knowledge graph.
Source: Claude History¶
File: ~/.claude/history.jsonl
Format: JSONL with session commands
Processing: 1. Group commands by session ID 2. Extract entities from command text 3. Create episode per session with key events 4. Track file operations, git commands, code changes
Episode types: decision, implementation, error, learning
Source: Daily Journals¶
Files: ~/memory/journal/*.md
Format: Markdown with sections
Processing: 1. Parse journal into sections (## headers) 2. Each section becomes an episode 3. Extract entities from section content 4. Link related entities across sections
Episode types: milestone, research, general
Automated Ingestion¶
Cron Job: Daily at 3:00 AM UTC
crontab -l
# 0 3 * * * cd /home/agent/projects/aegis-core && /home/agent/projects/aegis-core/.venv/bin/python scripts/ingest_transcripts.py >> /home/agent/logs/ingest.log 2>&1
Manual execution:
cd /home/agent/projects/aegis-core
python scripts/ingest_transcripts.py --dry-run # Preview
python scripts/ingest_transcripts.py --stats # Show stats only
python scripts/ingest_transcripts.py --after 2026-01-01 # Filter by date
python scripts/ingest_transcripts.py # Full ingestion
MCP Integration¶
FalkorDB is accessed via MCP servers:
Memory MCP¶
Basic key-value storage over Redis protocol:
# Store entity
mcp__memory__store_entity(
entity_id="nginx-prod",
entity_type="service",
attributes={"host": "10.10.10.103", "status": "running"}
)
# Retrieve entity
entity = mcp__memory__get_entity(entity_id="nginx-prod")
Graphiti MCP¶
Graph operations via Graphiti-Core:
# Add episode with entity extraction
mcp__graphiti__add_episode(
name="api-deployment",
content="Deployed FastAPI dashboard to production",
source_description="deployment log"
)
# Search entities
entities = mcp__graphiti__search_nodes(
query="FastAPI dashboard production",
limit=5
)
# Search facts
facts = mcp__graphiti__search_facts(
query="deployed to production",
limit=10
)
Querying the Graph¶
Via Redis CLI¶
docker exec -it falkordb redis-cli
# List graphs
GRAPH.LIST
# Query graph (Cypher-like syntax)
GRAPH.QUERY aegis "MATCH (n:Entity) RETURN n LIMIT 10"
# Count entities
GRAPH.QUERY aegis "MATCH (n:Entity) RETURN count(n)"
# Find relationships
GRAPH.QUERY aegis "MATCH (a)-[r]->(b) RETURN a.name, type(r), b.name LIMIT 20"
Via Python¶
import redis
from redis.commands.graph import Graph
r = redis.Redis(host='localhost', port=6379, decode_responses=True)
graph = Graph(r, 'aegis')
# Execute Cypher query
result = graph.query("MATCH (n:Entity {type: 'System'}) RETURN n.name LIMIT 10")
for record in result.result_set:
print(record[0])
Via FalkorDB Browser¶
URL: http://localhost:3001 (when running on host)
Features: - Visual graph explorer - Cypher query editor - Schema visualization - Query profiling
Monitoring¶
Health Check¶
# Docker healthcheck
docker exec falkordb redis-cli ping
# Expected: PONG
# Check module loaded
docker exec falkordb redis-cli MODULE LIST
# Expected: name=graph
Memory Usage¶
Graph Statistics¶
from aegis.memory.graphiti_client import GraphitiClient
client = GraphitiClient()
await client.initialize()
# Get graph stats (via Cypher)
stats = await client.get_stats()
print(f"Entities: {stats['entity_count']}")
print(f"Relationships: {stats['relationship_count']}")
print(f"Episodes: {stats['episode_count']}")
Logs¶
docker logs falkordb -f
# Filter for errors
docker logs falkordb 2>&1 | grep -i error
# Filter for query slowness
docker logs falkordb 2>&1 | grep -i slow
Performance¶
Query Optimization¶
-
Indexes: Create indexes on frequently queried properties:
-
Limit results: Always use
LIMITfor large graphs: -
Filter early: Push filters into
MATCHclauses:
Memory Management¶
FalkorDB stores graph in RAM for fast access.
Monitor memory:
Flush graph (if needed, DESTRUCTIVE):
Persistence: Graphs are persisted to /data volume (AOF + RDB)
Backup and Restore¶
Backup¶
# Dump entire database
docker exec falkordb redis-cli --rdb /data/dump.rdb
# Copy to host
docker cp falkordb:/data/dump.rdb /home/agent/backups/falkordb-$(date +%Y%m%d).rdb
Restore¶
# Stop FalkorDB
docker stop falkordb
# Copy backup to volume
docker cp /home/agent/backups/falkordb-20260125.rdb falkordb:/data/dump.rdb
# Start FalkorDB
docker start falkordb
Export Graph¶
# Export to JSON
from aegis.memory.graphiti_client import GraphitiClient
client = GraphitiClient()
await client.initialize()
graph_data = await client.export_graph()
with open('graph_export.json', 'w') as f:
json.dump(graph_data, f, indent=2)
Troubleshooting¶
Connection refused¶
-
Check container is running:
-
Check port binding:
-
Test connection:
Module not loaded¶
Check FalkorDB module is loaded:
If missing, check command includes --loadmodule:
Out of memory¶
FalkorDB stores graph in RAM. If memory is exhausted:
-
Check memory usage:
-
Increase container memory limit:
-
Prune old episodes:
Slow queries¶
Enable query profiling:
Add indexes for common filters:
Development¶
Local Access¶
For development outside containers:
from aegis.memory.graphiti_client import GraphitiClient
# Configure to use localhost
import os
os.environ['FALKORDB_HOST'] = 'localhost'
os.environ['FALKORDB_PORT'] = '6379'
client = GraphitiClient()
await client.initialize()
Testing Graph Operations¶
# Test entity extraction
await client.add_episode(
name="test-episode",
content="Test entity extraction with nginx and PostgreSQL",
source_description="test"
)
# Verify entities created
entities = await client.search_nodes("nginx", limit=10)
for entity in entities:
print(f"{entity.name} ({entity.type})")
Schema Exploration¶
# Show all node labels
GRAPH.QUERY aegis "MATCH (n) RETURN DISTINCT labels(n)"
# Show all relationship types
GRAPH.QUERY aegis "MATCH ()-[r]->() RETURN DISTINCT type(r)"
# Show sample of each type
GRAPH.QUERY aegis "MATCH (n:Entity) RETURN n.type, count(*) GROUP BY n.type"
Related Documentation¶
- postgresql.md - Episodic memory source
- dashboard.md - Uses graph for semantic queries
- scheduler.md - Runs transcript ingestion job