tier

package
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 25, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package tier implements the tiered memory subsystem: tier-scoped record stores, a manager that remembers and recalls records across hot/warm/cold levels, and the policies that migrate records between them.

Single durable tier (no composite, no reconcile queue)

A host that only needs durable session memory (e.g. the Postgres tier store) can back the manager with a single-level store directly — no composite and no job queue are required. The store forces its own level on Put and answers List/Count for other levels with empty results, so Remember persists immediately and Recall reads the durable tier:

store, _ := postgres.NewStore(db)                 // level = warm
manager := tier.NewManager(store, tier.SingleLevelPolicy(), nil)

SingleLevelPolicy disables promotion, demotion, TTL, and capacity eviction, so recall-time bookkeeping never migrates records out of the durable tier. Hosts seeding chat history should build records with MessageRecord (optionally WithProvenance), which populates fields exactly like the runtime's own writes.

Approximating a flat "most recent, replayed in order" recall

A flat memory.Repository replays every message in insertion order and consumers typically tail the newest N. RankMemories instead SCORES candidates: score = semantic*lexicalOverlap(query) + recency*exp(-age/168h) + importance*record.Importance, weighted by RecallWeights (defaults {Semantic: 0.5, Recency: 0.3, Importance: 0.2}; zero weights are replaced by those defaults, so use small positive values to de-emphasize a dimension). RecallBudget then caps the selection (default Total 20, split 60%/25%/15% across hot/warm/cold by Normalize). The final output is ALWAYS re-sorted chronologically — ranking only picks what survives, not the replay order. To approximate the flat tail-N behavior:

  • recall with an empty query (no semantic signal),
  • set weights recency-dominant, e.g. {Semantic: 0.01, Recency: 1.0, Importance: 0.01},
  • size RecallBudget.Total at the replay window (e.g. 200) and raise the per-level caps to match.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func RecordTierDepth

func RecordTierDepth(ctx context.Context, store Store, recorder observability.Recorder, scenario string, ns memory.Namespace)

RecordTierDepth publishes per-level record counts for a namespace.

func WithMigrationRunID added in v0.2.0

func WithMigrationRunID(ctx context.Context, runID string) context.Context

WithMigrationRunID attaches a run ID to ctx for tier migration events.

Types

type ChainedMigrationObserver added in v0.2.0

type ChainedMigrationObserver struct {
	Observers []MigrationObserver
}

ChainedMigrationObserver fans out migration notifications to multiple observers.

func (ChainedMigrationObserver) Demoted added in v0.2.0

func (o ChainedMigrationObserver) Demoted(ctx context.Context, ns memory.Namespace, recordID string, from, to Level)

func (ChainedMigrationObserver) Evicted added in v0.2.0

func (o ChainedMigrationObserver) Evicted(ctx context.Context, ns memory.Namespace, recordID string, from Level)

func (ChainedMigrationObserver) Promoted added in v0.2.0

func (o ChainedMigrationObserver) Promoted(ctx context.Context, ns memory.Namespace, recordID string, from, to Level)

type ChatMessage added in v0.3.1

type ChatMessage struct {
	Role       string            `json:"role"`
	Content    string            `json:"content,omitempty"`
	ToolCalls  []llm.ToolCall    `json:"tool_calls,omitempty"`
	Tool       string            `json:"tool,omitempty"`
	ToolCallID string            `json:"tool_call_id,omitempty"`
	Metadata   map[string]string `json:"metadata,omitempty"`
	Time       time.Time         `json:"time"`
}

ChatMessage is the wire format the runtime persists for one chat message inside a tier record's Content field. It intentionally mirrors the runtime's internal message schema field-for-field so records seeded by a host (e.g. chat transcript hydration) are indistinguishable from records the framework writes itself on recall.

type CognitiveAdapter

type CognitiveAdapter struct {
	Manager Manager
	Weights RecallWeights
	Budget  func(limit int) RecallBudget
}

CognitiveAdapter implements memory.CognitiveMemory using a tier Manager.

func NewCognitiveAdapter

func NewCognitiveAdapter(manager Manager, weights RecallWeights) *CognitiveAdapter

NewCognitiveAdapter wraps a tier Manager as a CognitiveMemory port.

func (*CognitiveAdapter) Recall

func (a *CognitiveAdapter) Recall(ctx context.Context, ns memory.Namespace, query string, limit int) ([]memory.CognitiveRecord, error)

func (*CognitiveAdapter) Remember

type ColdSummaryBackend added in v0.2.0

type ColdSummaryBackend interface {
	Archive(ctx context.Context, ns memory.Namespace, record *Record) error
	SearchRecordIDs(ctx context.Context, ns memory.Namespace, query string, limit int) ([]string, error)
	Delete(ctx context.Context, ns memory.Namespace, recordID string) error
}

ColdSummaryBackend archives cold records and optionally indexes summaries for semantic recall.

type ColdSummaryIndexer added in v0.2.0

type ColdSummaryIndexer interface {
	UpsertSummary(ctx context.Context, ns memory.Namespace, record Record, summary string) error
	SearchSummaries(ctx context.Context, ns memory.Namespace, query string, limit int) ([]string, error)
	DeleteSummary(ctx context.Context, ns memory.Namespace, recordID string) error
}

ColdSummaryIndexer stores and searches cold summaries in a vector index.

type ColdSummarySettings added in v0.2.0

type ColdSummarySettings struct {
	Enabled         bool   `json:"enabled,omitempty" yaml:"enabled"`
	MinBytes        int64  `json:"min_bytes,omitempty" yaml:"min_bytes"`
	MaxSummaryChars int    `json:"max_summary_chars,omitempty" yaml:"max_summary_chars"`
	SummaryProfile  string `json:"summary_profile,omitempty" yaml:"summary_profile"`
}

ColdSummarySettings configures cold-tier summarization before archive.

type CompositeStore

type CompositeStore struct {
	Hot  Store
	Warm Store
	Cold Store
}

CompositeStore routes tier records across hot, warm, and cold backends.

func (*CompositeStore) Count

func (c *CompositeStore) Count(ctx context.Context, ns memory.Namespace, level Level) (int, error)

func (*CompositeStore) Delete

func (c *CompositeStore) Delete(ctx context.Context, ns memory.Namespace, id string) error

func (*CompositeStore) Get

func (*CompositeStore) List

func (c *CompositeStore) List(ctx context.Context, ns memory.Namespace, level Level, limit int) ([]Record, error)

func (*CompositeStore) Put

func (c *CompositeStore) Put(ctx context.Context, ns memory.Namespace, record Record) error

type ContentSummarizer added in v0.2.0

type ContentSummarizer interface {
	Summarize(ctx context.Context, content string, maxChars int) (string, error)
}

ContentSummarizer compresses large record content before cold archive.

type EventSinkMigrationObserver added in v0.2.0

type EventSinkMigrationObserver struct {
	Sink     core.EventSink
	Scenario string
}

EventSinkMigrationObserver emits tier migration events to a core.EventSink.

func (EventSinkMigrationObserver) Demoted added in v0.2.0

func (o EventSinkMigrationObserver) Demoted(ctx context.Context, ns memory.Namespace, recordID string, from, to Level)

func (EventSinkMigrationObserver) Evicted added in v0.2.0

func (o EventSinkMigrationObserver) Evicted(ctx context.Context, ns memory.Namespace, recordID string, from Level)

func (EventSinkMigrationObserver) Promoted added in v0.2.0

func (o EventSinkMigrationObserver) Promoted(ctx context.Context, ns memory.Namespace, recordID string, from, to Level)

type IndexRebuilder added in v0.3.0

type IndexRebuilder interface {
	RebuildIndex(ctx context.Context, ns memory.Namespace) (int, error)
}

IndexRebuilder is an optional Manager capability that re-mirrors the durable tier records into a secondary index (e.g. a cognitive search index), used to converge the index after a transient mirror failure. It returns the number of records re-mirrored.

type Level

type Level string

Level identifies a memory storage and recall tier.

const (
	LevelHot  Level = "hot"
	LevelWarm Level = "warm"
	LevelCold Level = "cold"
)

type Manager

type Manager interface {
	Remember(ctx context.Context, ns memory.Namespace, record Record) error
	Recall(ctx context.Context, ns memory.Namespace, query string, budget RecallBudget) ([]Record, error)
	Reconcile(ctx context.Context, ns memory.Namespace, now time.Time) (MigrationReport, error)
}

Manager orchestrates tiered remember, recall, and reconciliation.

func NewDualWriteManager

func NewDualWriteManager(inner Manager, index memory.CognitiveMemory) Manager

NewDualWriteManager remembers tier records and mirrors searchable cognitive entries.

func NewManager

func NewManager(store Store, policy Policy, observer MigrationObserver) Manager

NewManager constructs a tier Manager backed by store and policy.

func NewManagerWithWeights

func NewManagerWithWeights(store Store, policy Policy, observer MigrationObserver, weights memory.RecallWeights, coldSummary ColdSummaryBackend) Manager

NewManagerWithWeights constructs a tier Manager with custom RankMemories weights.

type MetricsObserver

type MetricsObserver struct {
	Recorder observability.Recorder
	Scenario string
}

MetricsObserver records tier migration and depth metrics.

func (MetricsObserver) Demoted

func (o MetricsObserver) Demoted(ctx context.Context, ns memory.Namespace, recordID string, from, to Level)

func (MetricsObserver) Evicted

func (o MetricsObserver) Evicted(ctx context.Context, ns memory.Namespace, recordID string, from Level)

func (MetricsObserver) Promoted

func (o MetricsObserver) Promoted(ctx context.Context, ns memory.Namespace, recordID string, from, to Level)

type MigrationObserver

type MigrationObserver interface {
	Promoted(ctx context.Context, ns memory.Namespace, recordID string, from, to Level)
	Demoted(ctx context.Context, ns memory.Namespace, recordID string, from, to Level)
	Evicted(ctx context.Context, ns memory.Namespace, recordID string, from Level)
}

MigrationObserver receives tier migration notifications from a Manager.

func ChainMigrationObservers added in v0.2.0

func ChainMigrationObservers(observers ...MigrationObserver) MigrationObserver

type MigrationReport

type MigrationReport struct {
	Promoted int `json:"promoted"`
	Demoted  int `json:"demoted"`
	Evicted  int `json:"evicted"`
}

MigrationReport summarizes tier migrations from a reconcile pass.

type NoopColdSummaryBackend added in v0.2.0

type NoopColdSummaryBackend struct{}

NoopColdSummaryBackend disables cold summary behavior.

func (NoopColdSummaryBackend) Archive added in v0.2.0

func (NoopColdSummaryBackend) Delete added in v0.2.0

func (NoopColdSummaryBackend) SearchRecordIDs added in v0.2.0

type NoopMigrationObserver

type NoopMigrationObserver struct{}

NoopMigrationObserver discards migration notifications.

func (NoopMigrationObserver) Demoted

func (NoopMigrationObserver) Evicted

func (NoopMigrationObserver) Promoted

type Policy

type Policy struct {
	HotCapacity   int
	WarmCapacity  int
	ColdCapacity  int
	HotTTL        time.Duration
	WarmTTL       time.Duration
	PromoteAccess int
	DemoteIdle    time.Duration
}

Policy configures automatic promotion, demotion, and eviction between tiers.

func DefaultPolicy

func DefaultPolicy() Policy

DefaultPolicy returns baseline hot/warm/cold promotion and demotion rules.

func SingleLevelPolicy added in v0.3.1

func SingleLevelPolicy() Policy

SingleLevelPolicy returns a Policy with no promotion, demotion, TTL expiry, or capacity eviction: every record stays in the tier its store assigns. Use it when one durable store (e.g. the Postgres tier store) backs the whole manager without a composite or a reconcile queue, so recall-time bookkeeping never migrates records out of the durable tier and the store's level is the single source of truth.

func (Policy) NextTierOnDemote

func (p Policy) NextTierOnDemote(level Level) (Level, bool)

NextTierOnDemote returns the colder tier, or empty if eviction is required.

func (Policy) ShouldDemote

func (p Policy) ShouldDemote(record Record, now time.Time, levelCount int) bool

ShouldDemote reports whether a record should move to a colder tier.

func (Policy) ShouldPromote

func (p Policy) ShouldPromote(record Record, now time.Time) bool

ShouldPromote reports whether a record should move to a hotter tier after access.

func (Policy) TargetTier

func (p Policy) TargetTier(record Record, now time.Time, levelCount map[Level]int) Level

TargetTier returns the tier a record should occupy after promotion or demotion.

type RecallBudget

type RecallBudget struct {
	Total int `json:"total"`
	Hot   int `json:"hot"`
	Warm  int `json:"warm"`
	Cold  int `json:"cold"`
}

RecallBudget limits how many records to pull from each tier during recall.

func (RecallBudget) Normalize

func (b RecallBudget) Normalize() RecallBudget

Normalize fills zero values with sensible defaults and caps per-tier limits by Total.

type RecallWeights

type RecallWeights struct {
	Semantic   float64 `json:"semantic,omitempty" yaml:"semantic"`
	Recency    float64 `json:"recency,omitempty" yaml:"recency"`
	Importance float64 `json:"importance,omitempty" yaml:"importance"`
}

RecallWeights configures RankMemories weighting during tier recall.

type Record

type Record struct {
	memory.CognitiveRecord
	Tier         Level     `json:"tier"`
	AccessCount  int       `json:"access_count"`
	LastAccessAt time.Time `json:"last_access_at"`
	PromotedAt   time.Time `json:"promoted_at"`
	SizeBytes    int64     `json:"size_bytes,omitempty"`
	Pinned       bool      `json:"pinned,omitempty"`
}

Record extends a cognitive memory entry with tier lifecycle metadata.

func MessageRecord added in v0.3.1

func MessageRecord(ns memory.Namespace, msg ChatMessage, opts ...SeedOption) (Record, error)

MessageRecord builds a tier.Record for one chat message using the same field-population rules the runtime applies to its own memory writes: Content carries the marshaled message, Categories/Importance derive from the role, and the record metadata marks role/kind/searchable. Hosts hydrating chat history into a tier store should seed through this helper (with WithProvenance(memory.ProvenanceIntegrator)) instead of re-implementing the mapping, so framework-side recall treats seeded and runtime-written records identically.

type RecordEnumerator added in v0.3.0

type RecordEnumerator interface {
	ListAll(ctx context.Context, ns memory.Namespace) ([]Record, error)
}

RecordEnumerator is an optional Manager capability that lists every stored record in a namespace across all tiers. It backs index rebuild/reconciliation.

type SeedOption added in v0.3.1

type SeedOption func(*seedConfig)

SeedOption customizes MessageRecord.

func WithProvenance added in v0.3.1

func WithProvenance(provenance string) SeedOption

WithProvenance tags the seeded message with a provenance marker (see memory.ProvenanceRunTurn, memory.ProvenanceIntegrator) recorded inside the message metadata, exactly how the runtime tags its own writes. It does not affect recall scoring.

type Settings

type Settings struct {
	Enabled       bool                `json:"enabled,omitempty" yaml:"enabled"`
	HotCapacity   int                 `json:"hot_capacity,omitempty" yaml:"hot_capacity"`
	WarmCapacity  int                 `json:"warm_capacity,omitempty" yaml:"warm_capacity"`
	ColdCapacity  int                 `json:"cold_capacity,omitempty" yaml:"cold_capacity"`
	HotTTL        time.Duration       `json:"hot_ttl,omitempty" yaml:"hot_ttl"`
	WarmTTL       time.Duration       `json:"warm_ttl,omitempty" yaml:"warm_ttl"`
	PromoteAccess int                 `json:"promote_access,omitempty" yaml:"promote_access"`
	DemoteIdle    time.Duration       `json:"demote_idle,omitempty" yaml:"demote_idle"`
	RecallBudget  RecallBudget        `json:"recall_budget,omitempty" yaml:"recall_budget"`
	RecallWeights RecallWeights       `json:"recall_weights,omitempty" yaml:"recall_weights"`
	ColdSummary   ColdSummarySettings `json:"cold_summary,omitempty" yaml:"cold_summary"`
}

Settings configures tiered memory for a scenario memory reference.

func SettingsFromCore

func SettingsFromCore(ref *core.MemoryTierSettings) (Settings, bool)

SettingsFromCore converts a scenario memory tier reference into tier settings.

func (Settings) Budget

func (s Settings) Budget() RecallBudget

Budget returns the normalized recall budget for tier recall.

func (Settings) Policy

func (s Settings) Policy() Policy

Policy returns the effective tier policy from settings, overlaying defaults.

func (Settings) Weights

func (s Settings) Weights() memory.RecallWeights

Weights returns normalized RankMemories weights.

type Store

type Store interface {
	Put(ctx context.Context, ns memory.Namespace, record Record) error
	Get(ctx context.Context, ns memory.Namespace, id string) (Record, error)
	List(ctx context.Context, ns memory.Namespace, level Level, limit int) ([]Record, error)
	Delete(ctx context.Context, ns memory.Namespace, id string) error
	Count(ctx context.Context, ns memory.Namespace, level Level) (int, error)
}

Store persists tier-scoped memory records.

type TruncateColdSummaryBackend added in v0.2.0

type TruncateColdSummaryBackend struct {
	Settings   ColdSummarySettings
	Vector     ColdSummaryIndexer
	Summarizer ContentSummarizer
}

TruncateColdSummaryBackend summarizes large records with a deterministic truncate fallback.

func (TruncateColdSummaryBackend) Archive added in v0.2.0

func (TruncateColdSummaryBackend) Delete added in v0.2.0

func (TruncateColdSummaryBackend) SearchRecordIDs added in v0.2.0

func (b TruncateColdSummaryBackend) SearchRecordIDs(ctx context.Context, ns memory.Namespace, query string, limit int) ([]string, error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL