SmartMemory
Concepts

Opinions & Observations

Part of the expertise layer. Read the overview →

SmartMemory synthesizes opinions and observations from raw memories, enabling agents to form beliefs and entity summaries that evolve over time.

Overview

TypeDescriptionExample
OpinionBelief with confidence score"User prefers functional programming (85% confident)"
ObservationEntity summary"Alice: Works at Google since 2020, promoted in 2023"

Opinions

Opinions are beliefs formed from patterns in episodic memories. They have confidence scores that can be reinforced or contradicted.

Formation

The OpinionSynthesisEvolver detects patterns:

graph LR
    E1[Episodic: User chose map()] --> P[Pattern Detector]
    E2[Episodic: User chose filter()] --> P
    E3[Episodic: User avoided loops] --> P
    P --> O[Opinion: Prefers functional style]

Confidence Scoring

from smartmemory.models.opinion import OpinionMetadata

meta = OpinionMetadata(
    confidence=0.75,
    subject="functional programming",
    subject_type="preference"
)

# When supporting evidence arrives
meta.reinforce("evidence_123")
# confidence: 0.75 → 0.775 (diminishing returns)

# When contradicting evidence arrives
meta.contradict("evidence_456")
# confidence: 0.775 → 0.659 (15% penalty)

Disposition

Opinions are influenced by configurable disposition traits:

from smartmemory.models.opinion import Disposition

disposition = Disposition(
    skepticism=0.7,   # Requires more evidence before forming opinions
    literalism=0.5,   # Balance literal vs inferred meaning
    empathy=0.8       # Weight emotional/preference signals highly
)

Reinforcement Evolver

The OpinionReinforcementEvolver runs as a background job:

  1. Scans new episodic memories for evidence
  2. Matches against existing opinions
  3. Reinforces or contradicts based on similarity
  4. Decays stale opinions over time
  5. Archives opinions below confidence threshold

Observations

Observations are synthesized entity summaries built from scattered facts.

Synthesis

The ObservationSynthesisEvolver combines facts:

graph TD
    F1["Alice works at Google"] --> S[Synthesis]
    F2["Alice started in 2020"] --> S
    F3["Alice was promoted in 2023"] --> S
    S --> O["Observation: Alice's career at Google<br/>Started 2020, promoted 2023"]

Aspect Coverage

Observations track which aspects of an entity are covered:

from smartmemory.models.opinion import ObservationMetadata

meta = ObservationMetadata(
    entity_id="alice_123",
    entity_name="Alice",
    entity_type="person",
    aspects_covered=["career", "location", "skills"],
    completeness=0.6  # 60% complete
)

Available aspects:

  • career - Work, job, company, role
  • education - School, degree, study
  • location - City, country, address
  • preferences - Likes, favorites
  • relationships - Family, colleagues
  • skills - Expertise, proficiency
  • interests - Hobbies, passions

The Reflect API

Trigger synthesis on-demand:

# Run synthesis evolvers and get results
result = memory.reflect(top_k=5)

This:

  1. Runs OpinionSynthesisEvolver
  2. Runs ObservationSynthesisEvolver
  3. Returns newly formed opinions/observations

Evolution Configuration

Opinion Synthesis

from smartmemory.plugins.evolvers.opinion_synthesis import OpinionSynthesisConfig

config = OpinionSynthesisConfig(
    min_pattern_occurrences=3,  # Pattern must appear 3+ times
    min_confidence=0.5,          # Minimum confidence to create
    lookback_days=30,            # Analyze last 30 days
    skepticism=0.5               # Disposition skepticism
)

Opinion Reinforcement

from smartmemory.plugins.evolvers.opinion_reinforcement import OpinionReinforcementConfig

config = OpinionReinforcementConfig(
    min_confidence_threshold=0.2,  # Archive below this
    lookback_days=7,               # Check last 7 days for evidence
    enable_decay=True,             # Enable staleness decay
    decay_after_days=30,           # Start decaying after 30 days
    decay_rate=0.05                # 5% decay per cycle
)

Observation Synthesis

from smartmemory.plugins.evolvers.observation_synthesis import ObservationSynthesisConfig

config = ObservationSynthesisConfig(
    min_facts_per_entity=2,        # Need 2+ facts to synthesize
    lookback_days=90,              # Look back 90 days
    max_observations_per_run=20   # Limit per evolution cycle
)

Memory Types

# Opinion and observation are extended *string* memory types — pass them as
# strings (they are not members of the `MemoryType` enum).

# Store opinion
memory.add(
    content="User prefers functional programming",
    memory_type="opinion",
    metadata={
        "confidence": 0.85,
        "subject": "functional programming",
        "subject_type": "preference"
    }
)

# Store observation
memory.add(
    content="Alice: Senior engineer at Google since 2020",
    memory_type="observation",
    metadata={
        "entity_id": "alice_123",
        "entity_name": "Alice",
        "aspects_covered": ["career"]
    }
)

On this page