A demonstration project showing how to build and use Context Graphs with Neo4j for AI-powered decision tracing in financial institutions.
Context Graphs are the infrastructure layer that enables AI agents to make enterprise-grade decisions. They capture decision traces - the tribal knowledge, exception logic, and reasoning that traditionally lives only in human experts' heads.
Key concepts:
- State Clock: What is true now (traditional databases)
- Event Clock: What happened, when, and why (context graphs)
- Decision Traces: Full reasoning, risk factors, confidence scores, and causal relationships
Ask questions about customers, decisions, and policies.
Visualize entities, decisions, and causal relationships.
Inspect reasoning, precedents, and causal chains.
User: "Should we approve a $50K credit line increase for John Smith?"
Agent:
1. Searches customer profile
2. Finds similar past decisions via FastRP embeddings
3. Cites relevant precedents
4. Makes recommendation with confidence score
5. Records decision trace with full reasoning
User: "Analyze account #12345 for fraud patterns"
Agent:
1. Uses FastRP embeddings to compare with known fraud typologies
2. Applies Node Similarity to find structural matches
3. Visualizes suspicious patterns in graph
4. Returns risk score with explanation
User: "We need to override the trading limit for XYZ Corp"
Agent:
1. Finds past exceptions and their outcomes
2. Traces causal chain of similar exceptions
3. Records exception with justification and precedent links
4. Links to applicable policies
This demo showcases three key differentiators of Neo4j for context graphs:
Neo4j is the natural substrate for context graphs - entities, decisions, and causal relationships map directly to nodes and relationships.
Graph Data Science algorithms provide structural/topological similarity that's impossible on Postgres without a PhD in graph theory:
- FastRP: 75,000x faster than node2vec, captures structural embeddings
- KNN: Find k-nearest neighbors based on graph structure
- Node Similarity: Compare neighborhood patterns (fraud detection)
- Louvain: Community detection for decision clusters
- PageRank: Influence scoring for decision impact
Combine semantic similarity (text embeddings) with structural similarity (FastRP) for hybrid search that understands both meaning and context.
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Next.js UI │────▶│ FastAPI + SDK │────▶│ Neo4j + GDS │
│ Chakra UI v3 │ │ Claude Agent │ │ Vector Search │
│ NVL Graphs │ │ 10 MCP Tools │ │ FastRP/KNN │
└─────────────────┘ └─────────────────┘ └─────────────────┘
- Python 3.11+ with uv package manager
- Node.js 18+
- Neo4j AuraDS instance (or local Neo4j Enterprise with GDS plugin)
- Anthropic API Key
- OpenAI API Key (for embeddings)
cd context-graph
# Create environment file
cat > .env << 'EOF'
# Neo4j Connection
NEO4J_URI=neo4j+s://xxxx.databases.neo4j.io
NEO4J_USERNAME=neo4j
NEO4J_PASSWORD=your_neo4j_password
# Anthropic API Key (for Claude Agent SDK)
ANTHROPIC_API_KEY=your_anthropic_key
# OpenAI API Key (for text embeddings)
OPENAI_API_KEY=your_openai_key
EOFcd backend
# Create virtual environment and install dependencies with uv
uv venv
uv pip install -e .cd backend
source .venv/bin/activate
export $(grep -v '^#' ../.env | xargs)
python scripts/generate_sample_data.pyThis creates:
- 200 persons
- 350 accounts
- 2000 transactions
- 600 decisions with causal chains
- 50 organizations
- 30 employees
- 15 policies
cd backend
source .venv/bin/activate
export $(grep -v '^#' ../.env | xargs)
uvicorn app.main:app --port 8000Backend runs at http://localhost:8000
cd frontend
npm install
npm run devFrontend runs at http://localhost:3000
When deploying to a multihomed environment, such as a cloud virtual machine, you will need to make a couple of changes. Open the file backend/app/main.py in your favorite text editor and locate the following code:
# CORS middleware for frontend
app.add_middleware(
CORSMiddleware,
allow_origins=[
"http://localhost:3000",
"http://127.0.0.1:3000",
"http://localhost:3001",
"http://127.0.0.1:3001",
"https://context-graph-demo.vercel.app",
],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
Change the URL "https://context-graph-demo.vercel.app" to reflect the public IP and port (3000) you use to access the frontend. If your backend is running, stop and restart it to pick up the change.
The second thing you will need to do is to set an environment variable before starting the frontend. You should set the variable NEXT_PUBLIC_API_URL to the public URL (including host and port) for the backend:
export NEXT_PUBLIC_API_URL="http://<public ip>:8000"
For the best experience with GDS algorithms:
- Create an AuraDS instance at https://console.neo4j.io
- Note the connection URI (format:
neo4j+s://xxxx.databases.neo4j.io) - Update your
.envwith the connection details
AuraDS includes all GDS algorithms (FastRP, KNN, Node Similarity, Louvain, PageRank) without additional configuration.
If you have a Neo4j Enterprise license:
docker-compose up -dWait for Neo4j to be ready at http://localhost:7474, then update .env:
NEO4J_URI=bolt://localhost:7687
NEO4J_USERNAME=neo4j
NEO4J_PASSWORD=password| Endpoint | Description |
|---|---|
GET /health |
Health check |
POST /api/chat |
Chat with AI agent |
POST /api/chat/stream |
Streaming chat with SSE |
GET /api/customers/search?query= |
Search customers |
GET /api/customers/{id} |
Get customer details |
GET /api/customers/{id}/decisions |
Get customer decisions |
GET /api/decisions |
List decisions |
GET /api/decisions/{id} |
Get decision details |
POST /api/decisions |
Create new decision |
GET /api/decisions/{id}/similar |
Find similar decisions |
GET /api/decisions/{id}/causal-chain |
Get causal chain |
GET /api/graph |
Get graph visualization data |
GET /api/graph/expand/{node_id} |
Expand node connections |
POST /api/graph/relationships |
Get relationships between nodes |
GET /api/graph/schema |
Get graph schema |
GET /api/graph/statistics |
Get graph statistics |
GET /api/policies |
List policies |
GET /api/policies/{id} |
Get policy details |
context-graph/
├── backend/
│ ├── app/
│ │ ├── main.py # FastAPI application
│ │ ├── agent.py # Claude Agent SDK with MCP tools
│ │ ├── context_graph_client.py # Neo4j operations
│ │ ├── gds_client.py # GDS algorithms
│ │ ├── vector_client.py # Vector search
│ │ └── models/ # Pydantic models
│ └── scripts/
│ └── generate_sample_data.py
├── frontend/
│ ├── app/ # Next.js pages
│ ├── components/
│ │ ├── ChatInterface.tsx # AI chat with inline graphs
│ │ ├── ContextGraphView.tsx # NVL visualization
│ │ └── DecisionTracePanel.tsx
│ └── lib/
│ └── api.ts # API client
├── cypher/
│ ├── schema.cypher # Neo4j schema
│ └── gds_projections.cypher # GDS algorithms
├── docker-compose.yml # Local Neo4j setup
└── .env # Environment variables
The Claude Agent has access to 10 custom tools:
| Tool | Description |
|---|---|
search_customer |
Search customers by name, email, account number |
get_customer_decisions |
Get all decisions about a customer |
find_similar_decisions |
FastRP-based structural similarity search |
find_precedents |
Semantic + structural precedent search |
get_causal_chain |
Trace causes and effects of a decision |
record_decision |
Create new decision trace with reasoning |
detect_fraud_patterns |
Graph-based fraud analysis |
get_policy |
Get current policy rules |
execute_cypher |
Read-only Cypher for custom analysis |
get_schema |
Retrieve the current Neo4j schema |
Person- Customer/employee with FastRP embeddingAccount- Bank/trading accounts with risk tiersTransaction- Financial transactions with fraud scoresOrganization- Companies with sanctions status
Decision- Core decision with reasoning, confidenceDecisionContext- State snapshot at decision timePrecedent- Links to similar past decisionsPolicy- Rules governing decisionsException- Documented exceptions
(:Decision)-[:CAUSED]->(:Decision)
(:Decision)-[:INFLUENCED]->(:Decision)
(:Decision)-[:PRECEDENT_FOR]->(:Decision)
(:Decision)-[:ABOUT]->(:Person|:Account|:Transaction)
(:Decision)-[:APPLIED_POLICY]->(:Policy)
(:Decision)-[:GRANTED_EXCEPTION]->(:Exception)
CALL gds.fastRP.mutate('decision-graph', {
embeddingDimension: 128,
iterationWeights: [0.0, 1.0, 1.0, 0.8, 0.6],
mutateProperty: 'fastrp_embedding'
})// Find decisions similar in both meaning and graph structure
CALL db.index.vector.queryNodes('decision_semantic_idx', 10, $query_embedding)
YIELD node, score AS semantic_score
WITH node, semantic_score
CALL db.index.vector.queryNodes('decision_fastrp_idx', 10, node.fastrp_embedding)
YIELD node AS similar, score AS structural_score
RETURN similar, (semantic_score + structural_score) / 2 AS combined_score
ORDER BY combined_score DESC- AI's Trillion-Dollar Opportunity: Context Graphs - Foundation Capital
- Claude Agent SDK
- NVL Visualization Library
MIT



