Doramagic Project Pack · Human Manual
genesys
Genesys is an intelligence layer for AI memory — a scoring engine, causal graph, and lifecycle manager for AI agent memory. It provides persistent memory capabilities with intelligent forg...
Getting Started with Genesys
Related topics: Configuration Guide, Storage Backend Comparison
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Configuration Guide, Storage Backend Comparison
Getting Started with Genesys
Overview
Genesys is an intelligence layer for AI memory — a scoring engine, causal graph, and lifecycle manager for AI agent memory. It provides persistent memory capabilities with intelligent forgetting, ensuring AI systems maintain context across sessions without unbounded memory growth.
The system speaks MCP (Model Context Protocol) natively, making it compatible with Claude Code, Claude Desktop, and any MCP-compatible AI client.
Key capabilities:
- Multi-force memory scoring (relevance × connectivity × reactivation)
- Causal graph relationships between memories
- Intelligent forgetting — memories decay and are pruned when irrelevant
- Core memory promotion for structurally important information
- Multiple storage backends (in-memory, Postgres, Obsidian, FalkorDB)
- Hybrid retrieval (vector + keyword + graph spreading activation)
Sources: README.md
Sources: README.md
System Architecture
Related topics: Memory Scoring Engine, Memory Lifecycle Management, Nodes and Edges Data Models
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Memory Scoring Engine, Memory Lifecycle Management, Nodes and Edges Data Models
System Architecture
Overview
Genesys is a scoring engine, causal graph, and lifecycle manager for AI agent memory. It implements a sophisticated memory management system that enables AI agents to store, retrieve, and intelligently forget information over time. The system speaks MCP (Model Context Protocol) natively, allowing seamless integration with Claude Desktop and Claude Code.
Sources: README.md
High-Level Architecture
The Genesys system is organized into several interconnected layers:
graph TB
subgraph "Client Layer"
ClaudeDesktop["Claude Desktop"]
ClaudeCode["Claude Code"]
MCPSDK["MCP SDK"]
end
subgraph "API Layer"
Server["MCP Server (stdio)"]
Tools["MCP Tools"]
end
subgraph "Core Engine"
Scoring["Scoring Engine"]
Lifecycle["Lifecycle Manager"]
LLMProvider["LLM Provider"]
end
subgraph "Storage Layer"
MemoryBackend["In-Memory"]
Postgres["Postgres + pgvector"]
Obsidian["Obsidian Vault"]
FalkorDB["FalkorDB"]
end
ClaudeDesktop & ClaudeCode --> MCPSDK
MCPSDK --> Server
Server --> Tools
Tools --> Scoring
Scoring --> Lifecycle
Scoring --> LLMProvider
Lifecycle --> MemoryBackend & Postgres & Obsidian & FalkorDBSources: server.json:1-30 | src/genesys_memory/server.py:1-20
Component Architecture
MCP Server Layer
The MCP Server is the primary interface for client applications. It uses stdio transport for communication, making it suitable for desktop integration.
| Component | Description | Source |
|---|---|---|
app | Main MCP Server instance | server.py:20 |
providers | Storage and tool providers | server.py:24 |
_TOOL_DISPATCH | Tool method routing table | server.py:30-45 |
The server initializes providers and tools via get_providers():
providers = get_providers()
tools = providers.tools
Sources: src/genesys_memory/server.py:23-27
MCP Tools Interface
The MCP protocol exposes a set of tools that provide the primary interface for memory operations:
| Tool | Description | Required Args |
|---|---|---|
memory_store | Store a new memory with optional causal links | content |
memory_recall | Hybrid search using vector + keyword + graph | query |
memory_search | Filtered search by status, category, date | query |
memory_traverse | Graph traversal from a starting node | node_id |
memory_explain | Explain memory score breakdown | node_id |
memory_stats | Get graph statistics | none |
pin_memory | Pin memory to core status | node_id |
unpin_memory | Unpin and re-evaluate | node_id |
delete_memory | Permanently delete memory | node_id |
list_core_memories | List core memories by category | category (optional) |
set_core_preferences | Configure core memory categories | auto, approval, excluded |
Sources: src/genesys_memory/server.py:7-80 | README.md
Storage Layer
Genesys supports multiple storage backends through a provider abstraction:
graph LR
subgraph "Storage Providers"
Memory["MemoryProvider"]
Postgres["PostgresProvider"]
Obsidian["ObsidianProvider"]
FalkorDB["FalkorDBProvider"]
end
subgraph "Capabilities"
Cache["CacheProvider"]
Embedding["EmbeddingProvider"]
EventBus["EventBusProvider"]
Graph["GraphStorageProvider"]
end
Memory & Postgres & Obsidian & FalkorDB --> Cache
Memory & Postgres & Obsidian & FalkorDB --> Embedding
Memory & Postgres & Obsidian & FalkorDB --> Graph
Memory & Postgres & Obsidian & FalkorDB --> EventBus#### Backend Comparison
| Backend | Install | Use Case | Scalability |
|---|---|---|---|
memory | Built-in | Zero deps, try it out | Low |
postgres + pgvector | genesys-memory[postgres] | Persistent, scalable | High |
| Obsidian vault | genesys-memory[obsidian] | Local-first knowledge base | Medium |
| FalkorDB | genesys-memory[falkordb] | Graph-native traversal | High |
#### Configuration Options
| Variable | Required | Description |
|---|---|---|
OPENAI_API_KEY | Unless GENESYS_EMBEDDER=local | Embeddings provider |
ANTHROPIC_API_KEY | No | LLM memory processing |
GENESYS_BACKEND | No | memory, postgres, obsidian, falkordb |
GENESYS_EMBEDDER | No | openai or local (sentence-transformers) |
DATABASE_URL | If postgres | Postgres connection string |
OBSIDIAN_VAULT_PATH | If obsidian | Path to Obsidian vault |
FALKORDB_HOST | If falkordb | FalkorDB host (default: localhost) |
Sources: README.md
Data Models
MemoryNode
The MemoryNode is the core data structure representing a single memory:
class MemoryNode(BaseModel):
id: uuid.UUID = Field(default_factory=uuid.uuid4)
status: MemoryStatus = MemoryStatus.ACTIVE
content_summary: str = Field(max_length=200)
content_full: str | None = None
content_ref: str | None = None
embedding: list[float] | None = None
# Timestamps
created_at: datetime
last_accessed_at: datetime
last_reactivated_at: datetime
# Lifecycle scores
decay_score: float = 1.0
causal_weight: int = 0
reactivation_count: int = 0
reactivation_pattern: ReactivationPattern
irrelevance_counter: int = 0
# Stability (spaced repetition)
stability: float = 1.0
# Core memory
pinned: bool = False
promotion_reason: str | None = None
Sources: src/genesys_memory/models/node.py:6-40
MemoryEdge
Relationships between memories are represented as edges with metadata:
| Field | Type | Description |
|---|---|---|
edge_type | EdgeType | caused_by, supports, derived_from |
confidence | float | 0.0 to 1.0 |
reason | str | Explanation of relationship |
Sources: src/genesys_memory/engine/llm_provider.py:1-30
Scoring Engine
Memory Scoring Formula
Every memory is scored by three forces multiplied together:
decay_score = relevance × connectivity × reactivation
- Relevance: Decays over time. Old memories fade unless reinforced
- Connectivity: Rewards memories with many causal links (hub memories survive)
- Reactivation: Boosts frequently accessed memories
Because the formula is multiplicative, a memory must score on all three axes to survive. A highly connected but never-accessed memory still decays.
Sources: README.md
LLM Provider for Causal Relationships
The LLM Provider identifies causal relationships between new memories and existing ones:
graph LR
NewMemory["New Memory"] --> LLMPrompt["LLM Prompt"]
ExistingMemories["Existing Memories"] --> LLMPrompt
LLMPrompt --> LLM["LLM API"]
LLM --> Relationships["Causal Edges<br/>confidence > 0.6"]The LLM processes:
target_id: ID of the existing memoryedge_type:caused_by,supports, orderived_fromconfidence: 0.0 to 1.0reason: Brief explanation
Sources: src/genesys_memory/engine/llm_provider.py:10-30
Memory Lifecycle
State Machine
graph LR
STORE["STORE"] --> ACTIVE["ACTIVE"]
ACTIVE --> DORMANT["DORMANT"]
DORMANT --> FADING["FADING"]
FADING --> PRUNED["PRUNED"]
ACTIVE -.->|reactivation| ACTIVE
DORMANT -.->|reactivation| ACTIVE
FADING -.->|reactivation| ACTIVE
PRUNED -.->|never| REAPPEAR["REAPPEAR"]Lifecycle Rules
| State | Description | Transition Condition |
|---|---|---|
STORE | Newly created memory | Initial state |
ACTIVE | Frequently accessed, high score | Score > threshold |
DORMANT | Low access, moderate decay | Score declining |
FADING | Near-zero score | Score approaching 0 |
PRUNED | Permanently deleted | Score = 0, orphan, not pinned |
Core Memory Promotion
Memories can be promoted to core status — structurally important memories that are:
- Auto-pinned on promotion
- Never pruned automatically
- Assigned a
promotion_reason
Sources: src/genesys_memory/models/node.py:35-38 | README.md
Authentication & Authorization
Multi-User Mode
The system supports multi-user operation with organization-level access control:
def _caller_owns_node(node: MemoryNode) -> bool:
uid = _caller_uid()
if uid is None:
raise PermissionError("current_user_id not set")
role = current_user_role.get(None)
if role == "admin" and node.org_id in current_org_ids.get([]):
return True
return node.original_user_id == uid
Sources: src/genesys_memory/mcp/tools.py:20-35
Visibility Levels
| Level | Description | Access |
|---|---|---|
private | User-only | Owner only |
org | Organization-wide | Org members |
public | All users | Read access |
Sources: src/genesys_memory/models/enums.py
Tool Dispatch Architecture
The tool dispatch system maps MCP tool names to internal methods:
_TOOL_DISPATCH: dict[str, tuple[Any, ...]] = {
"memory_store": (tools.memory_store, ["content"], {"source_session": "", "related_to": None, "visibility": "private", "org_id": None}),
"memory_recall": (tools.memory_recall, ["query"], {"k": 10, "max_results": None}),
"memory_search": (tools.memory_search, ["query"], {"filters": None, "k": 10}),
"memory_traverse": (tools.memory_traverse, ["node_id"], {"depth": 2, "edge_types": None}),
"memory_explain": (tools.memory_explain, ["node_id"], {}),
"pin_memory": (tools.pin_memory, ["node_id"], {}),
"unpin_memory": (tools.unpin_memory, ["node_id"], {}),
"list_core_memories": (tools.list_core_memories, [], {"category": None}),
"delete_memory": (tools.delete_memory, ["node_id"], {}),
"memory_stats": (tools.memory_stats, [], {}),
"set_core_preferences": (tools.set_core_preferences, [], {}),
}
Each entry contains:
- The method to call
- Required argument names
- Optional arguments with default values
Sources: src/genesys_memory/server.py:30-45
Deployment Topologies
Development Mode (In-Memory)
pip install genesys-memory
cp .env.example .env
uvicorn genesys.api:app --port 8000
Suitable for local development with zero infrastructure.
Production Mode (Postgres)
pip install 'genesys-memory[postgres]'
docker compose up -d postgres
alembic upgrade head
GENESYS_BACKEND=postgres uvicorn genesys.api:app --port 8000
Claude Desktop Integration
{
"mcpServers": {
"genesys": {
"url": "http://localhost:8000/mcp"
}
}
}
Sources: README.md
Performance Characteristics
Benchmark Results (LoCoMo Benchmark)
| Category | J-Score |
|---|---|
| Single-hop | 94.3% |
| Temporal | 87.5% |
| Multi-hop | 69.8% |
| Open-domain | 91.7% |
| Overall | 89.9% |
Compared to alternatives:
- Mem0: 67.1%
- Zep: 75.1%
Sources: README.md
Dependencies
Core Requirements
| Package | Purpose |
|---|---|
mcp | Model Context Protocol server |
pydantic | Data validation |
fastapi | API framework |
uvicorn | ASGI server |
Optional Dependencies
| Extra | Packages |
|---|---|
postgres | psycopg2-binary, alembic, asyncpg |
obsidian | python-dotenv |
local | sentence-transformers |
Sources: CONTRIBUTING.md | server.json
Source: https://github.com/rishimeka/genesys / Human Manual
Memory Scoring Engine
Related topics: Memory Lifecycle Management
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Memory Lifecycle Management
Memory Scoring Engine
Overview
The Memory Scoring Engine is the core intelligence layer of Genesys that determines which memories survive, decay, or get promoted to core status. It implements a multiplicative scoring formula that evaluates memories across three dimensions: relevance, connectivity, and reactivation frequency.
decay_score = relevance × connectivity × reactivation
Sources: README.md
Architecture
Core Components
The scoring engine consists of several interconnected modules:
| Component | File | Purpose |
|---|---|---|
| Scoring Calculator | engine/scoring.py | Computes the decay score for each memory node |
| Configuration | engine/config.py | Defines thresholds and env-configurable parameters |
| Reactivation Handler | engine/reactivation.py | Tracks and updates memory access patterns |
| Transition Engine | engine/transitions.py | Evaluates and executes state transitions |
| LLM Provider | engine/llm_provider.py | LLM-based consolidation and contradiction detection |
Sources: engine/transitions.py:1-15
Scoring Formula
The decay score is calculated as the product of three independent factors:
graph TD
A[Memory Node] --> B[Relevance Score]
A --> C[Connectivity Score]
A --> D[Reactivation Score]
B --> E[decay_score]
C --> E
D --> E
E --> F{decay_score > threshold?}- Relevance: Decays over time. Old memories fade unless reinforced through recall or context reactivation.
- Connectivity: Rewards memories with many causal links. Hub memories (highly connected nodes) survive longer.
- Reactivation: Boosts memories that are repeatedly accessed. Frequency of recall matters.
Sources: README.md
Multiplicative Nature
Because the formula is multiplicative, a memory must score on all three axes to survive:
| Scenario | Relevance | Connectivity | Reactivation | Result |
|---|---|---|---|---|
| High connections, never accessed | ✓ | ✓ | ✗ | Memory decays |
| Frequently recalled, no links | ✓ | ✗ | ✓ | Memory fades |
| Old but connected and active | ✗ | ✓ | ✓ | May survive |
Sources: README.md
Memory Node Data Model
Each memory node stores scoring-related metrics:
class MemoryNode(BaseModel):
# Lifecycle scores
decay_score: float = 1.0
causal_weight: int = 0
reactivation_count: int = 0
reactivation_pattern: ReactivationPattern = ReactivationPattern.SINGLE
irrelevance_counter: int = 0
# Stability (increases on successful retrieval, per spaced repetition)
stability: float = 1.0
# Timestamps
created_at: datetime
last_accessed_at: datetime
last_reactivated_at: datetime
# Core memory flags
pinned: bool = False
promotion_reason: str | None = None
Sources: src/genesys_memory/models/node.py:20-40
Scoring Fields
| Field | Type | Description |
|---|---|---|
decay_score | float | Combined score (0.0 to 1.0), product of all factors |
causal_weight | int | Number of incoming/outgoing causal edges |
reactivation_count | int | Total times memory was successfully recalled |
reactivation_pattern | ReactivationPattern | Pattern type: SINGLE, SPIKE, or CONSOLIDATED |
irrelevance_counter | int | Consecutive failed relevance matches |
stability | float | Retrieval success rate (spaced repetition factor) |
pinned | bool | If True, memory is exempt from pruning |
Sources: src/genesys_memory/models/node.py:25-45
State Transitions
Lifecycle States
stateDiagram-v2
[*] --> STORE: Store new memory
STORE --> ACTIVE: Edge formed (consolidation)
ACTIVE --> DORMANT: Low reactivation
DORMANT --> ACTIVE: Reactivation
DORMANT --> FADING: Extended inactivity
FADING --> ACTIVE: Reactivation
FADING --> PRUNED: Score reaches 0 OR orphaned
ACTIVE --> CORE: Promotion evaluation
CORE --> [*]: Manual unpinTransition Evaluation
The transition engine evaluates all non-core, non-pruned nodes:
async def evaluate_transitions(
graph: GraphStorageProvider,
embeddings: EmbeddingProvider,
llm: LLMProvider,
context_embedding: list[float] | None = None,
context_entities: list[str] | None = None,
) -> list[dict[str, Any]]:
Sources: src/genesys_memory/engine/transitions.py:15-23
Transition Rules
| From State | To State | Trigger Condition |
|---|---|---|
| TAGGED | ACTIVE | Node has edges (consolidation signal) |
| ACTIVE | DORMANT | Low reactivation + relevance drops |
| DORMANT | ACTIVE | Successful reactivation recall |
| DORMANT | FADING | Extended inactivity period |
| FADING | PRUNED | decay_score = 0 or orphaned + not pinned |
Sources: src/genesys_memory/engine/transitions.py:25-40
Tagged Memory Expiration
Tagged memories auto-expire after 24 hours if no connections form:
# Auto-expire tagged memories after 24h with no connections
age_hours = (datetime.now(timezone.utc) - node.created_at).total_seconds() / 3600
Sources: src/genesys_memory/engine/transitions.py:40-41
Reactivation Patterns
Reactivation tracks how memories are accessed over time:
| Pattern | Description | Effect on Score |
|---|---|---|
SINGLE | Single retrieval event | Baseline reactivation boost |
SPIKE | Burst of retrievals | Stronger boost, may indicate importance |
CONSOLIDATED | Regular spaced retrieval | Maximum stability increase |
Sources: src/genesys_memory/models/node.py:30
Core Memory Promotion
Memories can be promoted to core status — structurally important memories that are:
- Auto-pinned on promotion
- Never pruned
- Automatically identified based on graph centrality
graph LR
A[High Causal Weight] --> B{Evaluate Core<br/>Promotion}
C[Category Match] --> B
D[User Annotation] --> B
B --> E[Pin Memory]
E --> F[Mark as Core]Memories eligible for core promotion must:
- Have high causal weight (hub nodes)
- Match configured category patterns
- Not be manually excluded
Sources: src/genesys_memory/mcp/tools.py:35-45
Configuration
Engine thresholds are environment-configurable and should not be hardcoded:
| Parameter | Source | Default | Description |
|---|---|---|---|
| Decay rates | engine/config.py | Environment | Time-based relevance decay |
| Causal thresholds | engine/config.py | Environment | Min connections for hub status |
| Reactivation boost | engine/config.py | Environment | Multiplier for recall events |
Sources: CONTRIBUTING.md
LLM Integration
The scoring engine uses LLM providers for advanced operations:
Consolidation
Combines episodic memories into coherent summaries:
async def consolidate(self, episodic_memories: list[str]) -> str:
memories_text = "\n".join(f"- {m}" for m in episodic_memories)
# LLM generates consolidated summary
Sources: src/genesys_memory/engine/llm_provider.py:45-50
Causal Link Detection
Automatically identifies relationships between memories:
async def identify_causal_relationships(
new_memory: str,
existing_memories: list[tuple[str, str]]
) -> list[tuple[str, EdgeType, float, str | None]]:
Edge types detected:
caused_by— Causal dependencysupports— Supporting evidencederived_from— Extracted from source
Sources: src/genesys_memory/engine/llm_provider.py:15-35
Confidence Threshold
Only relationships with confidence > 0.6 are included:
"Only include relationships with confidence > 0.6."
Sources: src/genesys_memory/engine/llm_provider.py:25
MCP Tools for Scoring
| Tool | Function | Scoring Impact |
|---|---|---|
memory_recall | Hybrid search (vector + keyword + graph) | Updates last_reactivated_at, increments reactivation_count |
memory_traverse | Graph walk from node | May boost connectivity scores |
memory_explain | Score breakdown analysis | Read-only |
pin_memory | Manual core promotion | Sets pinned=True, exempts from pruning |
unpin_memory | Remove core status | Re-evaluates core eligibility |
Sources: src/genesys_memory/server.py:10-45
Engine Workflow
graph TD
A[Memory Store Request] --> B{Parse & Validate}
B -->|Valid| C[Generate Embedding]
B -->|Invalid| Z[Reject]
C --> D[LLM: Identify Causal Links]
D --> E[Graph: Create Node + Edges]
E --> F[Initial Scoring]
F --> G[Evaluate Transitions]
G --> H{Transition Needed?}
H -->|Yes| I[Update State]
H -->|No| J[Index for Retrieval]
I --> J
J --> K[Return to Client]
L[Recall Query] --> M[Vector Search]
M --> N[Graph Spreading Activation]
N --> O[Rank by decay_score]
O --> P[Update Reactivation Metrics]
P --> Q[Return Ranked Results]Benchmark Performance
The scoring engine was evaluated on the LoCoMo benchmark:
| Category | J-Score |
|---|---|
| Single-hop | 94.3% |
| Temporal | 87.5% |
| Multi-hop | 69.8% |
| Open-domain | 91.7% |
| Overall | 89.9% |
Compared against:
- Mem0: 67.1%
- Zep: 75.1%
Sources: README.md
Testing
The scoring engine modules are tightly coupled. When modifying scoring, transitions, or forgetting logic, run the full test suite:
# Run all unit tests
pytest tests/ -v
# With coverage
pytest tests/ -v --cov=src/genesys_memory --cov-report=term-missing
Sources: CONTRIBUTING.md
Sources: README.md
Memory Lifecycle Management
Related topics: Memory Scoring Engine, Nodes and Edges Data Models
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Memory Scoring Engine, Nodes and Edges Data Models
Memory Lifecycle Management
Memory Lifecycle Management is the core intelligence layer of Genesys that governs how memories are created, scored, transitioned between states, consolidated, and ultimately forgotten. It provides an intelligent forgetting mechanism that goes beyond simple time-based decay by evaluating memories through a multiplicative scoring formula that considers relevance, connectivity, and reactivation patterns.
Overview
Genesys implements an active memory management system where memories are not passive storage entries but dynamic entities governed by lifecycle rules. Every memory in the system follows a deterministic path from creation through potential promotion or eventual pruning.
The lifecycle management system consists of several interconnected components:
| Component | Purpose |
|---|---|
| Transitions Engine | Evaluates and executes status changes between memory states |
| Scoring Engine | Calculates decay scores using relevance, connectivity, and reactivation |
| Consolidation Engine | Processes episodic memories and forms causal relationships |
| Forgetting Engine | Handles pruning of low-value, orphaned memories |
| Promotion System | Manages core memory designation and pinning |
Sources: src/genesys_memory/engine/transitions.py:1-20
Memory States
Memories exist in one of several distinct states, defined by the MemoryStatus enum. Each state represents a different phase in the memory's lifecycle with specific behavioral characteristics.
graph TD
STORED["STORE (New)"] --> ACTIVE["ACTIVE"]
ACTIVE --> DORMANT["DORMANT"]
DORMANT --> FADING["FADING"]
FADING --> PRUNED["PRUNED"]
ACTIVE -.-> REACTIVATION["reactivation"]
REACTIVATION -.-> ACTIVE
FADING -.->|score=0, orphan, not pinned| PRUNED
STYLED_STORE{{"Created - waiting for consolidation"}}
STYLED_ACTIVE{{"In use - scored and tracked"}}
STYLED_DORMANT{{"Low usage - may be accessed"}}
STYLED_FADING{{"About to be forgotten"}}
STYLED_PRUNED{{"Permanently deleted"}}State Definitions
| State | Description | Auto-transition |
|---|---|---|
TAGGED | Newly created, awaiting consolidation signal | 24h timeout → PRUNED |
ACTIVE | Currently relevant, regularly scored | Decay → DORMANT |
DORMANT | Infrequently accessed, reduced priority | Further decay → FADING |
FADING | Pending deletion, low score | score=0 → PRUNED |
PRUNED | Permanently deleted | None |
Sources: src/genesys_memory/models/enums.py (MemoryStatus enum referenced in transitions.py)
State Transition Rules
The transition engine evaluates non-core, non-pruned nodes for status changes. The evaluation follows these rules:
- Tagged → Active: Promote when the node has formed causal edges (consolidation signal received)
- Active → Dormant: When reactivation count drops below threshold
- Dormant → Fading: When decay score falls to critical levels
- Fading → Pruned: Only when
score=0, node is an orphan, and not pinned
# From transitions.py - key evaluation logic
async def evaluate_transitions(
graph: GraphStorageProvider,
embeddings: EmbeddingProvider,
llm: LLMProvider,
context_embedding: list[float] | None = None,
context_entities: list[str] | None = None,
) -> list[dict[str, Any]]:
Sources: src/genesys_memory/engine/transitions.py:18-25
The Scoring System
Every memory is scored by three forces multiplied together, forming the core intelligence of the lifecycle management system:
decay_score = relevance × connectivity × reactivation
Scoring Components
| Component | Description | Behavior |
|---|---|---|
| Relevance | Time-based decay factor | Old memories fade unless reinforced |
| Connectivity | Causal graph weight | Rewards memories with many causal links; hub memories survive |
| Reactivation | Access frequency | Boosts memories that keep being recalled |
Because the formula is multiplicative, a memory must score on all three axes to survive. A highly connected but never-accessed memory still decays. A frequently recalled but causally orphaned memory still fades.
graph LR
subgraph "Score Factors"
R[Relevance]
C[Connectivity]
A[Reactivation]
end
R --> MULT["×"]
C --> MULT
A --> MULT
MULT --> SCORE[decay_score]
SCORE -->|high| SURVIVE["SURVIVE"]
SCORE -->|zero| PRUNE["PRUNED"]Sources: src/genesys_memory/engine/scoring.py (referenced in transitions.py)
Memory Node Data Model
Each memory in the system is represented by a MemoryNode that tracks all lifecycle-relevant attributes:
class MemoryNode(BaseModel):
id: uuid.UUID = Field(default_factory=uuid.uuid4)
status: MemoryStatus = MemoryStatus.ACTIVE
content_summary: str = Field(max_length=200)
content_full: str | None = None
# Lifecycle scores
decay_score: float = 1.0
causal_weight: int = 0
reactivation_count: int = 0
reactivation_pattern: ReactivationPattern = ReactivationPattern.SINGLE
# Timestamps
created_at: datetime
last_accessed_at: datetime
last_reactivated_at: datetime
# Core memory
pinned: bool = False
promotion_reason: str | None = None
# Stability
stability: float = 1.0
Sources: src/genesys_memory/models/node.py:14-45
Key Lifecycle Fields
| Field | Type | Purpose |
|---|---|---|
decay_score | float | Current composite score (0.0 to 1.0) |
causal_weight | int | Number of causal connections |
reactivation_count | int | Number of successful recalls |
reactivation_pattern | ReactivationPattern | SINGLE, REPEATED, or CONSOLIDATED |
stability | float | Increases on successful retrieval (spaced repetition) |
pinned | bool | Core memory flag - never pruned |
irrelevance_counter | int | Consecutive low-relevance evaluations |
MCP Tools for Lifecycle Management
The MCP server exposes tools for programmatic lifecycle management:
| Tool | Description |
|---|---|
memory_explain | Explain why a memory exists and its causal chain |
pin_memory | Pin a memory so it's never forgotten |
unpin_memory | Unpin a previously pinned memory |
list_core_memories | List core memories, optionally filtered by category |
memory_stats | Get memory system statistics |
promote_to_org | Promote a private memory to org visibility |
Sources: src/genesys_memory/server.py:40-90
Core Preferences Configuration
Users can configure automatic core memory behavior:
Tool(name="set_core_preferences", description="Configure core memory category preferences.", inputSchema={
"type": "object",
"properties": {
"auto": {"type": "array", "items": {"type": "string"}},
"approval": {"type": "array", "items": {"type": "string"}},
"excluded": {"type": "array", "items": {"type": "string"}},
},
})
Sources: src/genesys_memory/server.py:80-90
Engine Thresholds
The lifecycle behavior is controlled through configurable thresholds defined in engine/config.py. These thresholds govern transition points and scoring calculations.
| Threshold | Default | Description |
|---|---|---|
| Active→Dormant decay | Configurable | Score threshold for dormancy |
| Dormant→Fading decay | Configurable | Score threshold for fading |
| Orphan detection | 0 edges | Nodes with no causal connections |
| Reactivation boost | Configurable | Multiplier for recalled memories |
Note: Engine thresholds are environment-configurable. Do not hardcode magic numbers in engine files.
Sources: src/genesys_memory/engine/config.py (referenced in CONTRIBUTING.md)
Consolidation and Causal Edge Formation
When new memories are stored, the LLM provider analyzes relationships with existing memories to form causal edges:
async def identify_causal_relationships(
self,
new_memory: str,
existing_memories: list[tuple[str, str]],
) -> list[tuple[str, EdgeType, float, str | None]]:
The provider identifies three types of causal relationships:
| Edge Type | Description |
|---|---|
caused_by | Causal dependency |
supports | Supporting evidence |
derived_from | Information lineage |
Relationships are only created when confidence exceeds 0.6.
Sources: src/genesys_memory/engine/llm_provider.py:30-60
Reactivation Patterns
Memories track how they are reactivated, which affects scoring:
| Pattern | Description |
|---|---|
SINGLE | Occasional single recall |
REPEATED | Frequently recalled |
CONSOLIDATED | Formed connections during consolidation |
Reactivation history is stored as timestamps in reactivation_timestamps, allowing the system to implement spaced repetition principles where successful retrievals increase memory stability.
Sources: src/genesys_memory/models/node.py:35-40
Permissions and Ownership
Lifecycle management respects multi-tenant permissions:
def _caller_owns_node(node: MemoryNode) -> bool:
"""Check if the current caller is the original owner of a node."""
uid = _caller_uid()
if uid is None:
raise PermissionError("current_user_id not set — cannot verify ownership")
role = current_user_role.get(None)
if role == "admin" and node.org_id and node.org_id in current_org_ids.get([]):
return True
if node.original_user_id:
return node.original_user_id == uid
return True
Sources: src/genesys_memory/mcp/tools.py:25-38
Benchmark Performance
The lifecycle management system was evaluated on the LoCoMo benchmark:
| Category | J-Score |
|---|---|
| Single-hop | 94.3% |
| Temporal | 87.5% |
| Multi-hop | 69.8% |
| Open-domain | 91.7% |
| Overall | 89.9% |
For comparison, Mem0 scored 67.1% and Zep scored 75.1% on the same benchmark.
Nodes and Edges Data Models
Related topics: Graph Traversal and Causal Reasoning, Storage Provider Implementation
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Graph Traversal and Causal Reasoning, Storage Provider Implementation
Nodes and Edges Data Models
The Nodes and Edges data models form the foundational graph structure of the Genesys memory system. Every piece of information stored in Genesys is represented as a node within a causal graph, with relationships between memories expressed through typed edges. This graph-native approach enables sophisticated memory operations including traversal, causal reasoning, and intelligent forgetting based on connectivity patterns.
Overview
The data model architecture consists of two primary entities:
- MemoryNode: Represents an individual memory with content, metadata, embedding vectors, and lifecycle state
- MemoryEdge: Represents a typed, weighted relationship between two memory nodes
Together, these constructs enable the causal graph that powers Genesys's memory intelligence layer. The graph structure supports operations like vector similarity search, causal traversal, and the multiplicative scoring formula that determines memory survival.
MemoryNode Model
The MemoryNode class represents the core unit of memory storage in the Genesys system. Each node encapsulates both the semantic content of a memory and its operational metadata.
Core Attributes
@dataclass
class MemoryNode:
id: UUID
status: MemoryStatus
content_summary: str
content_full: str
embedding: list[float]
created_at: datetime
last_accessed_at: datetime
last_reactivated_at: datetime
entity_refs: list[str]
# Additional fields from source code
original_user_id: Optional[str] = None
org_id: Optional[str] = None
visibility: Visibility = Visibility.PRIVATE
is_pinned: bool = False
category: Optional[str] = None
Attribute Descriptions
| Attribute | Type | Description |
|---|---|---|
id | UUID | Unique identifier for the memory node |
status | MemoryStatus | Current lifecycle state (ACTIVE, TAGGED, DORMANT, etc.) |
content_summary | str | Concise summary of the memory content |
content_full | str | Complete memory content |
embedding | list[float] | Vector representation for similarity search |
created_at | datetime | Timestamp when the memory was created |
last_accessed_at | datetime | Timestamp of most recent access |
last_reactivated_at | datetime | Timestamp of most recent recall operation |
entity_refs | list[str] | References to entities mentioned in the memory |
original_user_id | str | User who originally created the memory |
org_id | str | Organization ID for org-scoped memories |
visibility | Visibility | Access level (PRIVATE, ORG, PUBLIC) |
is_pinned | bool | Whether memory is protected from pruning |
category | str | Optional categorization for filtering |
MemoryStatus Enum
The lifecycle state of a memory node is governed by the MemoryStatus enum, which defines the progression from creation through potential pruning.
Sources: src/genesys_memory/models/enums.py
class MemoryStatus(Enum):
SEMANTIC = "semantic" # LLM-consolidated abstract memory
ACTIVE = "active" # Frequently accessed, high relevance
TAGGED = "tagged" # Newly created, not yet consolidated
DORMANT = "dormant" # Decaying relevance, low access
FADING = "fading" # Near-pruning threshold
PRUNED = "pruned" # Permanently removed
Lifecycle State Transitions
graph TD
TAGGED[TAGGED] -->|consolidation signal| ACTIVE[ACTIVE]
TAGGED -->|24h no connections| PRUNED[PRUNED]
ACTIVE -->|decay score drops| DORMANT[DORMANT]
DORMANT -->|reactivation| ACTIVE
DORMANT -->|score continues declining| FADING[FADING]
FADING -->|score = 0| PRUNED
FADING -->|reactivation| DORMANT
TAGGED -->|LLM consolidation| SEMANTIC[SEMANTIC]Sources: src/genesys_memory/engine/transitions.py:1-50
The transition engine evaluates nodes for state changes based on:
- Consolidation signals: Tagged nodes with formed edges promote to active
- Decay scoring: Low scores trigger transitions toward dormant and fading states
- Reactivation: Recall operations boost nodes back toward active status
MemoryEdge Model
The MemoryEdge class represents relationships between memory nodes, enabling the causal graph structure that powers Genesys's understanding of memory interconnectedness.
Core Attributes
@dataclass
class MemoryEdge:
source_id: UUID
target_id: UUID
type: EdgeType
weight: float
reason: Optional[str] = None
created_by: Optional[str] = None
Attribute Descriptions
| Attribute | Type | Description |
|---|---|---|
source_id | UUID | ID of the memory node where the edge originates |
target_id | UUID | ID of the memory node where the edge points |
type | EdgeType | Semantic relationship type |
weight | float | Connection strength (0.0 to 1.0) |
reason | str | Explanation of why the relationship exists |
created_by | str | Provenance: "user_explicit", "auto_link", or LLM-generated |
EdgeType Enum
The relationship semantics between memory nodes are defined by the EdgeType enum, which categorizes different kinds of causal and associative connections.
Sources: src/genesys_memory/models/enums.py
class EdgeType(Enum):
CAUSED_BY = "caused_by" # Causal relationship: source caused target
SUPPORTS = "supports" # Evidential: source supports/validates target
DERIVED_FROM = "derived_from" # Created from: source derived from target
RELATED_TO = "related_to" # Semantic similarity
Edge Relationship Types
| Edge Type | Direction | Semantics | Typical Weight |
|---|---|---|---|
CAUSED_BY | source → target | Source memory caused/influenced target | 0.7 |
SUPPORTS | source → target | Source provides evidence for target | 0.8 |
DERIVED_FROM | source → target | Source is abstracted from target | 0.7 |
RELATED_TO | bidirectional | Semantic similarity connection | 0.3-1.0 |
Graph Data Flow
The interaction between nodes and edges creates the causal graph that powers Genesys's memory operations.
graph LR
subgraph MemoryNode[MemoryNode]
N1[Content + Embedding]
N2[Status + Timestamps]
N3[Entity References]
end
subgraph MemoryEdge[MemoryEdge]
E1[Source → Target]
E2[Type + Weight]
E3[Reason + Provenance]
end
N1 -->|links| E1
N2 -->|determines| E1
N3 -->|informs| E2Memory Storage Operations
The storage layer implements the GraphStorageProvider interface to persist and query nodes and edges across different backend options.
Node Creation
When storing a new memory, the system performs the following operations:
- Generate embedding vector via the configured
EmbeddingProvider - Create the
MemoryNodewith initialTAGGEDstatus - Create explicit
CAUSED_BYedges for related memories - Auto-link to semantically similar existing memories via vector search
Sources: src/genesys_memory/mcp/tools.py
# Auto-link to semantically similar existing memories
if embedding:
similar = await self.graph.vector_search(embedding, k=4, org_ids=org_ids)
for other_node, score in similar:
if score < 0.3:
continue
edge = MemoryEdge(
source_id=node.id,
target_id=other_node.id,
type=EdgeType.RELATED_TO,
weight=round(score, 4),
reason=f"cosine similarity {score:.3f}",
created_by="auto_link",
)
await self.graph.create_edge(edge)
Consolidation Operations
The consolidation engine creates SEMANTIC nodes from related episodic memories, establishing DERIVED_FROM edges to track the abstraction chain.
Sources: src/genesys_memory/engine/consolidation.py:200
# Create DERIVED_FROM edges
for source_node in matching:
edge = MemoryEdge(
source_id=semantic_node.id,
target_id=source_node.id,
type=EdgeType.DERIVED_FROM,
weight=0.7,
)
await graph.create_edge(edge)
Visibility and Access Control
Memory nodes support three visibility levels that govern cross-user and cross-organization access:
class Visibility(Enum):
PRIVATE = "private" # Only visible to original user
ORG = "org" # Visible to organization members
PUBLIC = "public" # Visible to all users
Org Boundary Rules
When a memory has ORG visibility:
- Edges can only connect to other
ORGnodes within the same organization - Private nodes cannot link to org-scoped nodes
- This isolation ensures data governance compliance
ReactivationPattern Enum
The reactivation behavior tracking is defined by the ReactivationPattern enum, which captures how memories are accessed and reinforced over time.
class ReactivationPattern(Enum):
# Patterns for tracking memory access patterns
EXPLICIT = "explicit" # Direct recall request
IMPLICIT = "implicit" # Accessed via graph traversal
CONSOLIDATED = "consolidated" # Incorporated into semantic memory
Integration with MCP Tools
The MCP server exposes tools that operate on the nodes and edges data models:
| MCP Tool | Operation | Data Model Impact |
|---|---|---|
memory_store | Store new memory | Creates node + edges |
memory_recall | Recall by query | Updates last_reactivated_at |
memory_traverse | Graph walk | Reads nodes + edges |
memory_explain | Score breakdown | Reads node + connected edges |
pin_memory | Protect from pruning | Sets is_pinned=True |
delete_memory | Remove memory | Deletes node + all edges |
Scoring Formula Integration
The nodes and edges data models directly support the multiplicative scoring formula:
decay_score = relevance × connectivity × reactivation
- Relevance: Derived from
created_atandlast_accessed_attimestamps - Connectivity: Calculated from edge weights connected to the node
- Reactivation: Boosted when
last_reactivated_atis recent
The graph structure enables the connectivity calculation by summing weighted edges, while timestamps on nodes track relevance and reactivation factors.
Storage Backend Options
The nodes and edges data models are abstracted behind the GraphStorageProvider interface, enabling multiple backend options:
| Backend | Description | Use Case |
|---|---|---|
memory | In-memory Python dict/list | Development, testing |
postgres | PostgreSQL with pgvector | Production, scalable |
obsidian | SQLite sidecar in vault | Local-first knowledge base |
falkordb | Redis-based graph database | Graph-native traversal |
Summary
The Nodes and Edges data models provide the structural foundation for Genesys's causal graph memory system. MemoryNode captures the content, state, and metadata of individual memories, while MemoryEdge expresses the typed, weighted relationships between them. Together with the lifecycle states defined in MemoryStatus and relationship semantics in EdgeType, these models enable sophisticated memory operations including intelligent forgetting, causal reasoning, and semantic consolidation.
Sources: src/genesys_memory/models/enums.py
Graph Traversal and Causal Reasoning
Related topics: Nodes and Edges Data Models, MCP Tools Reference
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Nodes and Edges Data Models, MCP Tools Reference
Graph Traversal and Causal Reasoning
Genesys implements a sophisticated graph-based memory system where memories are interconnected through causal relationships. This design enables the system to traverse memory networks, explain why memories exist, detect contradictions, and intelligently consolidate related information.
Architecture Overview
The graph traversal and causal reasoning system consists of several interconnected components that work together to maintain a living memory network.
graph TB
subgraph "Graph Layer"
TRAVERSE[memory_traverse]
EXPLAIN[memory_explain]
CAUSAL[Causal Chain Resolution]
end
subgraph "Engine Layer"
CONTRADICT[Contradiction Detection]
CONSOLIDATE[Memory Consolidation]
TRANSITIONS[Status Transitions]
LLM_PROC[LLM Provider]
end
subgraph "Storage Layer"
GRAPH[GraphStorageProvider]
VECTOR[Vector Search]
end
TRAVERSE --> GRAPH
EXPLAIN --> CAUSAL
CAUSAL --> GRAPH
CONTRADICT --> VECTOR
CONTRADICT --> LLM_PROC
CONSOLIDATE --> LLM_PROC
TRANSITIONS --> GRAPH
GRAPH --> VECTORCausal Chain Resolution
Causal chains represent the lineage and relationships between memories. Each memory can have upstream causes (memories that influenced it) and downstream effects (memories it influenced).
How Causal Chains Work
When a memory is stored or recalled, the system resolves its causal context by fetching neighboring nodes in both directions. The causal chain is limited to the top 5 most relevant upstream and downstream nodes to maintain performance while providing meaningful context.
graph LR
A[Memory A] -->|caused_by| B[Memory B]
B -->|caused_by| C[Memory C]
C -->|caused_by| D[Memory D]
style A fill:#e1f5fe
style D fill:#ffcdd2Causal Chain Data Structure
When explaining a memory, the system builds a structured response containing:
| Field | Type | Description |
|---|---|---|
id | string | Memory node UUID |
summary | string | Content summary of the memory |
direction | string | "upstream" or "downstream" |
causal_chain | array | Ordered list from origin to target |
Sources: src/genesys_memory/mcp/tools.py:1-1
Implementation Details
The causal chain resolution iterates through upstream and downstream nodes, collecting their summaries and preventing duplicates via a seen_causal set:
seen_causal: set[str] = set()
for n in upstream[:5]:
nid_str = str(n.id)
if nid_str not in seen_causal:
causal_basis.append({"id": nid_str, "summary": n.content_summary, "direction": "upstream"})
seen_causal.add(nid_str)
Sources: src/genesys_memory/mcp/tools.py:1-1
Memory Traversal
The memory_traverse MCP tool enables walking the causal graph from any given memory node. This is fundamental for understanding memory context and retrieving related information.
Traversal Workflow
sequenceDiagram
participant Client
participant MCP as MCP Server
participant Graph as GraphStorageProvider
participant Vector as Vector Search
Client->>MCP: memory_traverse(node_id, direction)
MCP->>Graph: get_causal_chain(node_id, direction)
Graph->>Vector: vector_search(embedding, k)
Vector-->>Graph: similar nodes
Graph-->>MCP: causal chain nodes
MCP->>MCP: format_response(nodes)
MCP-->>Client: formatted traversal resultTraversal Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
node_id | string | required | Starting memory node ID |
direction | string | "both" | "upstream", "downstream", or "both" |
max_depth | integer | 3 | Maximum traversal depth |
k | integer | 5 | Number of nodes per level |
Edge Types in Traversal
The system maintains several edge types that govern traversal behavior:
| Edge Type | Semantics | Created By |
|---|---|---|
CAUSED_BY | Upstream dependency | User or LLM |
SUPPORTS | Reinforcing relationship | LLM inference |
DERIVED_FROM | Consolidation origin | Consolidation engine |
CONTRADICTS | Conflicting memory | Contradiction detection |
RELATED_TO | Semantic similarity | Auto-linking |
Sources: src/genesys_memory/engine/contradiction.py:1-1
Auto-Linking Mechanism
When memories are stored, the system automatically links them to semantically similar existing memories. This creates the underlying graph structure that enables traversal.
Auto-Linking Process
- After storing a new memory, generate its embedding
- Perform vector search for top-K similar memories (k=4)
- Filter by similarity threshold (0.3 minimum score)
- Create
RELATED_TOedges for qualifying matches
graph TD
A[New Memory] --> B[Generate Embedding]
B --> C[Vector Search]
C --> D{score >= 0.3?}
D-->|No| E[Skip]
D-->|Yes| F{Cross-org?}
F-->|Yes| E
F-->|No| G{Edge exists?}
G-->|Yes| E
G-->|No| H[Create RELATED_TO edge]Sources: src/genesys_memory/mcp/tools.py:1-1
Auto-Link Constraints
The auto-linking mechanism enforces organizational boundaries:
- Org-scoped memories (
visibility=ORG) can only link to nodes with matchingorg_id - Cross-organization linking is prohibited
- Duplicate edges are prevented via existence check
if vis == Visibility.ORG:
if other_node.visibility != Visibility.ORG or other_node.org_id != org_id:
continue
already = await self.graph.edge_exists(node_id, str(other_node.id), EdgeType.RELATED_TO)
Sources: src/genesys_memory/mcp/tools.py:1-1
Contradiction Detection
The contradiction detection system identifies conflicting memories and creates appropriate edges to track them.
Detection Pipeline
graph LR
A[New Memory] --> B[Vector Search]
B --> C{Similarity > 0.85?}
C-->|No| D[Skip]
C-->|Yes| E[LLM Confirmation]
E --> F{Confirmed?}
F-->|No| D
F-->|Yes| G[Create CONTRADICTS edge]Detection Algorithm
The contradiction detection follows a two-stage approach:
- Vector Search Stage: Find highly similar candidates (>0.85 similarity)
- LLM Confirmation Stage: Use language model to verify actual contradiction
candidates = await graph.vector_search(new_node.embedding, k=20)
for candidate_node, sim_score in candidates:
similarity = 1.0 - sim_score if sim_score <= 1.0 else sim_score
if similarity < 0.85:
continue
is_contradiction, confidence, _ = await llm.check_contradiction(...)
Sources: src/genesys_memory/engine/contradiction.py:1-1
LLM Contradiction Check
The LLM provider compares the content of both memories and determines if they truly contradict:
prompt = f"""Compare these two memories and determine if they contradict each other:
Memory A: {content_a}
Memory B: {content_b}
Respond with JSON: {{"contradicts": bool, "confidence": 0.0-1.0, "reason": "..."}}"""
Sources: src/genesys_memory/engine/llm_provider.py:1-1
Causal Relationship Identification
The LLM provider can identify causal relationships between a new memory and existing memories, creating appropriate causal edges.
Relationship Types
| Type | Confidence Threshold | Description |
|---|---|---|
caused_by | > 0.6 | Direct causation |
supports | > 0.6 | Reinforcing evidence |
derived_from | > 0.6 | Semantic extraction |
Identification Process
prompt = (
"Given a new memory and a list of existing memories, identify causal relationships.\n\n"
f"New memory: {new_memory}\n\nExisting memories:\n{mem_lines}\n\n"
"For each causal relationship found, specify:\n"
"- target_id: the ID of the existing memory\n"
'- edge_type: one of "caused_by", "supports", "derived_from"\n'
"- confidence: 0.0 to 1.0\n"
"- reason: brief explanation\n\n"
"Only include relationships with confidence > 0.6."
)
Sources: src/genesys_memory/engine/llm_provider.py:1-1
Memory Consolidation
Consolidation converts episodic (short-lived) memories into semantic (long-term) representations, creating DERIVED_FROM edges to track the source memories.
Consolidation Workflow
graph TD
A[Episodic Memories] --> B[Fetch Content]
B --> C[LLM Consolidation]
C --> D[Generate Summary]
D --> E[Create Semantic Node]
E --> F[Create DERIVED_FROM Edges]
F --> G[Update Graph]Semantic Node Creation
The consolidation engine:
- Collects episodic memory contents
- Sends to LLM for summarization
- Generates new embedding for consolidated content
- Creates semantic memory node with
DERIVED_FROMedges
summary = await llm.consolidate([m.content_full or m.content_summary for m in matching])
embedding = await embeddings.embed(consolidated_text)
semantic_node = MemoryNode(
status=MemoryStatus.SEMANTIC,
content_summary=summary,
content_full=consolidated_text,
embedding=embedding,
...
)
for source_node in matching:
edge = MemoryEdge(
source_id=semantic_node.id,
target_id=source_node.id,
type=EdgeType.DERIVED_FROM,
weight=0.7,
)
await graph.create_edge(edge)
Sources: src/genesys_memory/engine/consolidation.py:1-1
Status Transitions Based on Graph Activity
The transition engine evaluates memories for promotion based on their graph connectivity.
Tagged → Active Promotion
Memories in TAGGED status are promoted to ACTIVE when they form connections in the causal graph:
tagged_nodes = await graph.get_nodes_by_status(MemoryStatus.TAGGED)
for node in tagged_nodes:
if node.visibility == Visibility.ORG:
continue
if not await graph.is_orphan(str(node.id)):
await graph.update_node(str(node.id), {"status": MemoryStatus.ACTIVE})
transitions.append({
"node_id": str(node.id),
"old": "tagged",
"new": "active",
"reason": "consolidation signal: edge formed",
})
Sources: src/genesys_memory/engine/transitions.py:1-1
Orphan Expiration
Tagged memories that remain disconnected for 24 hours are automatically expired:
age_hours = (datetime.now(timezone.utc) - node.created_at).total_seconds() / 3600
if age_hours > 24:
await graph.update_node(str(node.id), {"status": MemoryStatus.FADING})
Sources: src/genesys_memory/engine/transitions.py:1-1
Graph Storage Provider
The storage layer implements efficient graph operations with per-user isolation and edge indexing.
In-Memory Graph Implementation
The InMemoryGraphProvider provides graph storage with performance optimizations:
class InMemoryGraphProvider:
"""GraphStorageProvider backed by plain dicts with per-user isolation."""
# Edge indexes: {user_id: {node_id: [edges]}}
_idx_by_source: dict[str, dict[str, list[MemoryEdge]]] = {}
_idx_by_target: dict[str, dict[str, list[MemoryEdge]]] = {}
Sources: src/genesys_memory/storage/memory.py:1-1
Performance Characteristics
| Operation | Complexity | Notes |
|---|---|---|
| Edge lookup by source | O(degree) | Indexed by _idx_by_source |
| Edge lookup by target | O(degree) | Indexed by _idx_by_target |
| Is orphan check | O(degree) | Uses edge indexes |
| Full graph scan | O(total_edges) | Only for full traversals |
Persistence Support
The in-memory provider supports JSON persistence for survival across process restarts:
def __init__(self, persist_path: str | None = None):
self._persist_path = Path(persist_path) if persist_path else None
self._save_depth = 0
self._dirty = False
Sources: src/genesys_memory/storage/memory.py:1-1
MCP Tools Reference
memory_traverse
Walk the causal graph from a given memory node.
{
"node_id": "uuid-string",
"direction": "upstream | downstream | both",
"max_depth": 3,
"k": 5
}
memory_explain
Explain why a memory exists by showing its causal chain.
{
"node_id": "uuid-string",
"include_context": true
}
Returns the memory with causal_basis (immediate neighbors) and causal_chain (full lineage).
Related Systems
- Scoring Engine: Applies the decay formula
decay_score = relevance × connectivity × reactivationwhere connectivity is derived from graph structure - Reactivation Tracking: Updates
last_reactivated_attimestamps when memories are traversed - Pruning System: Uses connectivity metrics to determine which memories to prune
Sources: README.md:1-1
Sources: src/genesys_memory/mcp/tools.py:1-1
Storage Backend Comparison
Related topics: Storage Provider Implementation
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Storage Provider Implementation
Storage Backend Comparison
Genesys supports multiple storage backends to accommodate different deployment scenarios, from zero-dependency local development to production-scale distributed systems. This page provides a comprehensive comparison of available backends, their architectures, and guidance for selecting the appropriate backend for your use case.
Architecture Overview
Genesys implements a provider abstraction pattern where all data access flows through standardized interfaces defined in storage/base.py. This design ensures that business logic remains decoupled from storage implementation details, enabling seamless backend switching without code changes.
graph TD
A["🔷 MCP Tools Layer<br/>(tools.py)"] --> B["📦 Storage Provider Interface<br/>(base.py)"]
B --> C1["🟢 In-Memory Provider"]
B --> C2["🔵 Postgres Provider"]
B --> C3["🟡 Obsidian Provider"]
B --> C4["🟣 FalkorDB Provider"]
B --> C5["⚪ Custom Provider"]
C1 --> D1["Dict + JSON File"]
C2 --> D2["PostgreSQL + pgvector"]
C3 --> D3["SQLite + File System"]
C4 --> D4["Redis Graph"]
style A fill:#4a90d9,color:#fff
style B fill:#f5a623,color:#fff
style D1 fill:#7ed321,color:#fff
style D2 fill:#4a90d9,color:#fff
style D3 fill:#f5a623,color:#fff
style D4 fill:#9013fe,color:#fffKey Design Principle: Storage abstraction is mandatory. All data access goes through provider interfaces in storage/base.py. Never import a database client directly in business logic. Sources: CONTRIBUTING.md:1
Storage Provider Interfaces
The storage layer is composed of three interconnected provider types that handle different aspects of memory management.
Provider Types
| Provider | Responsibility | Key Methods |
|---|---|---|
| GraphStorageProvider | Nodes, edges, causal relationships | upsert_node, get_node, delete_node, upsert_edge, get_neighbors |
| CacheProvider | Short-term caching, TTL management | get, set, delete, exists |
| EmbeddingProvider | Vector embedding generation | embed, batch_embed |
Sources: src/genesys_memory/storage/base.py:1
Memory Node Structure
Every memory in Genesys is represented as a MemoryNode with the following core attributes:
class MemoryNode(BaseModel):
id: uuid.UUID
status: MemoryStatus # ACTIVE, DORMANT, FADING, PRUNED
content_summary: str # Max 200 chars
content_full: str | None
embedding: list[float] | None
# Lifecycle scores
decay_score: float = 1.0
causal_weight: int = 0
reactivation_count: int = 0
# Core memory
pinned: bool = False
category: str | None
Sources: src/genesys_memory/models/node.py:1
Available Backends
1. In-Memory Backend (Built-in)
The default backend with zero external dependencies. Suitable for development, testing, and lightweight deployments.
#### Features
- Built-in dict-based storage with per-user isolation
- Optional JSON file persistence via
GENESYS_PERSIST_PATH - No Docker, database, or API keys required for basic operation
- Fast startup, ideal for local development
#### Architecture
class InMemoryCacheProvider:
"""CacheProvider backed by a plain dict."""
def __init__(self) -> None:
self._data: dict[str, str] = {}
class InMemoryGraphProvider:
"""GraphStorageProvider backed by plain dicts with per-user isolation."""
# State persisted to JSON if persist_path is set
Sources: src/genesys_memory/storage/memory.py:1
#### Configuration
| Variable | Required | Default | Description |
|---|---|---|---|
GENESYS_BACKEND | No | memory | Set to memory explicitly |
GENESYS_PERSIST_PATH | No | None | Path for JSON state persistence |
OPENAI_API_KEY | If using OpenAI embeddings | - | For vector search |
GENESYS_EMBEDDER | No | openai | Or local for no API key |
#### Use Cases
- Local development and testing
- Single-user CLI applications
- Prototyping and evaluation
- When infrastructure overhead must be minimized
Sources: src/genesys_memory/storage/base.py:1
Storage Provider Implementation
Related topics: Storage Backend Comparison, System Architecture
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Storage Backend Comparison, System Architecture
Storage Provider Implementation
Overview
The Storage Provider Implementation in Genesys provides a modular, pluggable architecture for persisting memory nodes and their causal relationships. This abstraction layer enables the memory system to operate with different storage backends—from simple in-memory dictionaries to production-grade databases like PostgreSQL with pgvector, or even Obsidian vaults and FalkorDB—without changing the core memory logic.
The storage layer is composed of four provider types that work together:
- GraphStorageProvider: Manages
MemoryNodeentities andMemoryEdgerelationships (the causal graph) - CacheProvider: Provides fast key-value caching for temporary data
- EmbeddingProvider: Generates and retrieves vector embeddings for semantic search
- EventBusProvider: Handles event-driven communication between system components
Sources: src/genesys_memory/storage/base.py
Sources: src/genesys_memory/storage/base.py
MCP Tools Reference
Related topics: Configuration Guide, Getting Started with Genesys
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Configuration Guide, Getting Started with Genesys
MCP Tools Reference
The Model Context Protocol (MCP) Tools layer is the primary interface through which AI agents interact with the Genesys memory system. This module exposes all memory operations as callable tools via the MCP stdio transport, enabling seamless integration with Claude Desktop and other MCP-compatible clients.
Architecture Overview
The MCP tools layer sits between the MCP protocol server and the core Genesys engine. It handles:
- Tool dispatching: Routing tool calls to appropriate engine methods
- Context injection: Providing user/org context for multi-tenant support
- Permission validation: Ensuring callers have appropriate access rights
- Response formatting: Converting engine results into MCP-compatible format
graph TD
A[MCP Client] -->|call_tool| B[MCP Server]
B -->|dispatch| C[Tool Dispatcher]
C -->|inject context| D[Context Managers]
D -->|verify permissions| E[Core Memory Engine]
E -->|execute| F[Storage Providers]
F -->|graph ops| G[Vector DB / FalkorDB / Obsidian]
C -->|format response| H[TextContent Response]Tool Registry
All available MCP tools are registered in server.py with their schemas and dispatch mappings.
Tool Dispatch Table
| Tool Name | Required Args | Optional Args | Description |
|---|---|---|---|
memory_store | content | source_session, related_to, visibility, org_id | Store a new memory |
memory_recall | query | k, max_results | Hybrid search recall |
memory_search | query | filters, k | Filtered vector search |
memory_traverse | node_id | depth, edge_types | Graph traversal |
memory_explain | node_id | - | Score breakdown explanation |
pin_memory | node_id | - | Pin to core status |
unpin_memory | node_id | - | Unpin and re-evaluate |
list_core_memories | - | category | List core memories |
delete_memory | node_id | - | Permanently delete |
memory_stats | - | - | Get graph statistics |
set_core_preferences | - | auto, approval, excluded | Configure core categories |
promote_to_org | node_id, org_id | action, dry_run | Promote to org visibility |
Sources: src/genesys_memory/server.py:15-60
Memory Store Tool
Creates a new memory node with automatic causal edge discovery.
Input Schema
{
"type": "object",
"required": ["content"],
"properties": {
"content": { "type": "string" },
"source_session": { "type": "string" },
"related_to": {
"type": "array",
"items": { "type": "string" }
},
"visibility": {
"type": "string",
"enum": ["private", "org", "public"],
"default": "private"
},
"org_id": { "type": "string" }
}
}
Behavior
- Generates embedding for content via configured embedder
- Creates
MemoryNodewithACTIVEstatus - Optionally links to existing memories via
related_to - Triggers causal edge discovery via LLM provider
- Emits
MemoryStoredEventto event bus
Sources: src/genesys_memory/mcp/tools.py:1-50
Memory Recall Tool
Implements hybrid search combining vector similarity, keyword matching, and graph spreading activation.
Input Schema
{
"type": "object",
"required": ["query"],
"properties": {
"query": { "type": "string" },
"k": { "type": "integer", "default": 10 },
"max_results": { "type": "integer" }
}
}
Search Algorithm
graph LR
A[Query Text] --> B[Vector Embedding]
A --> C[Keyword Extraction]
B --> D[Vector Similarity Search]
C --> E[BM25 Ranking]
D --> F[Initial Candidates]
E --> F
F --> G[Graph Spreading Activation]
G --> H[Score Normalization]
H --> I[Top K Results]The k parameter controls the number of initial vector candidates considered. Spreading activation propagates through causal edges, boosting memories connected to initially-matched nodes.
Sources: src/genesys_memory/engine/llm_provider.py:20-60
Memory Traverse Tool
Walks the causal graph from a starting node using configurable depth and edge type filtering.
Input Schema
{
"type": "object",
"required": ["node_id"],
"properties": {
"node_id": { "type": "string" },
"depth": { "type": "integer", "default": 2 },
"edge_types": {
"type": "array",
"items": { "type": "string" }
}
}
}
Traversal Behavior
| Depth | Nodes Explored | Description |
|---|---|---|
| 1 | Direct neighbors | Immediate causal relationships |
| 2 | Friends-of-friends | Secondary connections |
| N | N-level reach | Deeper causal chains |
Edge type filtering supports: caused_by, supports, derived_from, reactivated, contradicts
Memory Explain Tool
Returns the score breakdown for a memory node, revealing why it exists and how it scores on each axis.
Input Schema
{
"type": "object",
"required": ["node_id"],
"properties": {
"node_id": { "type": "string" }
}
}
Score Components
The decay formula is multiplicative:
decay_score = relevance × connectivity × reactivation
| Component | Factor | Description |
|---|---|---|
| Relevance | Time-based decay | How recently accessed |
| Connectivity | Causal weight | Number/type of edges |
| Reactivation | Frequency pattern | Recall history |
Sources: src/genesys_memory/models/node.py:15-45
Pin/Unpin Memory Tools
Controls core memory status for individual nodes.
pin_memory
{
"type": "object",
"required": ["node_id"],
"properties": {
"node_id": { "type": "string" }
}
}
Pinned memories are immune to automatic pruning. Setting pinned=true also sets promotion_reason to indicate manual promotion.
unpin_memory
{
"type": "object",
"required": ["node_id"],
"properties": {
"node_id": { "type": "string" }
}
}
Unpinning triggers re-evaluation for automatic core promotion based on category preferences.
List Core Memories Tool
Retrieves all memories marked as core (pinned or auto-promoted).
Input Schema
{
"type": "object",
"properties": {
"category": { "type": "string" }
}
}
Response Structure
{
"cores": [
{
"id": "uuid",
"content_summary": "...",
"category": "project_context",
"promotion_reason": "auto|manual",
"pinned": true
}
]
}
Set Core Preferences Tool
Configures automatic core memory categorization rules.
Input Schema
{
"type": "object",
"properties": {
"auto": {
"type": "array",
"items": { "type": "string" }
},
"approval": {
"type": "array",
"items": { "type": "string" }
},
"excluded": {
"type": "array",
"items": { "type": "string" }
}
}
}
| Category | Behavior |
|---|---|
auto | Auto-promoted to core when category matches |
approval | Queued for user approval before promotion |
excluded | Never auto-promoted, even if frequently accessed |
Permission Model
All tools enforce permission checks before execution.
Permission Hierarchy
graph TD
A[Tool Call] --> B{_caller_uid set?}
B -->|No| C[PermissionError]
B -->|Yes| D{Node Owner?}
D -->|Own| E[Allow]
D -->|Admin + Org| F[Check Org Membership]
F -->|Member| E
F -->|Not Member| CPermission Functions
| Function | Purpose |
|---|---|
_caller_uid() | Returns current user ID from context |
_caller_owns_node(node) | Verifies ownership or admin org membership |
_is_edge_stale(edge) | Checks if edge requires refresh |
Sources: src/genesys_memory/mcp/tools.py:25-50
Visibility Levels
Memory nodes support three visibility levels:
| Level | Access | Description |
|---|---|---|
private | Owner only | Personal memories |
org | Organization members | Shared team context |
public | All users | Knowledge base entries |
promote_to_org Tool
Promotes a private memory to org visibility:
{
"type": "object",
"required": ["node_id", "org_id"],
"properties": {
"node_id": { "type": "string" },
"org_id": { "type": "string" },
"action": {
"type": "string",
"enum": ["keep_private", "promote_all", "delete_links"],
"default": "keep_private"
},
"dry_run": { "type": "boolean", "default": false }
}
}
Actions:
keep_private: Only this node becomes org-visiblepromote_all: All causally-linked nodes also promoteddelete_links: Remove private edges before promotion
Context Managers
The tools layer uses FastAPI-style context variables for multi-tenant support:
current_user_id # Active user identifier
current_org_ids # List of user's org memberships
current_user_role # "admin", "member", etc.
Sources: src/genesys_memory/context.py
Response Format
All tool responses are returned as list[TextContent] with type "text":
[
{
"type": "text",
"text": "JSON serialized response"
}
]
Error responses include structured error messages:
[
{
"type": "text",
"text": "Error: Permission denied for memory node abc-123"
}
]
Integration with MCP Transport
The stdio transport enables direct connection to Claude Desktop:
# Claude Desktop config
{
"mcpServers": {
"genesys": {
"url": "http://localhost:8000/mcp"
}
}
}
Or for Claude Code CLI:
claude mcp add --transport http genesys http://localhost:8000/mcp
Sources: README.md:80-100
Summary
The MCP Tools layer provides a complete interface for AI memory operations:
- 12 core tools covering CRUD, traversal, and lifecycle management
- Multi-tenant support via context injection and permission checks
- Three visibility levels (private, org, public)
- Hybrid search combining vectors, keywords, and graph traversal
- Core memory automation via category-based promotion rules
Sources: src/genesys_memory/server.py:15-60
Configuration Guide
Related topics: Getting Started with Genesys
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Getting Started with Genesys
Configuration Guide
This guide covers all configuration options available in Genesys, including environment variables, storage backends, embedding providers, and LLM integration settings.
Overview
Genesys supports multiple configuration options to accommodate different deployment scenarios, from local development with zero dependencies to production-grade deployments with persistent storage. Configuration is primarily driven by environment variables, with sensible defaults provided for most settings.
The configuration system enables:
- Multi-backend storage: Choose between in-memory, PostgreSQL, Obsidian vault, or FalkorDB
- Flexible embedding: Use OpenAI embeddings or local sentence-transformers
- LLM integration: Optional Anthropic API for memory consolidation and processing
- Multi-tenancy: Support for user and organization-level memory isolation
Environment Variables Reference
Core Configuration
| Variable | Required | Default | Description |
|---|---|---|---|
OPENAI_API_KEY | No* | - | OpenAI API key for embedding generation. Not required if GENESYS_EMBEDDER=local |
ANTHROPIC_API_KEY | No | - | Anthropic API key for LLM-based memory processing (consolidation, contradiction detection) |
GENESYS_BACKEND | No | memory | Storage backend: memory, postgres, obsidian, or falkordb |
GENESYS_EMBEDDER | No | openai | Embedding provider: openai or local |
GENESYS_USER_ID | No | - | Default user ID for single-tenant mode |
GENESYS_PERSIST_PATH | No | - | File path for persisting state in memory backend mode |
*Required unless using local embedder
Sources: README.md
Backend-Specific Configuration
| Variable | Required For | Default | Description |
|---|---|---|---|
DATABASE_URL | postgres | - | PostgreSQL connection string (e.g., postgresql://user:pass@localhost:5432/genesys) |
OBSIDIAN_VAULT_PATH | obsidian | Auto-detect | Path to your Obsidian vault directory |
FALKORDB_HOST | falkordb | localhost | FalkorDB host address |
CLERK_SECRET_KEY | Seed scripts | - | Clerk authentication secret for demo seeding |
CLERK_USER_ID | Seed scripts | - | Clerk user ID for demo seeding |
Sources: README.md
Storage Backends
Genesys is designed to work with multiple storage backends, each suited for different use cases.
Backend Comparison
| Backend | Dependencies | Use Case | Persistence |
|---|---|---|---|
memory | None | Local development, quick testing | Ephemeral (state lost on restart) |
postgres | PostgreSQL + pgvector | Production deployments | Persistent |
obsidian | Obsidian vault | Local-first knowledge management | File-based |
falkordb | FalkorDB | Graph-native traversal | Persistent |
Sources: README.md
Memory Backend (Default)
The in-memory backend requires no additional dependencies and is ideal for exploration.
GENESYS_BACKEND=memory
To persist state across restarts:
GENESYS_BACKEND=memory
GENESYS_PERSIST_PATH=.genesys_state.json
Sources: README.md
PostgreSQL Backend
Requires PostgreSQL with pgvector extension for vector similarity search.
GENESYS_BACKEND=postgres
DATABASE_URL=postgresql://genesys:genesys@localhost:5432/genesys
Start PostgreSQL with Docker:
docker compose up -d postgres
alembic upgrade head
uvicorn genesys.api:app --port 8000
Sources: README.md
Obsidian Backend
Integrates directly with your Obsidian vault. Markdown files become memory nodes, and [[wikilinks]] become causal edges.
GENESYS_BACKEND=obsidian
OBSIDIAN_VAULT_PATH=/path/to/your/vault
If OBSIDIAN_VAULT_PATH is not set, Genesys auto-detects by looking for .obsidian/ in:
~/Documents/personal~/Documents/Obsidian~/obsidian
Sources: README.md
FalkorDB Backend
Uses FalkorDB (Redis-based graph database) for native graph traversal.
GENESYS_BACKEND=falkordb
FALKORDB_HOST=localhost
Start FalkorDB:
docker compose up -d falkordb
uvicorn genesys.api:app --port 8000
Sources: README.md
Embedding Configuration
OpenAI Embeddings (Default)
Uses OpenAI's embedding models for vector representation.
GENESYS_EMBEDDER=openai
OPENAI_API_KEY=sk-...
Local Embeddings (No API Key Required)
Uses sentence-transformers for fully local embedding generation. Downloads all-MiniLM-L6-v2 (~80 MB) on first use.
GENESYS_EMBEDDER=local
For local Obsidian mode with zero external dependencies:
GENESYS_BACKEND=obsidian
GENESYS_EMBEDDER=local
OBSIDIAN_VAULT_PATH=/path/to/your/vault
# No OPENAI_API_KEY needed
Sources: README.md
Memory Node Model
The core data model for memories in Genesys. Key configuration-related fields:
class MemoryNode(BaseModel):
id: uuid.UUID = Field(default_factory=uuid.uuid4)
status: MemoryStatus = MemoryStatus.ACTIVE
content_summary: str = Field(max_length=200)
content_full: str | None = None
embedding: list[float] | None = None
# Timestamps
created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
last_accessed_at: datetime
last_reactivated_at: datetime
# Lifecycle scores
decay_score: float = 1.0
causal_weight: int = 0
reactivation_count: int = 0
# Core memory
pinned: bool = False
promotion_reason: str | None = None
Sources: src/genesys_memory/models/node.py
LLM Provider Configuration
The LLM provider handles memory consolidation and causal relationship detection.
Causal Link Detection
When storing new memories, the LLM provider can automatically identify causal relationships with existing memories:
prompt = (
"Given a new memory and a list of existing memories, identify causal relationships.\n\n"
f"New memory: {new_memory}\n\nExisting memories:\n{mem_lines}\n\n"
"For each causal relationship found, specify:\n"
"- target_id: the ID of the existing memory\n"
'- edge_type: one of "caused_by", "supports", "derived_from"\n'
"- confidence: 0.0 to 1.0\n"
"- reason: brief explanation of why this relationship exists\n\n"
"Only include relationships with confidence > 0.6.\n"
"Respond with ONLY a JSON array of objects, no other text."
)
Configuration requires ANTHROPIC_API_KEY for LLM-based processing. Edge types include:
caused_bysupportsderived_from
Sources: src/genesys_memory/engine/llm_provider.py
MCP Server Configuration
The MCP (Model Context Protocol) server exposes Genesys functionality as tools. Configure the MCP endpoint in your AI client's configuration.
Claude Desktop
Add to claude_desktop_config.json:
{
"mcpServers": {
"genesys": {
"url": "http://localhost:8000/mcp"
}
}
}
Claude Code
claude mcp add --transport http genesys http://localhost:8000/mcp
MCP Tools Available
| Tool | Description |
|---|---|
memory_store | Store a new memory, optionally linking to related memories |
memory_recall | Recall memories by natural language query (vector + graph) |
memory_search | Search memories with filters (status, date range, keyword) |
memory_traverse | Walk the causal graph from a given memory node |
memory_explain | Explain why a memory exists and its causal chain |
memory_stats | Get memory system statistics |
pin_memory | Pin a memory so it's never forgotten |
unpin_memory | Unpin a previously pinned memory |
delete_memory | Permanently delete a memory |
list_core_memories | List core memories, optionally filtered by category |
set_core_preferences | Set user preferences for core memory categories |
Sources: README.md
Quick Start Configurations
Minimal Setup (Zero Dependencies)
# No .env file needed - defaults work out of the box
pip install genesys-memory
uvicorn genesys.api:app --port 8000
Fully Local with Obsidian
GENESYS_BACKEND=obsidian
GENESYS_EMBEDDER=local
OBSIDIAN_VAULT_PATH=/path/to/your/vault
Production with PostgreSQL
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
GENESYS_BACKEND=postgres
DATABASE_URL=postgresql://genesys:genesys@localhost:5432/genesys
Multi-Tenant with Organizations
OPENAI_API_KEY=sk-...
GENESYS_BACKEND=postgres
DATABASE_URL=postgresql://genesys:genesys@localhost:5432/genesys
Sources: README.md
Configuration Flow
graph TD
A[Application Start] --> B{Load Environment Variables}
B --> C{GENESYS_BACKEND?}
C -->|memory| D[In-Memory Storage]
C -->|postgres| E[PostgreSQL + pgvector]
C -->|obsidian| F[Obsidian Vault]
C -->|falkordb| G[FalkorDB]
H{GENESYS_EMBEDDER?}
H -->|openai| I[OpenAI Embeddings]
H -->|local| J[Local sentence-transformers]
D --> K[Initialize MCP Server]
E --> K
F --> K
G --> K
I --> L[Ready]
J --> L
K --> M[Register Tools]
M --> LEngine Thresholds
Engine thresholds such as decay rates, scoring multipliers, and transition thresholds are configurable through environment variables. These values are defined in engine/config.py and should not be hardcoded.
For the most current threshold configurations, refer to the source file:
# Refer to src/genesys_memory/engine/config.py for threshold values
Sources: CONTRIBUTING.md
See Also
- Contributing Guide - Development setup and coding standards
- README.md - Project overview and features
- Benchmarks - Performance testing configurations
Sources: README.md
Doramagic Pitfall Log
Source-linked risks stay visible on the manual page so the preview does not read like a recommendation.
Users may get misleading failures or incomplete behavior unless configuration is checked carefully.
The project should not be treated as fully validated until this signal is reviewed.
Users cannot judge support quality until recent activity, releases, and issue response are checked.
The project may affect permissions, credentials, data exposure, or host boundaries.
Doramagic Pitfall Log
Doramagic extracted 7 source-linked risk signals. Review them before installing or handing real data to the project.
1. Configuration risk: Configuration risk needs validation
- Severity: medium
- Finding: Configuration risk is backed by a source signal: Configuration risk needs validation. Treat it as a review item until the current version is checked.
- User impact: Users may get misleading failures or incomplete behavior unless configuration is checked carefully.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: capability.host_targets | github_repo:1207565616 | https://github.com/rishimeka/genesys | host_targets=mcp_host, claude
2. Capability assumption: README/documentation is current enough for a first validation pass.
- Severity: medium
- Finding: README/documentation is current enough for a first validation pass.
- User impact: The project should not be treated as fully validated until this signal is reviewed.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: capability.assumptions | github_repo:1207565616 | https://github.com/rishimeka/genesys | README/documentation is current enough for a first validation pass.
3. Maintenance risk: Maintainer activity is unknown
- Severity: medium
- Finding: Maintenance risk is backed by a source signal: Maintainer activity is unknown. Treat it as a review item until the current version is checked.
- User impact: Users cannot judge support quality until recent activity, releases, and issue response are checked.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: evidence.maintainer_signals | github_repo:1207565616 | https://github.com/rishimeka/genesys | last_activity_observed missing
4. Security or permission risk: no_demo
- Severity: medium
- Finding: no_demo
- User impact: The project may affect permissions, credentials, data exposure, or host boundaries.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: downstream_validation.risk_items | github_repo:1207565616 | https://github.com/rishimeka/genesys | no_demo; severity=medium
5. Security or permission risk: no_demo
- Severity: medium
- Finding: no_demo
- User impact: The project may affect permissions, credentials, data exposure, or host boundaries.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: risks.scoring_risks | github_repo:1207565616 | https://github.com/rishimeka/genesys | no_demo; severity=medium
6. Maintenance risk: issue_or_pr_quality=unknown
- Severity: low
- Finding: issue_or_pr_quality=unknown。
- User impact: Users cannot judge support quality until recent activity, releases, and issue response are checked.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: evidence.maintainer_signals | github_repo:1207565616 | https://github.com/rishimeka/genesys | issue_or_pr_quality=unknown
7. Maintenance risk: release_recency=unknown
- Severity: low
- Finding: release_recency=unknown。
- User impact: Users cannot judge support quality until recent activity, releases, and issue response are checked.
- Recommended check: Open the linked source, confirm whether it still applies to the current version, and keep the first run isolated.
- Evidence: evidence.maintainer_signals | github_repo:1207565616 | https://github.com/rishimeka/genesys | release_recency=unknown
Source: Doramagic discovery, validation, and Project Pack records
Community Discussion Evidence
These external discussion links are review inputs, not standalone proof that the project is production-ready.
Count of project-level external discussion links exposed on this manual page.
Open the linked issues or discussions before treating the pack as ready for your environment.
Community Discussion Evidence
Doramagic exposes project-level community discussion separately from official documentation. Review these links before using genesys with real data or production workflows.
- Configuration risk needs validation - GitHub / issue
Source: Project Pack community evidence and pitfall evidence