Skip to main content

StackComponentProtocol — Cross-Cutting Concerns

Stack components are the stack’s equivalent of plugins. They extend what the stack can do by hooking into its lifecycle: memory saves, searches, loads, and periodic maintenance. Think of them as middleware for memory operations. When a memory is saved, every component gets notified. When search results come back, every component can re-rank them. When maintenance runs, every component does its background work.

StackComponentProtocol Interface

Properties

Hook Dispatch

The stack calls component hooks at four points in its lifecycle:

on_save

Called after a memory is saved. Can modify the memory by returning a modified version (return None to leave unchanged). Used by:
  • EmotionalTagging: Detects valence/arousal, adds emotional metadata
  • MetaMemory: Initializes confidence tracking
  • Embedding: Generates and stores vector representation
Called after search results are assembled. Returns the (possibly modified) results list. Components can re-rank, filter, or augment results. Used by:
  • Forgetting: Could filter out low-salience results
  • EmotionalTagging: Could boost emotionally relevant results

on_load

Called during load() working memory assembly. Components contribute to the context dict by mutating it directly. Used by:
  • Anxiety: Adds current anxiety levels and dimension scores
  • Forgetting: Adds forgetting statistics

on_maintenance

Called during periodic maintenance. Each component does background work and returns a stats dict. The stack combines all stats keyed by component name. Used by:
  • Forgetting: Runs salience decay sweeps, soft-deletes low-salience memories
  • Consolidation: Detects cross-domain patterns in episodes
  • Suggestions: Scans raw entries for potential episodes/beliefs/notes
  • MetaMemory: Applies confidence decay to stale memories
  • Knowledge: Analyzes domain coverage and knowledge gaps

Error Isolation

Component failures never crash stack operations. If a component’s hook throws an exception, the stack logs the error and continues with the remaining components. This isolation means:
  • A buggy emotional tagger won’t prevent memory saves
  • A failing embedding component won’t break search (results just won’t have embeddings)
  • One component crashing during maintenance won’t prevent others from running

The 8 Default Components

SQLiteStack auto-loads all 8 built-in components on initialization. Pass components=[] for a bare stack, or an explicit list for custom configuration.

Component Configuration

Entry Point Registration

Stack components register in the kernle.stack_components entry point group:
Components can also be discovered dynamically:

Building a Custom Component

To create a custom stack component, implement the StackComponentProtocol:
Register it:
Add it to a stack at runtime:
Or include it in the initial component list: