Skip to Content
GuidesCore concepts

Core Concepts

Node Types

Every memory is stored as a typed node. The type affects how the memory is scored, decayed, and organized.

TypeValuePurposeDefault TTL
ENTITY"entity"People, places, organizationsNone
EVENT"event"Things that happened365 days
FACT"fact"Statements of truthNone
DECISION"decision"Choices made with context180 days
PREFERENCE"preference"User likes/dislikesNone
TASK"task"Action items90 days
SUMMARY"summary"Rollup of other nodes365 days
NOTE"note"General-purpose (default)90 days
INSTRUCTION"instruction"Learned behavioral rulesNone
from prme.types import NodeType client.store("Always use UTC timestamps.", user_id="u1", node_type=NodeType.INSTRUCTION)

Lifecycle States

Every node progresses through lifecycle states. Transitions are forward-only.

TENTATIVE ──> STABLE ──> SUPERSEDED ──> ARCHIVED │ │ │ │ ├──> CONTESTED ──> DEPRECATED ──> ARCHIVED │ │ └────────────┴──> ARCHIVED
StateMeaning
TENTATIVENewly created, not yet confirmed
STABLEConfirmed through age or reinforcement
CONTESTEDContradicted by newer information
SUPERSEDEDReplaced by a newer version
DEPRECATEDConfirmed incorrect
ARCHIVEDTerminal state, excluded from retrieval

The organizer automatically promotes TENTATIVE nodes to STABLE after 7 days (configurable) with at least 1 evidence reference.

Scopes

Scopes control visibility and isolation of memories.

ScopeValuePurpose
PERSONAL"personal"Single user’s memories
PROJECT"project"Shared across a project
ORGANISATION"organisation"Cross-project organizational facts
AGENT"agent"Private to the AI agent
SYSTEM"system"System-generated content
SANDBOX"sandbox"Temporary, supports hard delete
from prme.types import Scope # Personal memory client.store("I prefer dark mode.", user_id="alice", scope=Scope.PERSONAL) # Shared project decision client.store("API uses REST, not GraphQL.", user_id="alice", scope=Scope.PROJECT)

Epistemic Model

PRME tracks the epistemic status of each memory — how it was learned and how certain it is.

Epistemic Types

TypeWeightMeaning
OBSERVED1.0Evidence-based
ASSERTED0.9User stated directly
INFERRED0.7Derived by logic
CONDITIONAL0.5Depends on other state
UNVERIFIED0.5Not yet confirmed
HYPOTHETICAL0.3Speculative
DEPRECATED0.1Confirmed wrong

In DEFAULT retrieval mode, HYPOTHETICAL and DEPRECATED nodes are excluded. Use EXPLICIT mode to include them.

Source Types

TypeMeaning
USER_STATEDUser told us directly
USER_DEMONSTRATEDInferred from user behavior
SYSTEM_INFERREDSystem-derived conclusion
EXTERNAL_DOCUMENTFrom an external source
TOOL_OUTPUTFrom a tool or API

Confidence and Salience

Every node carries two scores:

  • Confidence (0.0 - 1.0): How certain we are this is correct. Boosted by reinforcement, decayed over time.
  • Salience (0.0 - 1.0): How important/relevant this is right now. Decays based on the node’s DecayProfile.

Decay Profiles

ProfileLambdaHalf-life
PERMANENT0.000Never decays
SLOW0.005~139 days
MEDIUM0.020~35 days
FAST0.070~10 days
RAPID0.200~3.5 days

Edge Types

Nodes are connected by typed edges in the graph:

TypeMeaning
RELATES_TOGeneral relationship
SUPERSEDESNew version of old node
DERIVED_FROMCreated from another node
MENTIONSReferences an entity
PART_OFComponent relationship
CAUSED_BYCausal link
SUPPORTSEvidence for another node
CONTRADICTSConflicts with another node
HAS_FACTEntity owns a fact

Retrieval Pipeline

The retrieval pipeline runs 6 stages:

  1. Query Analysis: classifies intent (semantic, factual, entity_lookup, temporal, relational), extracts entities and temporal signals
  2. Candidate Generation: gathers candidates from vector search (k=500), lexical search (k=500), graph neighborhood (150), and pinned nodes
  3. Candidate Merging: deduplicates by node ID, tracks discovery paths
  4. Epistemic Filtering: removes HYPOTHETICAL/DEPRECATED in DEFAULT mode, filters by lifecycle state
  5. Scoring: by default, reciprocal rank fusion of the semantic and lexical ranks, adjusted by epistemic, node-type and temporal factors, with a recency boost on current-state questions; the weighted formula below is available with PRME_SCORING__FUSION=weighted
  6. Context Packing: greedy bin-packing into token budget with representation levels; by default each record is rendered as one plain line (the reader context format)

Scoring Formula

By default (PRMEConfig().scoring), PRME ranks candidates with reciprocal rank fusion (fusion="rrf", rrf_k=60): each candidate scores 1/(60 + rank) on the semantic and on the lexical channel, scaled so first place on both is 1.0, then adjusted by its epistemic, node-type and temporal factors relative to the largest in the pool. On current-state questions a recency boost of 0.25 applies, and equal scores are ordered newest first by event time. Rank fusion does not use the additive weights, graph proximity, salience or confidence (RFC-0005 Section 7.2).

With PRME_SCORING__FUSION=weighted, or a ScoringWeights() built in code, PRME uses the weighted formula:

score = semantic * 0.25 + lexical * 0.20 + graph * 0.20 + recency * 0.10 + salience * 0.10 + confidence * 0.15 score *= epistemic_weight (type-based multiplier) score += temporal_boost (0.15 for temporal queries with date proximity)

All weights are configurable via ScoringWeights. See Configuration.

Supersedence

When a fact changes, PRME doesn’t delete the old version. Instead, it creates a new node and marks the old one as SUPERSEDED:

# Old fact exists: "Alice uses VS Code" # New fact arrives: "Alice switched to Neovim" # → Old node gets lifecycle_state=SUPERSEDED, superseded_by=new_node_id # → Retrieval returns only the latest version by default

This preserves the full history. Use include_superseded=True to see the chain, or the CLI:

prme chain ./memory.duckdb <node-id>

Source: documentation/concepts.md  in PRME at 58caddb1.