You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A TypeScript knowledge-graph library for AI agents and applications that need
structured long-term memory. Entities, relations, and observations with
multiple storage backends (JSONL, SQLite, PostgreSQL), advanced search (BM25, TF-IDF,
fuzzy, semantic, hybrid, temporal, LLM-planned), graph algorithms, bitemporal
versioning, RBAC, and a complete Agent Memory System (session lifecycle,
working / episodic / semantic / procedural memory, decay, salience, consolidation,
causal reasoning, world-model orchestration).
Powers @danielsimonjr/memory-mcp,
a Model Context Protocol server for Claude and other MCP clients. The
library and the MCP server share the same core; this package is published
independently so non-MCP applications can use it directly.
For a runnable CLI: npx -p @danielsimonjr/memoryjs memory --help.
End-to-end smoke test against a fresh temp graph (~30 ops)
memory smoke --keep --verbose
Diagnostic snapshot + graph health checks
memory diag / memory health
Orphan + missing-parent + cycle detection with optional repair
memory check [--apply]
Rebuild ranked + spell indexes
memory reindex [--ranked|--spell]
Inspect a single entity verbosely
memory show <name>
Hierarchy tree (JSON or --ascii)
memory tree [root]
Search-cache stats / clear
memory cache stats | clear
Interactive REPL
memory interactive
Installation
npm install @danielsimonjr/memoryjs
Requirements
Node.js >= 18.0.0
TypeScript >= 5.0 (for development)
Quick Start
1. Initialize storage
import{ManagerContext}from'@danielsimonjr/memoryjs';// JSONL storage (default, human-readable)constctx=newManagerContext('./memory.jsonl');// Or SQLite (set MEMORY_STORAGE_TYPE=sqlite in the environment)constsqliteCtx=newManagerContext('./memory.db');
2. Create entities
awaitctx.entityManager.createEntities([{name: 'TypeScript',entityType: 'language',observations: ['A typed superset of JavaScript'],tags: ['programming','frontend'],importance: 8,},{name: 'Node.js',entityType: 'runtime',observations: ['JavaScript runtime built on V8'],tags: ['backend','server'],},]);
// Auto-select the best methodconstauto=awaitctx.searchManager.autoSearch('JavaScript');// Substring + tag searchconstnodes=awaitctx.searchManager.searchNodes('JavaScript');// Boolean (AND / OR / NOT) with an AST parserconstboth=awaitctx.searchManager.booleanSearch('TypeScript AND runtime');// Fuzzy (typo-tolerant; N-gram pre-filtered)constfuzzy=awaitctx.searchManager.fuzzySearch('Typscript',{threshold: 0.7});// Ranked TF-IDF / BM25constranked=awaitctx.rankedSearch.searchNodesRanked('runtime environment',undefined,undefined,undefined,10);// Active retrieval — iterative query rewriting until coverage thresholdconstadaptive=awaitctx.activeRetrieval.adaptiveRetrieve({query: 'memory leak'});console.log(adaptive.bestResults,adaptive.bestCoverage,adaptive.rounds);
5. Multi-agent collaboration
// Optimistic concurrency control — fail loudly on stale writestry{awaitctx.entityManager.updateEntity('Alice',{importance: 9},{expectedVersion: 3});}catch(e){if(einstanceofError&&e.name==='VersionConflictError'){// Refetch + retry}}// Synthesize a view across agents + resolve conflictsconstagent=ctx.agentMemory();constsynth=awaitagent.collaborativeSynthesis.synthesize('Alice');constwinners=agent.collaborativeSynthesis.resolveConflicts(synth,{strategy: 'highest_confidence',});// Enforce attribution on every mutationimport{CollaborationAuditEnforcer,AuditLog}from'@danielsimonjr/memoryjs';constenforcer=newCollaborationAuditEnforcer(ctx.entityManager,newAuditLog('./audit.jsonl'),);awaitenforcer.createEntities([{name: 'X',entityType: 't',observations: ['fact']}],'agent-alice',// throws AttributionRequiredError if agentId is missing);
6. Bitemporal versioning
// Mark an entity as no longer valid at a specific timeawaitctx.entityManager.invalidateEntity('OldFact','2025-12-31T00:00:00Z');// Time-travel queryconstpast=awaitctx.entityManager.entityAsOf('Alice','2024-06-15T00:00:00Z');// Per-observation validity windowsawaitctx.observationManager.invalidateObservation('Alice','works at Acme','2024-12-31T00:00:00Z',);constobsAtTime=awaitctx.observationManager.observationsAsOf('Alice','2024-06-15T00:00:00Z',);
7. Causal reasoning and world model
// Forward inference — "what does X cause?"consteffects=awaitctx.causalReasoner.findEffects('rain',['flooding','erosion']);// Counterfactual — "what if we remove this edge?"constsurviving=awaitctx.causalReasoner.counterfactual({seed: 'rain',removeFrom: 'rain',removeTo: 'flooding',predict: 'flooding',});// World-state snapshot + diffconstbefore=awaitctx.worldModelManager.getCurrentState();// ... mutations ...constafter=awaitctx.worldModelManager.getCurrentState();constchange=ctx.worldModelManager.detectStateChange(before,after);
8. RBAC and PII redaction
// Grant a roleawaitctx.roleAssignmentStore.assign({agentId: 'alice',role: 'writer',resourceType: 'entity',});ctx.rbacMiddleware.checkPermission('alice','write','entity');// true// Redact PII from exports / logsimport{PiiRedactor}from'@danielsimonjr/memoryjs';constredactor=newPiiRedactor();constcleanGraph=redactor.redactGraph(graph);const{ text, stats }=redactor.redactWithStats(observation);
Core Concepts
Entity
The primary node in the knowledge graph. Required fields are name, entityType,
and observations; the rest are optional and unlock specific features:
interfaceEntity{name: string;// Unique identifierentityType: string;// Classification (person, project, concept, …)observations: string[];// Atomic facts about the entityparentId?: string;// Parent entity for hierarchical nestingtags?: string[];// Lowercase tags for categorisationimportance?: number;// 0–10 scale for prioritisationcreatedAt?: string;// ISO 8601lastModified?: string;// ISO 8601// Freshnessttl?: number;// Seconds until staleconfidence?: number;// [0, 1] belief strength// Project scoping + supersessionprojectId?: string;// Multi-project isolationversion?: number;// Drives optimistic concurrency on updatesparentEntityName?: string;rootEntityName?: string;isLatest?: boolean;supersededBy?: string;// Memory-engine deduplicationcontentHash?: string;// SHA-256 for O(1) exact-equality dedup// Bitemporal validity (orthogonal to supersession)validFrom?: string;validUntil?: string;observationMeta?: Array<{content: string;validFrom?: string;validUntil?: string;recordedAt?: string;}>;}
A discrete atomic fact about an entity. Use addObservations() to append without
overwriting; combined with the bitemporal axis and per-observation validFrom /
validUntil you can preserve historical state instead of mutating in place.
ManagerContext
The central facade. Construct it with a storage-path string; every manager is
exposed as a property with lazy initialisation:
// AND — both terms must matchawaitctx.searchManager.booleanSearch('TypeScript AND runtime');// OR — either term matchesawaitctx.searchManager.booleanSearch('frontend OR backend');// NOT — exclude termawaitctx.searchManager.booleanSearch('JavaScript NOT browser');// Groupingawaitctx.searchManager.booleanSearch('(TypeScript OR JavaScript) AND server');
HybridSearchManager combines three signal layers. Instantiate it directly —
it is exported from the package but not wired onto ManagerContext because the
weighting + filter configuration is application-specific.
// Shortest path between entities (BFS)constresult=awaitctx.graphTraversal.findShortestPath('A','Z');console.log(result.path);// ['A', 'B', 'C', 'Z']console.log(result.distance);// 3// All paths with a depth boundconstall=awaitctx.graphTraversal.findAllPaths('A','Z',{maxDepth: 5});// → [['A', 'B', 'Z'], ['A', 'C', 'D', 'Z'], …]
Centrality
Each centrality algorithm has its own method (no unified getCentrality() — the
algorithms have different parameters and return shapes):
constdegree=awaitctx.graphTraversal.calculateDegreeCentrality();constbetween=awaitctx.graphTraversal.calculateBetweennessCentrality();constpagerank=awaitctx.graphTraversal.calculatePageRank();consthits=awaitctx.graphTraversal.calculateHITS();// Each returns a Map<entityName, score>
// Returns a TraversalResult { visited, edges, depthMap }constbfs=ctx.graphTraversal.bfs('startNode',{maxDepth: 3});constdfs=ctx.graphTraversal.dfs('startNode');
Agent Memory System
A memory system for AI agents with session lifecycle, working / episodic /
semantic / procedural memory, decay, salience, multi-agent visibility, and
specialised memory types (prospective, failure, plan, reflection, heuristic,
decision rationale, project context, tool affordance).
Key components
Component
Purpose
AgentMemoryManager
Unified facade for the system
SessionManager
Session lifecycle (start / end / restore / checkpoint)
WorkingMemoryManager
Short-term, session-scoped memories with promotion
EpisodicMemoryManager
Timeline-based event memories
DecayEngine
Time-based importance decay
SalienceEngine
Context-aware memory scoring
MultiAgentMemoryManager
Cross-agent memory with visibility controls
ConflictResolver
Resolution strategies for concurrent updates
Quick start
import{ManagerContext}from'@danielsimonjr/memoryjs';constctx=newManagerContext('./memory.jsonl');constagent=ctx.agentMemory();// Start a sessionconstsession=awaitagent.startSession({agentId: 'my-agent'});// Add working memoryawaitagent.addWorkingMemory({sessionId: session.name,content: 'User prefers dark mode',importance: 7,});// Episodic eventawaitagent.createEpisode('Completed onboarding flow',{sessionId: session.name,importance: 8,});// Retrieve context for an LLM prompt (token-budgeted)constcontext=awaitagent.retrieveForContext({maxTokens: 2000,includeEpisodic: true,});// End sessionawaitagent.endSession(session.name);
Memory types
typeMemoryType=|'working'// Short-term, session-scoped; may be promoted|'episodic'// Timeline-based event memories|'semantic'// Long-term factual knowledge|'procedural'// Executable procedures with feedback refinement|'prospective'// Intentions-to-act at a future time / event / condition|'failure'// Pre-task failure lookup keyed on applicability_hint|'plan'// Hierarchical goal trees with sub-tasks + acceptance criteria|'reflection'// Additive derived insights with content-hash dedup|'heuristic';// Condition → action guidelines
Each specialised type has a dedicated manager on ManagerContext —
ctx.prospectiveMemory, ctx.failureManager, ctx.plan, ctx.reflectionManager,
ctx.heuristicManager, ctx.decisionManager, ctx.projectContextManager,
ctx.toolAffordanceManager.
Trust hierarchy mixin: every MemorySource may carry an optional
categorical trustLevel: 'ground-truth' | 'verified' | 'inferred' | 'unverified'.
Used by the 'trust_level'ConflictStrategy (with recency tiebreak) and
backfilled from method + reliability via inferTrustLevel(source).
Decay
Memories naturally decay over time unless reinforced:
constagent=ctx.agentMemory({decay: {halfLifeHours: 168,// One-week half-lifeminImportance: 0.1,// Never fully forget},enableAutoDecay: true,});// Reinforce a memoryawaitagent.confirmMemory('memory_name',0.1);// Boost confidenceawaitagent.promoteMemory('memory_name','episodic');// Promote to long-term
Multi-agent
// Register an agentagent.registerAgent('agent_1',{name: 'Research Agent',type: 'llm',trustLevel: 0.8,capabilities: ['read','write'],});// Create with visibility (private / team / org / shared / public)awaitagent.addWorkingMemory({sessionId: session.name,content: 'Shared insight',visibility: 'shared',ownerAgentId: 'agent_1',});// Cross-agent searchconstresults=awaitagent.searchCrossAgent('agent_2','query');
API Reference
Method tables below cover the most-used surfaces. For the full surface use
your IDE's go-to-definition or read dist/index.d.ts.
EntityManager
Method
Description
createEntities(entities)
Create multiple entities in one batch
deleteEntities(names)
Delete entities by name
getEntity(name, options?)
Get one entity (with optional access tracking)
updateEntity(name, updates, { expectedVersion? })
Partial update; opt-in optimistic concurrency
addTags(name, tags) / removeTags(name, tags)
Tag management
setImportance(name, score)
Set importance (0–10)
getVersionChain(name) / getLatestVersion(name)
Supersession chains
invalidateEntity(name, ended?)
Set validUntil (bitemporal)
entityAsOf(name, asOf)
Time-travel query
entityTimeline(name)
Versions sorted by validFrom
RelationManager
Method
Description
createRelations(relations)
Create multiple relations
getRelations(entityName)
Incoming + outgoing relations
deleteRelations(relations)
Delete specific relations
invalidateRelation(from, type, to, ended?)
Set validUntil on a relation
queryAsOf(entity, asOf, options?)
Relations valid at time T
timeline(entity, options?)
Chronological history
ObservationManager
Method
Description
addObservations(adds, dedupOptions?)
Add observations (optional dedup)
deleteObservations(deletions)
Remove specific observations
getObservationsFor(entityName)
Read observations (column-store-aware)
invalidateObservation(entity, content, ended?)
Set per-observation validUntil
observationsAsOf(entity, asOf)
Observations valid at time T
SearchManager (ctx.searchManager)
Method
Description
searchNodes(query, options?)
Substring + tag matching
booleanSearch(query, options?)
AND / OR / NOT with AST
fuzzySearch(query, options?)
Levenshtein + N-gram pre-filter
searchByTime(query, options?)
Natural-language time ranges
autoSearch(query, limit?)
Auto-select best method; returns selectedMethod + selectionReason
openNodes(names)
Bulk-fetch entities by name
For ranked search use ctx.rankedSearch.searchNodesRanked(query, tags?, min?, max?, limit?).
For hybrid search, instantiate HybridSearchManager directly.
memoryjs is configured almost entirely through environment variables. The
table below lists the most-used; the full reference (decay / salience /
context-window / freshness / RBAC / mmap / segment / SQLite-pool / partial-index
knobs) lives in CLAUDE.md.
Variable
Description
Default
MEMORY_STORAGE_TYPE
Storage backend: jsonl or sqlite
jsonl
MEMORY_FILE_PATH
Override storage file path
(per ManagerContext ctor)
MEMORY_BACKEND
Pluggable Memory-Engine backend: sqlite or in-memory
sqlite
MEMORY_EMBEDDING_PROVIDER
Embedding provider: openai, local, or none
local
MEMORY_OPENAI_API_KEY
OpenAI API key (required when provider is openai)
—
MEMORY_AUTO_INDEX_EMBEDDINGS
Auto-build embedding index on entity create
false
MEMORY_AUTO_DECAY
Enable background memory decay
false
MEMORY_DECAY_HALF_LIFE_HOURS
Half-life for importance decay
168
MEMORY_GOVERNANCE_ENABLED
Enable GovernanceManager policy enforcement
false
MEMORY_AUDIT_LOG_FILE
Path for the audit JSONL trail
—
MEMORY_AGENT_ROLE
Apply a built-in role profile (researcher / planner / executor / reviewer / coordinator)
—
MEMORY_VALIDATE_ON_STORE
Run MemoryValidator before observation writes
false
MEMORY_AUDIT_ATTRIBUTION_REQUIRED
CollaborationAuditEnforcer strict mode
false
MEMORY_RBAC_ENABLED
Wire RbacMiddleware into GovernancePolicy
false
MEMORY_DEFAULT_VISIBILITY
Default AgentEntity.visibility
private
MEMORY_USE_MMAP
Use mmap for GraphStorage.loadFromDisk (strict 'true' literal match)
false
MEMORY_MMAP_THRESHOLD_BYTES
Minimum file size to trigger the mmap path; 0 = always
npm install # Install dependencies
npm run build # Build TypeScript to dist/ (tsup; ESM + CJS dual output)
npm run build:watch # Watch mode
npm test# Run all tests
npm run test:watch # Watch mode
npm run test:coverage # Run with coverage report
npm run test:ci # Excludes tests/performance/** (used by prepublishOnly)
npm run typecheck # Type checking without emit
npm run lint # ESLint (flat config; @typescript-eslint)
npm run benchmark # Standalone synthetic benchmarks
npm run bench # Vitest performance suite
SKIP_BENCHMARKS=true npm test# Skip perf tests in the main suite
Tooling
npm run audit:plans # Detect plan-doc rot
npx tsx tools/create-dependency-graph/create-dependency-graph.ts # Refresh DEPENDENCY_GRAPH.md
npx tsx tools/chunking-for-files/chunking-for-files.ts split <file># Split a large file
npx tsx tools/chunking-for-files/chunking-for-files.ts merge <manifest># Merge back
npx tsx tools/migrate-from-jsonl-to-sqlite/... # JSONL → SQLite migration
A TypeScript knowledge graph library for managing entities, relations, and observations with advanced search capabilities, hierarchical organization, and multiple storage backends.