How is memory and user context stored and retrieved?
Storage (DB, vector store, files); what is remembered; how it is injected into prompts; summarization.
Verdict
The two projects store memory very differently.
OpenBot keeps two kinds. Personal memories are free-text rows in Postgres, deduplicated by a content hash. Bots can propose observed facts that the person confirms or dismisses, and connected apps can be imported. PersonalMemoryMiddleware, an AG-UI middleware, injects them as a system message on every run. Conversation threads and learned skills are held by CopilotKit Intelligence, so a large part of the context is outside your database.
Rakazo keeps everything in its own Postgres. Messages are stored per thread and old history is compacted into an LLM summary that is injected into later runs. A MarkdownMemoryStore holds versioned Markdown documents per user, bot and scope, written and read through remember/recall_memory tools. Optional semantic providers (Serenity, Supermemory) add vector recall of up to five items, but only once a thread has been compacted. Memory text is passed through secret redaction before it reaches the prompt.
Pick OpenBot if a human-reviewed list of facts is what you want and you accept a hosted thread store. Pick Rakazo for self-contained, portable memory and long threads that need summarisation.
More projects in this category are being researched.
Per-project answers
CopilotKit/OpenBot
answeredStorage — PostgreSQL. Personal memories live in the personalMemories table in PostgreSQL, accessed through Drizzle ORM (server/src/db/schema/memory). The memory store (server/src/memory/store.ts:16-80) provides CRUD operations: list (up to 500, newest-first), create, formMemory (Bot-observed facts awaiting human review), update, remove. Deduplication uses a SHA-256 hash of lowercased content (deleted memories stay forgotten).
Memory types. Personal memories are free-text records with optional sourceApp and sourceLink. Bot-formed memories (formMemory) are observed facts the person can confirm or dismiss. A MemorySource records where imported data came from (a connected app). Memory import from connected apps is handled by normalizeConnectorRecords (server/src/memory/ingestion.ts:16-80) which parses JSON responses from external services (searching items, files, or results keys), normalizes records to text, and caps at 50 records or 256KB.
Injection into prompts. The PersonalMemoryMiddleware (server/src/memory/tools.ts:29-70) is an AG-UI Middleware that injects the person's memories as both a system message and a context entry on every agent run. The system message id is "openbot:personal-memory" — the middleware also deduplicates stale ones. Memory content is loaded asynchronously and injected before the run begins.
Learning (skills). ``CopilotKit Intelligence's Learning system (server/src/learning/runtime.ts:1-35) provides learned skills — reusable capabilities published from observed patterns. The runtime exposes copilotkit_load_skill and copilotkit_read_skill_file tools to agents, backed by CopilotKit Intelligence. A RemoteLearnedSkillsMiddleware injects learned skill context into agent runs. Learning targets are per-agent or default, configured through admin settings (server/src/learning/settings.ts).
elie222/rakazo
answeredStorage layers. Rakazo has three memory systems:
Conversation history — stored as
Messagerows in PostgreSQL (packages/db/src/messages.ts), scoped to athread. Each message has blocks (text, tool calls, images) and a sequentialseq. To manage context windows, history is compacted asynchronously viapackages/adapters/src/history-compaction.ts: messages beyond a sliding window of 50 are removed and replaced with an LLM-generated summary stored inthread.historyCompactionSummary. Compaction is triggered when the uncompacted window exceeds the batch size threshold (shouldEnqueueCompaction, line 20). The summary is injected as auser-role message in subsequent runs (line 6047-6054 of executor.ts).Markdown memory store (
packages/memory/src/index.ts—MarkdownMemoryStore): a user-and-bot-scoped key-value store for structured facts. Implements theMemoryStoreinterface from@rakazo/adapter-kit. Documents are stored inmemoryDocumentandmemoryRevisiontables. Supportsread(list docs by scope/path),commit(upsert with optimistic concurrency via revision numbers), andsearch(simple substring match on content/path). The agent callsremember/recall_memorytools to write/read from this store. It uses Prisma transactions withSerializableisolation (line 117).Semantic (vector) memory — optional providers accessed via
SpaceMemoryProviderResolver(packages/adapters/src/memory-provider-factory.ts). Supports Serenity (a self-hostable vector memory service) and Supermemory (external SaaS). These providers exposerecall(),save(), andforget()operations for semantic similarity search. The memory scope (isolatedvsshared, resolved inpackages/db/src/memory-config.ts) controls whether a bot sees only its own memories or the whole space's.
Injection into prompts. At run start, the executor calls semanticMemory.recall() (line 3459 of executor.ts) with the user's prompt as query, getting up to 5 relevant memories. The recalled text is formatted and injected into the prompt's historicalContext array (line 6056-6060). Similarly, compacted history summaries are injected as a synthetic user message. All memory content passes through redactSecrets() before injection.
← How are integrations (email, calendar, chat, docs) implemented? · How are actions on the user's behalf gated? →