js/ai/memory

js/ai/memory.ts

fino:ai/memory — durable, cross-session semantic memory for agents.

Memory stores embedding-backed facts and behaviours, not conversation history. SqliteMemory supplies durable storage, uses sqlite-vec for scoped cosine search when available, and falls back to an exact scan otherwise. agentMemory() adds recall policy, labels, bounded utility evidence, optional reinforcement, and optional forgetting. Controllers sharing a namespace and store see the same committed memories, including from concurrent sessions.

Signals and storage

Recall records exposure but does not assume a hit was useful. Applications can complete a returned selection with an eval score, or set stronger memory-specific manual feedback. The store keeps aggregates and bounded, short-lived selection receipts rather than prompts or an evidence ledger.

Conversation history and summarization remain in fino:ai/context and fino:ai/session. See Agent Memory for the full usage and lifecycle guide.

import { agentMemory, memoryTool, SqliteMemory } from 'fino:ai/memory';

const store = await SqliteMemory.open({ path: './memory.db', embedder });
const memory = agentMemory({ store, namespace: 'engineering' });
const remember = memoryTool(memory, { sessionId: 'debugging' });
await remember.run({ text: 'Prefer narrow root-cause fixes.', durability: 'shared' });
const selection = await memory.recall({ text: 'How should I fix this?' });
await memory.complete(selection.selectionId, { score: .9 });

Interfaces

interface Embedder {

Minimal embedding provider required by semantic memory.

Methods

embed(texts: string[]): Promise<Float32Array[]>

Embed texts in input order. Every vector must have dimensions values.

Readonly Properties

readonly dimensions: number

Fixed width of vectors produced by embed(). Must be positive.

interface ContextualMemoryUtility {

One compact utility aggregate for a label context.

Properties

key: string

Stable normalized representation of the context labels.

evalCount: number

Number of eval outcomes aggregated into this context.

evalSum: number

Sum of conservatively distributed eval scores.

updatedAt: number

Last update time in milliseconds since the Unix epoch.

interface MemoryUtility {

Compact evidence retained for one memory. No raw messages are stored.

Properties

exposures: number

Number of times this memory was returned by recall.

lastExposedAt: number | null

Last exposure time, or null before first recall.

evalCount: number

Number of eval bundles contributing to this memory.

evalSum: number

Sum of conservatively distributed eval scores.

manual: number | null

Mutable manual value in [-1, 1], or null when unset.

manualUpdatedAt: number | null

Last manual feedback time, or null.

reinforcedAt: number | null

Last positive reinforcement time, or null.

contexts: ContextualMemoryUtility[]

Bounded utility summaries for relevant label contexts.

interface MemoryRecord {

A stored semantic memory.

Properties

id: string

Stable store-assigned identifier.

text: string

Text embedded and returned to an agent when recalled.

scope: MemoryScope

Explicit access scope.

labels: MemoryLabels

Normalized descriptive labels.

metadata?: Record<string, unknown>

Optional application metadata, not interpreted by memory policy.

importance: number

Base retention importance in [0, 1]. Defaults to .5.

createdAt: number

Creation time in milliseconds since the Unix epoch.

updatedAt: number

Last mutation time in milliseconds since the Unix epoch.

expiresAt: number | null

Expiry time for semi-ephemeral entries, or null.

utility: MemoryUtility

Compact mutable utility state.

interface MemoryCandidate extends MemoryRecord {

Candidate returned by a MemoryStore before controller policy reranking.

Properties

similarity: number

Embedding similarity, where larger values are more relevant.

interface MemoryStoreInput {

Input accepted by the durable store. Controllers normally construct this.

Properties

text: string
scope: MemoryScope
labels: MemoryLabels
metadata?: Record<string, unknown>
importance: number
createdAt: number
expiresAt: number | null
embedding: Float32Array

interface MemorySelectionReceipt {

Short-lived receipt connecting an eval outcome to an exact recall bundle.

Properties

id: string
namespace: string
memoryIds: string[]
contextKey: string
createdAt: number

interface MemoryStore {

Durable mechanism used by AgentMemoryController.

Implementations must make consumeSelection() single-use and atomically apply its aggregate updates. Store values are plain structured data so the interface can be adapted across Realm boundaries.

Readonly Properties

readonly semanticAvailable: boolean

Whether embeddings can be searched.

Methods

embed(texts: string[]): Promise<Float32Array[]>

Embed query or entry text using the store's compatible embedding model.

put(input: MemoryStoreInput): Promise<MemoryRecord>

Persist one fully-scoped entry.

setLabels(id: string, labels: MemoryLabels, updatedAt: number): Promise<MemoryRecord | null>

Replace labels after best-effort automatic classification.

get(id: string): Promise<MemoryRecord | null>

Return one memory by id, including currently suppressed entries.

search(input: { namespace: string; sessionId?: string; embedding: Float32Array; limit: number; }): Promise<MemoryCandidate[]>

Search shared and optionally matching session entries by embedding.

recordSelection(receipt: MemorySelectionReceipt, maxSelections: number): Promise<void>

Record exposures and a bounded selection receipt.

consumeSelection(input: { selectionId: string; score: number; now: number; maxContexts: number; reinforce: boolean; }): Promise<boolean>

Consume one receipt and apply an eval contribution exactly once.

setManual( id: string, value: number | null, now: number, reinforce: boolean, ): Promise<MemoryRecord | null>

Replace or clear memory-specific manual feedback.

close(): Promise<void>

Release owned storage resources. Repeated calls are harmless.

interface MemoryLabelInput {

Input supplied to a configurable lightweight label classifier.

Properties

text: string

Text or summary being classified.

source: 'memory' | 'message' | 'session'

Classification moment, allowing different prompts or rules.

interface MemoryLabeler {

Optional classifier used to infer bounded labels.

Methods

label(input: MemoryLabelInput): Promise<MemoryLabels>

Return proposed labels. Errors are treated as best-effort failures.

interface MemoryLabelRules {

Rules controlling automatic and explicit label cardinality.

Properties

allowed?: Record<string, string[]>

Allowed keys and, when non-empty, allowed values for each key.

maxPerKey?: number

Maximum retained values per key. Defaults to 3.

interface RememberMemoryInput {

Input for creating a memory directly or through the creation tool.

Properties

text: string

Text to embed and remember.

scope?: MemoryRememberScope

Shared by default; session scope requires an explicit session id.

labels?: MemoryLabels

Explicit labels committed with the entry.

metadata?: Record<string, unknown>

Application metadata copied to the entry.

importance?: number

Base importance in [0, 1]. Defaults to .5.

expiresAt?: number

Optional expiry time in milliseconds since the Unix epoch.

interface MemoryQuery {

Query for semantic recall.

Properties

text: string

Natural-language text to embed.

topK?: number

Maximum returned hits. Defaults to 5.

sessionId?: string

Include session-scoped memories for this session in addition to shared memories.

runId?: string

Optional run identifier retained only by the caller, not as evidence.

labels?: MemoryLabels

Message or session labels used for boosts and contextual utility.

filter?: { labels?: MemoryLabels; metadata?: Record<string, unknown> }

Explicit hard filters.

interface RecallHit extends MemoryRecord {

A recalled entry with semantic and policy ranking details.

Properties

similarity: number

Raw embedding similarity.

score: number

Final controller score after bounded boosts and optional utility.

retention: number

Current retention multiplier; 1 when forgetting is disabled.

citation: { id: string; metadata?: Record<string, unknown> }

Source attribution suitable for model context or UI.

interface MemorySelection {

Immutable result of one recall operation.

Properties

selectionId: string

Single-use id accepted by complete().

labels: MemoryLabels

Normalized labels describing this work chunk.

hits: RecallHit[]

Ranked semantic hits.

interface MemoryForgettingOptions {

Optional exponential retention policy.

Properties

halfLifeMs: number

Base half-life in milliseconds before importance and utility adjustments.

suppressBelow?: number

Suppress hits below this retention multiplier. Defaults to .05.

interface AgentMemoryOptions {

Controller construction options.

Properties

store: MemoryStore

Durable shared store.

namespace: string

Access namespace bound to this controller.

labeler?: MemoryLabeler

Optional lightweight automatic classifier.

labelRules?: MemoryLabelRules

Label normalization and vocabulary rules.

reinforcement?: boolean

Whether utility affects ranking and retention. Defaults to false.

forgetting?: false | MemoryForgettingOptions

Exponential forgetting policy, or false to disable it. Defaults to false.

maxContexts?: number

Maximum contextual summaries retained per memory. Defaults to 8.

maxSelections?: number

Maximum outstanding selection receipts per namespace. Defaults to 256.

overfetch?: number

Semantic candidates considered per requested hit. Defaults to 4.

minSimilarity?: number

Minimum semantic similarity admitted to policy ranking. Defaults to .01.

now?: () => number

Injected clock used by all lifecycle policy. Defaults to Date.now.

interface Retriever {

Narrow semantic retrieval adapter for RAG call sites.

Methods

retrieve(text: string, opts?: Omit<MemoryQuery, 'text'>): Promise<RecallHit[]>

Return recalled hits for text, with call options overriding defaults.

interface SqliteMemoryOptions {

Options for opening the sqlite-backed durable memory store.

Properties

path: string

Filesystem path of the database, created when absent.

embedder: Embedder

Embedding model defining the store's vector space.

fs?: object

Optional filesystem provider forwarded to sqlite.

interface MemoryToolOptions {

Options binding namespace-safe authority into memoryTool().

Properties

sessionId?: string

Session id allowed for session-durability writes.

name?: string

Model-visible tool name. Defaults to remember.

Types

type MemoryScope = | { type: 'shared'; namespace: string } | { type: 'session'; namespace: string; sessionId: string }

A durable shared scope or a semi-ephemeral session scope.

type MemoryLabels = Record<string, string[]>

Bounded, normalized labels used for filtering, ranking, and utility context.

type MemoryRememberScope = { type: 'shared' } | { type: 'session'; sessionId: string }

Caller-facing scope. Namespace authority is bound by the controller.

type MemoryOptions = Omit<AgentMemoryOptions, 'store'> & SqliteMemoryOptions

Options for opening sqlite storage and constructing a controller at once.

Classes

class SqliteMemory implements MemoryStore {

Sqlite implementation of the durable MemoryStore contract.

Getters

get semanticAvailable(): boolean

Embedding search is available whenever the configured dimension is positive.

Methods

embed(texts: string[]): Promise<Float32Array[]>

Embed text with the model that defines this store's vector space.

put(input: MemoryStoreInput): Promise<MemoryRecord>

Persist one memory after validating its embedding width.

setLabels(id: string, labels: MemoryLabels, updatedAt: number): Promise<MemoryRecord | null>

Replace labels for an existing memory.

async get(id: string): Promise<MemoryRecord | null>

Load a memory by id.

async search(input: { namespace: string; sessionId?: string; embedding: Float32Array; limit: number; }): Promise<MemoryCandidate[]>

Search embeddings in the shared namespace and one optional session scope.

recordSelection(receipt: MemorySelectionReceipt, maxSelections: number): Promise<void>

Atomically record aggregate exposure and retain a bounded selection receipt.

consumeSelection(input: { selectionId: string; score: number; now: number; maxContexts: number; reinforce: boolean; }): Promise<boolean>

Consume a selection once and aggregate its observational eval score.

setManual( id: string, value: number | null, now: number, reinforce: boolean, ): Promise<MemoryRecord | null>

Replace or clear the compact manual value for one memory.

async close(): Promise<void>

Close the sqlite connection.

Static Methods

static async open(opts: SqliteMemoryOptions): Promise<SqliteMemory>

Open a sqlite memory store, creating its versioned schema when needed. The optional fs is forwarded to Database.open().

class AgentMemoryController {

Stateful policy coordinator over a durable, concurrently shared store.

The controller has no ambient current-session slot. Every session-specific operation carries an explicit session id, so one controller can safely be shared by simultaneous agent sessions.

Constructors

constructor(opts: AgentMemoryOptions)

Create a controller. Prefer the agentMemory() factory.

Getters

get namespace(): string

Namespace bound to this controller.

Methods

labels(input: MemoryLabelInput): Promise<MemoryLabels>

Classify a message, memory candidate, or session summary with the configured bounded label rules. Returns an empty object on classifier failure or when no labeler is configured.

async remember(input: RememberMemoryInput): Promise<MemoryRecord>

Embed, commit, and optionally auto-label one durable memory.

async recall(query: MemoryQuery): Promise<MemorySelection>

Recall semantic memories and record bounded exposure evidence.

complete(selectionId: string, outcome: { score: number }): Promise<boolean>

Apply one observational eval score to a returned selection.

async feedback( memoryId: string, feedback: { value: number | null }, ): Promise<MemoryRecord | null>

Set, replace, or clear the strongest memory-specific utility signal.

get(memoryId: string): Promise<MemoryRecord | null>

Inspect one entry without applying recall policy or exposure.

close(): Promise<void>

Close the owned or injected store. Repeated calls are delegated safely.

Functions

function agentMemory(opts: AgentMemoryOptions): AgentMemoryController

Create a policy controller over a shared durable memory store.

function retriever( memory: AgentMemoryController, defaults: Omit<MemoryQuery, 'text'> = {}, ): Retriever

Create a narrow semantic retriever over an agent-memory controller.

function memoryTool( memory: AgentMemoryController, opts: MemoryToolOptions = {}, ): Tool< { text: string; durability?: 'shared' | 'session'; labels?: MemoryLabels; importance?: number; expiresAt?: number; }, { content: string } >

Create an opt-in validated tool for memory creation.

Namespace is always bound by the controller. A session write is rejected unless the tool factory was given a session id, preventing model arguments from selecting arbitrary scopes.

async function memory(opts: MemoryOptions): Promise<AgentMemoryController>

Convenience factory that opens a sqlite store and binds a controller.