ADR-0042: Graph Recall Architecture and Cognitive Traversals¶
| Field | Value |
|---|---|
| Status | Accepted (Implemented) |
| Date | 2026-08-20 |
| Authors | Spector Maintainers & Architecture Working Group |
| Deciders | Spector Technical Steering Committee (TSC) |
| Supersedes | None |
| Superseded By | None |
| Last Verified | 2026-09-16 (Verified against main) |
1. Context¶
Spector's Model Context Protocol (MCP) server in synapse/spector-mcp exposes cognitive memory operations to external agents and runtimes. Among these tools, MemoryGraphRecallTool provides multi-hop graph traversal across temporal facts and entity hyperedges to discover relational pathways between entities.
2. Problem Statement¶
An architectural audit of the MCP layer revealed a severe module boundary violation in MemoryGraphRecallTool:
- The class contained 570 lines of traversal engine code directly importing six internal memory subsystem classes:
EntityDirectory,HyperEntityGraphMemory,HyperEdge,HyperEdgeVertex,TemporalFact, andTemporalKnowledgeGraph. - It bypassed the public
SpectorMemoryAPI, drilling directly into raw subsystems viamemory.admin().entityDirectory(),memory.admin().hyperEntityGraph(), andmemory.admin().temporalKnowledgeGraph(). - It implemented its own ad-hoc Breadth-First Search (BFS) traversal engine, duplicating logic that already existed in
CognitiveGraphFacade. - Because traversal logic lived in the MCP presentation layer, other consumers (REST APIs, internal agents, CLI) could not reuse graph recall, and upcoming features like temporal supersession and conflict-aware recall would have to be duplicated across multiple modules.
3. Decision Drivers¶
- Module Encapsulation: The MCP layer must remain a thin presentation adapter; all graph traversal and cognitive reasoning must reside in
memory/spector-memory. - DRY Cognitive Traversals: Unify multi-hop BFS graph traversal inside
CognitiveGraphFacadeto benefit from caching (SpectorCache). - Clean Public API: Expose graph recall via typed options (
GraphRecallOptions) and results (GraphTraversalResult) onSpectorMemory. - Architectural Boundary Enforcement: Strictly prevent external layers from importing internal graph storage implementations.
4. Considered Options¶
Option 1: Status Quo (Keep Traversal in MemoryGraphRecallTool)¶
- Description: Leave BFS traversal engine inside the MCP tool class.
- Advantages: No immediate refactoring required.
- Disadvantages: Module boundary violation; logic inaccessible to non-MCP consumers; requires duplicate implementation for temporal supersession.
Option 2: Expose Raw Subsystems Publicly¶
- Description: Promote
HyperEntityGraphMemory,EntityDirectory, andTemporalKnowledgeGraphto the public API ofSpectorMemory. - Advantages: Allows external callers to inspect graph structures directly.
- Disadvantages: Leaks off-heap storage and threading details; breaks encapsulation; severely limits internal storage refactoring.
Option 3: Dedicated graphRecall() Service in CognitiveGraphFacade (Selected)¶
- Description: Relocate multi-hop BFS traversal into
CognitiveGraphFacade.graphRecall(...), expose a thin delegation method onSpectorMemory, reduceMemoryGraphRecallToolto an 80-line adapter, and enforce boundaries via ArchUnit tests. - Advantages: Clean encapsulation; reusable across all presentation layers; leverages internal caching; single location for temporal supersession logic.
- Disadvantages: Requires updating MCP tool call sites and tests.
5. Decision Outcome¶
Chosen Option: Option 3 (Dedicated graphRecall() Service in CognitiveGraphFacade).
Architectural Implementation:¶
Step 1: Add graphRecall() to CognitiveGraphFacade and SpectorMemory¶
CognitiveGraphFacade encapsulates multi-hop BFS traversal, entity resolution, and temporal fact filtering:
public final class CognitiveGraphFacade {
/**
* Multi-hop BFS traversal for GraphRAG — entity-centric path discovery
* across TemporalKnowledgeGraph facts and HyperEntityGraph co-occurrences.
*/
public GraphTraversalResult graphRecall(GraphRecallOptions options) {
// BFS traversal, caching, entity resolution, and temporal filtering
}
}
Exposed via thin delegation on SpectorMemory:
default GraphTraversalResult graphRecall(GraphRecallOptions options) {
return admin().graph().graphRecall(options);
}
Step 2: Slim Down MemoryGraphRecallTool to an Adapter (~80 Lines)¶
MemoryGraphRecallTool delegates entirely to SpectorMemory.graphRecall() and focuses purely on argument parsing and MCP text response formatting:
@Override
protected McpSchema.CallToolResult executeMemory(SpectorMemory memory,
Map<String, Object> args) {
GraphTraversalResult result = memory.graphRecall(
GraphRecallOptions.builder()
.startEntity(startEntityName)
.targetEntity(targetEntityName)
.maxHops(maxHops)
.entityTypeFilters(entityTypeFilters)
.relationTypeFilters(relationTypeFilters)
.topPaths(topPaths)
.includeMemories(includeMemories)
.build());
return textResult(formatResult(result));
}
Step 3: Restrict Internal Class Visibility and Enforce ArchUnit Rules¶
- Internal graph structures (
HyperEdge,HyperEdgeVertex) restricted to package-private visibility where feasible. - Automated ArchUnit architectural test ensures no classes in
com.spectrayan.spector.mcpimport internal packages (..memory.graph..,..memory.temporal..,..memory.hebbian..,..memory.index..).
Positive Consequences¶
- Restores clean hexagonal architecture: MCP layer is strictly an adapter.
- Graph traversal logic is reusable by REST endpoints, CLI tools, and autonomous agent loops.
- Unblocks temporal supersession features with zero changes required in the MCP layer.
- Traversal gains transparent acceleration and caching via
SpectorCache.
Negative Consequences & Trade-offs¶
- One-time refactoring of existing MCP graph recall integration tests.
6. Pros and Cons of the Options¶
| Option | Pros | Cons |
|---|---|---|
| Option 1: Traversal in MCP | Zero refactor | 570 LOC boundary leak, duplicate BFS logic, no caching |
| Option 2: Expose Raw Subsystems | Full external access | Leaks off-heap internals, locks in storage structures |
| Option 3: CognitiveGraphFacade (Selected) | Clean encapsulation, reusable, cached, ArchUnit-enforced | Minor refactoring across MCP tool classes |
7. Implementation Plan¶
- Phase 1: Author
GraphRecallOptionsandGraphTraversalResultdomain records incom.spectrayan.spector.memory.model. - Phase 2: Port multi-hop BFS traversal engine from
MemoryGraphRecallToolintoCognitiveGraphFacade.graphRecall(). - Phase 3: Add
graphRecall(GraphRecallOptions)default method toSpectorMemoryinterface. - Phase 4: Refactor
MemoryGraphRecallToolto delegate toSpectorMemory.graphRecall(). - Phase 5: Add ArchUnit test enforcing module boundaries between
spector-mcpand internal memory packages.
8. Code Reference & Verification¶
- Primary Module(s):
memory/spector-memory,synapse/spector-mcp - Key Packages:
com.spectrayan.spector.memory.graph,com.spectrayan.spector.mcp.tools - Classes:
CognitiveGraphFacade.java,SpectorMemory.java,MemoryGraphRecallTool.java,HyperEntityGraphMemory.java,TemporalKnowledgeGraph.java - Verification Tests:
CognitiveGraphFacadeTest.java,MemoryGraphRecallToolTest.java