Skip to content

Architecture

The write paths, retrieval pipeline, utility-aware decision, and supported deployment boundary.

Retold separates who requests a search from how retrieved records enter an answer.

Mode Behavior Status
tool_only The agent receives the five memory tools and calls them when its task needs memory. Default
utility_aware The host drafts an answer, retrieves only for a specific missing fact, and admits records only when they would change the draft. Opt-in

The utility-aware path needs host-supplied model clients and supported_bundle() from retold.policy.reference. A store serves the bundle only after recording a passing fitness result. Otherwise, the path runs in shadow mode. Planner, provider, judge, timeout, and latency-budget failures all serve the original draft and record the reason.

Utility-aware memory path: draft first, retrieve only for specific missing context, and revise only with admitted records

How the decision works

  1. Receive the user turn. The host receives the user query along with public context, such as the current conversation and system instructions.
  2. Draft an answer without conditional memory. The model produces a usable first draft before Retold retrieves any stored records. This draft is the safe fallback.
  3. Check whether stored context is needed. In parallel with drafting, the planner checks whether the answer may require a previous decision, user preference, project fact, or other specific memory. It sees only the kinds of memory available, not the records themselves.
  4. Keep the original draft when memory is unnecessary. Ordinary questions stop here. Retold performs no search, adds no conditional memory to the model context, and introduces no retrieval latency beyond the planner running alongside the draft.
  5. Search for the missing context. When memory may help, Retold searches specifically for the missing information. Before ranking candidates, it filters records by the caller's grants, scope, lifecycle state, type, and time constraints.
  6. Judge whether the retrieved context would change the draft. Finding a related record is not enough. The admission judge compares each candidate with the existing draft and asks whether it would materially correct, complete, or personalize the answer.
  7. Keep the original draft when nothing is useful. Retrieved but unnecessary records are rejected and never reach the answering model.
  8. Revise once when useful context exists. The model receives only the admitted records and regenerates the answer once. Rejected candidates remain excluded.
  9. Serve the answer. The final result is either the original memory-free draft or one revision informed by useful, authorized memory.

The default quick start does not invoke a hosted provider. Call worker = memory.finish(extract=True) when you want the facade to run background transcript extraction. Retold checks the provider dependency and API key before ending the session. Keep Retold open until worker.join() completes if the process is about to exit.

Security without setup ceremony

Retold derives identity from application-controlled configuration. A model can ask to use memory, but it cannot choose its principal, user, session, or raw scope ID.

Concept Meaning
Principal The agent and user making the request, plus the current session and optional project
Scope The owner of a set of records: a private agent-user pair, user, project, or organization
Grant Permission for an agent to read or write a shared scope
Session The conversation that supplies evidence and consumes memory

Every agent-user pair receives an implicit private scope. The facade uses it, so two users of the same agent cannot read each other's memories and no grant is necessary.

Applications use explicit grants when agents need shared memory:

from retold import MemoryHost, Scope

host = MemoryHost(retold.store)
host.grant("research-assistant", Scope("project", "retold"), read=True, write=True)

Retold filters by scope and grant before ranking candidates. A caller cannot infer a foreign record through search results, lookup errors, or decision logs.

How Retold works

Records enter through evidence checks

During a session, an agent can call memory_write with a claim and source quote. After a session, an optional extractor and separate reviewer can propose memories from the transcript. Both paths apply the same evidence, entity, duplicate, contradiction, authority, and lifecycle rules.

A direct user statement or tool result starts confirmed. An agent inference starts provisional and expires after 30 days unless later evidence reinforces it. Superseded records remain as lineage.

Searches can return nothing

memory_search uses one pipeline regardless of caller:

  1. Filter by scope, grant, lifecycle, type, and time.
  2. Generate candidates from the configured embedding model, SQLite FTS5 BM25, and exact entity aliases.
  3. Fuse the channels by reciprocal rank and decay old episodic records.
  4. Gate each candidate against its own evidence.
  5. Remove near-duplicates and fit results within a token budget.
  6. Log candidates, scores, decisions, explanations, and stage timing.

Warm searches measured 23 ms at 1,000 records and 74 ms at 50,000 records on the project fixtures.[^1]

Is Retold a fit?

Use Retold when you are building a Python agent that needs durable per-user or per-project memory, wants local storage and retrieval, and must preserve evidence, lifecycle, and access boundaries.

Current boundaries:

  • Retold is a Python library backed by SQLite, not a hosted service or distributed database.
  • Python 3.12 and 3.13 are supported.
  • The lite profile uses about 640 MB of local model files. The standard BGE-M3 profile uses about 2.8 GB.
  • Background extraction and model-backed utility-aware policies require configured Anthropic or OpenAI clients. The deterministic utility-aware example uses local scripted policies and needs no API key.
  • Utility-aware results come from controlled offline evaluation. Production users should begin in shadow mode and inspect their decision logs.

Before production

  • Choose one database per application and environment. Use separate databases for customers that require independent backups, deletion, or contractual isolation.
  • Pin the Retold version, model IDs, embedding dimensions, and calibrated retrieval floors.
  • Start utility-aware operation in shadow mode, inspect its decisions on application traffic, and approve only the bundle you measured.
  • Configure SQLite backups, retention, user erasure, and restoration tests.
  • Monitor search decisions, policy failures, background extraction, write contention, and latency.
  • Recalibrate retrieval and re-embed stored records before changing the embedding model.
  • Test provider timeouts and verify that the host serves the memory-free draft when a utility-aware stage fails.