Skip to main content
Quark implements a dual-layer memory system that mirrors human cognition: fast, temporary recall for the current session and durable, summarized knowledge that persists across sessions. A third store — local SQLite — keeps a permanent, unabridged chat history that never expires.

Overview

LayerTechnologyScopeExpires
Short-Term Memory (STM)RedisSession30 minutes of inactivity
Long-Term Memory (LTM)Mem0UserNever
Chat historySQLiteLocal deviceNever
STM stores the recent message history for a single session in Redis. It is the primary source of conversational context during an active chat.Key format:
stm:{sessionId}
Each key holds a Redis list of serialized ChatMessage objects. Three functions manage the list:
export const addSTMMessage = async (
  sessionId: string,
  message: ChatMessage,
)
Appends a message and immediately calls lTrim to keep the list within MAX_MESSAGES. Then sets the TTL to TTL_SECONDS to start (or reset) the inactivity clock.
export const getSTM = async (
  sessionId: string,
): Promise<ChatMessage[]>
Fetches the full list for the session and deserializes each entry.
export const trimSTM = async (sessionId: string)
Trims the list to the most recent TRIM_TO messages. Called automatically during memory compression (see below).STM constants:
ConstantValueMeaning
STM_PREFIX"stm:"Redis key namespace
MAX_MESSAGES20List length before compression is triggered
TRIM_TO10Messages retained after compression
TTL_SECONDS1800Inactivity TTL in seconds (30 minutes)
STM is session-scoped. If a session is idle for 30 minutes, Redis expires the key and the next message starts a fresh context window. Long-term facts are preserved in Mem0 and are not affected by expiry.

How memory is assembled at query time

Inside retriveContext in retrival.ts, all three memory sources are fetched and combined before the LLM call:
const stmMessage = await getSTM(retrival.sessionId ?? "");
const contextMemory = await mem0Search(_mem0Search);

// ... vector search ...

const finalPrompt = Response(
  `${stmContext(stmMessage)}\n${contextMemory}\n${_contextString}`,
  retrival.filters,
  retrival.message,
);
The context window passed to the LLM is:
  1. STM context — the recent conversation turns formatted as role: content lines.
  2. LTM context — summarized long-term facts from Mem0.
  3. Vector search results — the re-ranked document chunks most relevant to the current question.
This ordering prioritizes recent conversational state, then durable user knowledge, then document content.

Local chat history (SQLite)

Separately from STM and LTM, every exchange is written to a local SQLite database. This store:
  • Never expires — it is a permanent audit log of all conversations.
  • Stays on your device — no data leaves your local machine.
  • Is not used as retrieval context; it exists for user-facing chat history display.
The SQLite history and the Redis STM are independent. Clearing your Redis instance (or waiting for the TTL to expire) does not delete your chat history from SQLite.

Build docs developers (and LLMs) love