Skip to content

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 Redis
  • TIMEOUT 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:

# Uses environment variables:
# - ZAI_API_KEY
# - ZAI_BASE_URL=https://api.z.ai/api/anthropic

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

docker exec falkordb redis-cli INFO memory

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

  1. Indexes: Create indexes on frequently queried properties:

    GRAPH.QUERY aegis "CREATE INDEX ON :Entity(name)"
    GRAPH.QUERY aegis "CREATE INDEX ON :Entity(type)"
    

  2. Limit results: Always use LIMIT for large graphs:

    MATCH (n:Entity) RETURN n LIMIT 100
    

  3. Filter early: Push filters into MATCH clauses:

    # Good
    MATCH (n:Entity {type: 'System'}) WHERE n.name CONTAINS 'nginx'
    
    # Bad
    MATCH (n:Entity) WHERE n.type = 'System' AND n.name CONTAINS 'nginx'
    

Memory Management

FalkorDB stores graph in RAM for fast access.

Monitor memory:

docker stats falkordb

Flush graph (if needed, DESTRUCTIVE):

docker exec falkordb redis-cli GRAPH.DELETE aegis

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

  1. Check container is running:

    docker ps | grep falkordb
    

  2. Check port binding:

    netstat -tlnp | grep 6379
    

  3. Test connection:

    redis-cli -h localhost -p 6379 ping
    

Module not loaded

Check FalkorDB module is loaded:

docker exec falkordb redis-cli MODULE LIST

If missing, check command includes --loadmodule:

docker inspect falkordb | jq '.[0].Config.Cmd'

Out of memory

FalkorDB stores graph in RAM. If memory is exhausted:

  1. Check memory usage:

    docker exec falkordb redis-cli INFO memory
    

  2. Increase container memory limit:

    falkordb:
      deploy:
        resources:
          limits:
            memory: 4G
    

  3. Prune old episodes:

    GRAPH.QUERY aegis "MATCH (e:Episode) WHERE e.timestamp < '2025-01-01' DELETE e"
    

Slow queries

Enable query profiling:

GRAPH.PROFILE aegis "MATCH (n:Entity)-[r]->(m) RETURN n, r, m LIMIT 10"

Add indexes for common filters:

GRAPH.QUERY aegis "CREATE INDEX ON :Entity(type)"
GRAPH.QUERY aegis "CREATE INDEX ON :Entity(name)"

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"