Keyoku
Engine / Memory System

Memory system.

Eight memory types, each with a base stability that determines how long it resists decay. Ebbinghaus-inspired retention curves, three-tier deduplication, conflict detection, and a knowledge graph — all running in a single SQLite database.

Types

Eight types, each with a half-life.

Every extracted memory is classified into one of eight types. The type determines its base stability — the number of days before natural decay reduces its retention score below threshold.

365 days

IDENTITY

Core identity facts — who they are, their name, age, occupation, background.

270 days

PREFERENCE

Likes, dislikes, preferences, communication style, tool choices.

270 days

RELATIONSHIP

Long-term connections with people, organizations, and places.

120 days

EVENT

Important events, milestones, achievements, and dated occurrences.

90 days

ACTIVITY

Behavioral history — what they were doing, working on, or interested in.

60 days

PLAN

Ongoing tasks, projects, goals, deadlines, and action items.

21 days

CONTEXT

Conversation context, session data, and working state.

3 days

EPHEMERAL

Transient, session-specific facts that expire quickly.

Lifecycle

Four states, one direction.

Memories flow through a lifecycle: ACTIVE to STALE to ARCHIVED to DELETED. The transition is driven by the decay formula and configurable thresholds.

ACTIVE

Memory is live and included in search results. Accessed normally.

retention >= 0.3

STALE

Memory has decayed below threshold. Deprioritized in search results but still retrievable.

retention < 0.3

ARCHIVED

Memory is excluded from default searches. Still accessible via explicit ID lookup or archive queries.

retention < 0.1 or 30+ days stale

DELETED

Soft-deleted. Purged permanently after 90 days (configurable via PurgeRetentionDays).

explicit delete or retention < 0.01

Ebbinghaus-inspired retention.

Memory retention decreases exponentially over time, but access frequency extends the effective stability logarithmically. Frequently recalled memories resist decay.

// Core decay formula
retention(t) = e^(-t / effective_stability)

// Effective stability grows with access
effective_stability = base_stability × (1 + ln(1 + access_count) × 0.5)

// Example: IDENTITY memory (365d base), accessed 10 times
effective_stability = 365 × (1 + ln(11) × 0.5)
effective_stability = 365 × (1 + 2.4 × 0.5)
effective_stability = 365 × 2.2 = 803 days

// After 200 days with 10 accesses:
retention = e^(-200 / 803) = 0.78 (still ACTIVE)
Deduplication

Three tiers of dedup.

Every ingest passes through three deduplication checks before storage. This prevents bloat while preserving genuinely new information.

TierSimilarityActionDescription
Exact hash100%SkipSHA256 hash of normalized content matches an existing memory. No storage needed.
Semantic duplicate95%+SkipCosine similarity of embedding vectors exceeds 0.95. Content is semantically identical.
Near-duplicate85% - 95%Merge or skipSimilar but not identical. If the new memory adds information, merge. If it is a subset, skip.
Conflicts

Five resolution modes.

When a new memory contradicts an existing one, the engine detects the conflict and applies one of five resolution strategies.

ModeBehavior
keep_existingPreserve the original memory, discard the new one.
use_newReplace the existing memory with the new one.
mergeCombine both memories, preserving unique information from each.
askFlag the conflict for user resolution. Both memories are kept until resolved.
temporalNewer memory wins. Assumes the most recent information is correct.
Knowledge graph

Entities and relationships.

The engine extracts entities and relationships from conversations automatically. Bidirectional relationships infer reverse edges.

PERSON

People mentioned in conversations — names, roles, attributes.

ORGANIZATION

Companies, teams, institutions, and groups.

LOCATION

Cities, countries, addresses, and named places.

PRODUCT

Software, tools, services, and physical products.

CONCEPT

Abstract ideas, topics, skills, and domains of knowledge.

EVENT

Named events, conferences, milestones, and occurrences.

OTHER

Entities that do not fit any other category.

Relationship types

40+ relationship types.

Relationships are extracted with strength scores calculated as: (count x 0.4) + (recency x 0.3) + (confidence x 0.3).

works_at
manages
reports_to
friend_of
lives_in
parent_of
child_of
dating
married_to
member_of
founded
uses
created
collaborates_with
mentors
competitor_of
partner_of
client_of
sibling_of
knows
Retrieval

Three-tier search with composite ranking.

Search follows a cascade: LRU hot cache (sub-millisecond) to HNSW approximate nearest neighbor (fast vector search) to SQLite full-text search (fallback). Results are ranked using a composite score.

balanced

Default mode. Good for general-purpose recall.

35% semantic + 20% recency + 20% decay + 20% importance + 5% confidence

recent

Prioritizes recently created or accessed memories.

30% semantic + 50% recency + 10% decay + 7% importance + 3% confidence

important

Surfaces high-importance memories regardless of age.

40% semantic + 10% recency + 10% decay + 35% importance + 5% confidence

historical

Best for deep recall across long time periods.

50% semantic + 5% recency + 25% decay + 15% importance + 5% confidence

comprehensive

Broader results with balanced weighting across dimensions.

45% semantic + 15% recency + 15% decay + 20% importance + 5% confidence

Cache, then HNSW, then FTS.

// 1. Check LRU hot cache (500 entries)
cache_hit = hot_cache.get(query_embedding)
if (cache_hit) return cache_hit  // ~0.1ms

// 2. HNSW approximate nearest neighbor
candidates = hnsw_index.search(query_embedding, k=50)  // ~1-5ms

// 3. Full-text search fallback
if (candidates.length < limit) {
  fts_results = sqlite.fts5_search(query_text)  // ~5-20ms
  candidates = merge(candidates, fts_results)
}

// 4. Composite ranking
ranked = candidates.sort((a, b) => score(b) - score(a))