smrti

Memory engine for AI agents.

Bayesian beliefs. Emotional valence. Attention-weighted salience. A single SQLite file.

$ pip install smrti GitHub

Knowledge stored as atoms

smrti is an AtomSpace-inspired graph database for agent memory. Each node—an atom—carries a Bayesian truth value, an emotional valence, and an attention weight. Retrieval ranks by computed salience across five dimensions, not by timestamp. Your agent remembers what matters, not just what happened last.

Evidence is append-only. Truth values are never mutated directly—observations are logged and merged during consolidation epochs via PLN (Probabilistic Logic Networks). Multi-tenant isolation keeps agent memories separate by tenant and space.

type
concept · belief · episode · goal · relation
truth
probability [0,1] + confidence [0,1]
attention
STI (short-term) + LTI (long-term)
valence
emotional tone [-1,1] + intensity [0,1]
entity
person · org · project · tool · preference · …
links
source → target with typed relations

Six layers, one SQLite file

Vector indexing via sqlite-vec (BAAI/bge-small-en-v1.5, 384 dimensions). Entity resolution cascades through exact match, alias lookup, fuzzy matching (RapidFuzz), and embedding similarity before creating new nodes.

smrti facade
servers mcp.py · rest.py · proxy.py · reflect_loop.py · tools.py
personality params.py · presets/
evolution epoch.py · truth.py (PLN)
retrieval fan_out.py · salience.py · classify.py
extraction resolve.py (entity resolution)
core models.py · atomspace.py · db.py · embed.py

Six operations

remember, recall, believe, reflect, forget, personality. The Python API is the same interface the MCP and REST servers expose.

from smrti import Smrti

engine = Smrti(personality="deterministic")

# Store a memory with negative valence
engine.remember(
    "Deploying on Friday caused a 2-hour outage",
    valence=-0.8
)

# Positive experience
engine.remember(
    "Feature flags made the rollout safe",
    valence=0.6
)
# Salience-ranked retrieval
results = engine.recall("deployment risks")

for r in results:
    print(
        f"{r.atom.content}",
        f"salience={r.salience:.2f}",
        f"confidence={r.atom.truth.confidence:.2f}",
        f"valence={r.atom.valence.valence:.1f}",
    )

# KNN search → 1-hop graph expansion → salience scoring
# Negative-valence atoms surface first when relevant
# Assert a belief with supporting evidence
engine.believe(
    "Feature flags reduce deployment risk",
    probability=0.85,
    evidence="3 successful staged rollouts"
)

# Evidence is appended, not overwritten.
# Conflicting observations create contradiction links.
# The consolidation epoch merges via PLN.
# Run a consolidation epoch
epoch = engine.reflect()

print(epoch)
# EpochResult(
#   beliefs_updated=3,
#   atoms_decayed=12,
#   atoms_pruned=1,
#   lti_promoted=2,
#   new_connections=4,
#   contradictions_resolved=1
# )

# Process evidence → decay STI/LTI → promote high-LTI
# → resolve contradictions → prune low-salience atoms
# Soft-forget: recall matching atoms, decay confidence
targets = engine.recall("Friday deployment outage", top_k=5)

for r in targets:
    engine.db.execute(
        "UPDATE atoms SET confidence = confidence * 0.3 WHERE id = ?",
        (r.atom.id,)
    )

# No hard delete — the consolidation epoch
# prunes when salience drops low enough
# Switch preset at runtime
engine.set_personality("analytical")

# 6 presets: balanced, analytical, curious,
# empathetic, maverick, deterministic
# Each tunes 16 hyperparameters that control
# learning rate, decay, promotion, and salience weights

Salience scoring

Every recall computes a weighted sum across five dimensions. Personality hyperparameters control the weights.

S = wsim × similarity + wsti × STI + wconf × confidence + wlti × LTI + wval × |valence| × intensity

Dynamic weight shifting

When valence drops below −0.5, weight shifts from STI to valence. Severe negative-valence atoms (errors, failures) get an LTI floor of 0.5 on creation, preventing epoch pruning. Critical errors outrank recent trivia.

Severity classification

Each recall result carries a severity tag. The proxy server injects these as XML tags into the LLM context.

  • critical_warning — valence < −0.5, intensity > 0.5
  • known_antipattern — probability < 0.3, confidence > 0.3
  • context — neutral background

16 hyperparameters, 6 presets

Each preset tunes how the agent learns, forgets, and weighs emotion. Swap at runtime with set_personality() or define custom profiles.

balanced
Default. Equal weight distribution across all dimensions.
learn
0.30
decay
0.10
promote
0.70
valence
0.10
analytical
Slow belief updates. Strict promotion. Confidence-heavy retrieval.
learn
0.15
decay
0.05
promote
0.90
valence
0.05
curious
Fast learning. Aggressive exploration. Attention-weighted recall.
learn
0.50
decay
0.20
promote
0.50
valence
0.15
empathetic
Emotion-dominant. High valence weight. Mood-sensitive scoring.
learn
0.40
decay
0.08
promote
0.70
valence
0.35
maverick
Low decay. Broad connections. Eclectic, exploratory recall.
learn
0.10
decay
0.15
promote
0.40
valence
0.20
deterministic
Agentic workflows. Fast learning + slow decay. Strict LTI promotion.
learn
0.40
decay
0.08
promote
0.85
valence
0.12

Three modes, same engine

MCP
Stdio server for Claude, Cursor, and any MCP-compatible client. Tool-based interface.
smrti serve mcp
REST
FastAPI on port 8420. JSON request/response. Direct HTTP integration.
smrti serve rest
Proxy
OpenAI-compatible on port 8421. Injects severity-tagged memories as XML into the LLM context window.
smrti serve proxy