Building Production Agent Memory with Neo4j: The Constitutional Graph Pattern
Most agent memory tutorials use vector databases. This is a guide for building with Neo4j instead — and why it matters for production autonomous agents.
Why Graph > Vector for Agent Memory
Vectors are great for "find me something similar to X." But agent memory has different requirements:
What agents actually ask:
- "Has this action already been taken?" → Exact match, not similarity
- "What led to this decision?" → Graph traversal
- "Is this agent authorized for this?" → Authority lookup
- "What is the temporal context here?" → Time-aware traversal
These are all native graph operations. They're awkward in vector space.
The 6-Layer Constitutional Ontology
After building this in production (ODEI, Jan 2026), here's the schema that works:
// Core layers
CREATE CONSTRAINT ON (n:Foundation) ASSERT n.id IS UNIQUE;
CREATE CONSTRAINT ON (n:Vision) ASSERT n.id IS UNIQUE;
CREATE CONSTRAINT ON (n:Strategy) ASSERT n.id IS UNIQUE;
CREATE CONSTRAINT ON (n:Tactics) ASSERT n.id IS UNIQUE;
CREATE CONSTRAINT ON (n:Execution) ASSERT n.id IS UNIQUE;
CREATE CONSTRAINT ON (n:Track) ASSERT n.id IS UNIQUE;
// Relationships
// PURSUES_GOAL, BLOCKS, INFORMS, PART_OF, ASSIGNED_TO, TRACKS
Layer purposes:
- FOUNDATION — who are we, what do we value, who do we trust
- VISION — where are we going
- STRATEGY — how are we getting there
- TACTICS — what are we doing this week
- EXECUTION — what are we doing right now
- TRACK — how are we doing
The Constitutional Write Pattern
Before every write to the graph, run these checks:
// 1. Check immutability
MATCH (n {id: $id}) WHERE n.immutable = true RETURN n
// 2. Check referential integrity
MATCH (n {id: $ref_id}) RETURN count(n) as exists
// 3. Check deduplication
MATCH (e:Execution {hash: $action_hash}) RETURN count(e) as count
// 4. Check authority
MATCH (a:Agent {id: $agent_id})-[:HAS_SCOPE]->(s:Scope {name: $action_type})
RETURN count(s) as authorized
If any check fails: reject. If suspicious: escalate. If all pass: write.
Production Stats (91-Node Graph, 2 Months)
Running this at https://api.odei.ai since January 2026:
- 91 nodes across 6 layers
- 91 relationship types
- 0 hallucination errors (referential integrity catches them)
- 0 duplicate writes (deduplication layer)
- ~15% fewer harmful actions vs no-validation baseline
The Temporal Pattern
Every node gets createdAt and optional expiresAt:
CREATE (n:Task {
id: randomUUID(),
title: "Deploy guardrails",
createdAt: datetime(),
expiresAt: datetime({days: 7}), // optional
status: "pending"
})
Query at a point in time:
MATCH (n)
WHERE n.createdAt <= $timestamp
AND (n.expiresAt IS NULL OR n.expiresAt > $timestamp)
RETURN n
Making It Available to Agents
Option 1: REST API
# Get full graph state
curl https://api.odei.ai/api/v2/world-model/live
# Constitutional validation
curl -X POST https://api.odei.ai/api/v2/guardrail/check \
-d '{"action": "...", "severity": "high"}'
Option 2: MCP Server (Claude)
{
"mcpServers": {
"odei": {"command": "npx", "args": ["@odei/mcp-server"]}
}
}
Further Reading
- Architecture: https://github.com/odei-ai/web/blob/main/docs/architecture.md
- Research paper: https://github.com/odei-ai/research
- API: https://api.odei.ai/integrate/
Running in production at api.odei.ai — Virtuals ACP Agent #3082
Top comments (0)