Core concepts
How Lore turns a stream of agent events into a read-your-writes context pack.
At a glance: agents write to an append-only event log; Lore consolidates those events into versioned memories and claims; and a pack returns a budget-fit slice of that memory for a query.
Data flow
The middle "consolidate" step is an asynchronous pipeline. Writes never block on it — a write returns immediately, and the pipeline catches up behind the scenes.
Write
Agents stream events to a run. Each event gets a server-assigned monotonic seq (per run), and the
write returns right away with HTTP 202 — nothing blocks.
Extract
An async worker reads new events and distills them into candidate memories and claims. The default extractor is an offline, deterministic fixture, so this runs with no external API key.
Consolidate
Candidates are merged into the durable store: deduplicated against existing memories, and each claim's conflicts resolved by policy — last-writer-wins by default — then versioned. Superseded content is kept as version history, not overwritten.
Embed
Each memory gets a vector so it can be retrieved by meaning, not just keywords. The default is the offline fixture embedder; point Lore at an OpenAI-compatible endpoint for a real semantic space (see Configuration).
Pack
The read path assembles a budget-fit context for a query: live working facts, distilled memories, and a raw tail of not-yet-distilled events, in a deterministic order. The response reports how fresh the distilled view is.
Extract, consolidate, and embed together advance the run's distilled checkpoint — the high-water mark of events the pack can serve as distilled memory rather than raw tail.
Read-your-writes
The reason the checkpoint matters: agents work over a shared memory that a moment ago was being written by someone else. Lore gives you an API-level guarantee so you never have to guess whether your write is visible yet.
Give multi-agent teams a read-your-writes guarantee at the API level: when one agent writes, any later
packrequest can be guaranteed to reflect that write — either as a distilled memory, or as a raw tail until extraction catches up. The client always knows its consistency state instead of guessing.
Three fields carry the contract:
seq— every write returns a server-assigned, per-run monotonic counter. Keep it.min_seq— pass a prior write'sseqon a pack request to require the pack reflect your writes up to that point. Anything newer than the distilled checkpoint is included as a raw tail.covered_seq(+freshness_lag_ms) — the pack response reports the run's distilled checkpoint and the age of the oldest not-yet-distilled event.covered_seq >= min_seqmeans read-your-writes is satisfied from distilled memory; below it, the requested events are still served — as the raw tail.
The read-your-writes window (events up to min_seq) is never dropped from a pack, even under a tight
token budget. For the full contract and the design rationale, see
RFC 0001 — Read-your-writes.
Pack anatomy
A pack is a single sectioned envelope of data, not instructions. It opens with a header that tells any downstream model to treat everything below as retrieved reference — never as directives to follow — and then lays out its sections in a fixed, deterministic order:
- Working — live coordination facts written through the low-latency lane (a same-run reader sees them
immediately). Its source is reported as
live,durable, orunavailable.unavailablemeans this pack carries no working section — the live stripe was not authoritative and no durable snapshot existed; the facts are still stored and still reach you through the raw tail. No producer writes durable working snapshots yet, sodurableis in the contract but not currently returned. - Distilled memories — the consolidated semantic, episodic, and procedural knowledge retrieved for the query (hybrid vector + lexical retrieval).
- Raw tail — recent events extraction hasn't distilled yet, labelled as raw and unverified. The read-your-writes window is always included here; beyond it, a bounded number of the most recent events may be appended.
An optional token_budget caps the distilled section with a coarse chars / 4 ≈ tokens heuristic; whole
memories are dropped once the estimate exceeds the budget, while the working section and the
read-your-writes window are exempt. truncated in the response flags when anything was capped.
A separate optional degraded array reports retrieval legs that missed the server's partial-result budget
and contributed nothing to the pack — today only dense, when the embedding provider answered slower than
LORE_RETRIEVAL_PARTIAL_TIMEOUT. It is unrelated to token_budget: nothing was capped, a source simply
never arrived. The field is omitted entirely when every leg finished, so its presence is the signal that
this answer was assembled from fewer sources than are configured. The response is still 200 — the pack is
valid, just narrower.
saved_tokens in the response is an estimate (the same chars / 4 heuristic), not a measured count.
The /v1/pack request and response fields are defined in the
OpenAPI spec.