Local multimodal memory for AI apps, agents, devices, and humans.
Cortext is a C++20 memory engine that ingests text, audio, and image signals, stores durable memory traces in SQLite, and returns a small context packet of relevant memories on later calls. It is designed for long-running assistants and realtime applications that need memory without sending an entire history window back to an LLM.
Links: Releases / Python / JavaScript / Paper / Roadmap
v1.1.10: publicRetention::Ephemeralcalls force a retrieval boundary without writing the query, so CLI/package recall works as documented.v1.1.9: package examples use real OpenAI Chat Completions message arrays.v1.1.8: PyPI and npm packages ship cross-platform native libraries/addons and download the verified AIST q8_0 model into a user cache on first use.- Public C++
Retention::Ephemeralis the no-storage query path: it still updates live context and retrieves memory, but does not store the query. - Command-line tools are built with
CORTEXT_BUILD_TOOLS=ON; examples remain behindCORTEXT_BUILD_EXAMPLES=ON.
Choose the surface you need.
Python:
pip install augmem.cortextNode.js / TypeScript:
npm install @augmem/cortextC++ from source:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
ctest --test-dir build -R cortext_tests --output-on-failureBuild the CLI:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCORTEXT_BUILD_TOOLS=ON
cmake --build build -j --target cortext_cli
./build/tools/cli/cortext_cli --helpThe default CMake build downloads the required AIST model into models/.
For offline setup, prefetch it explicitly:
python3 scripts/download_aist_model.py --output-dir models --quant q8_0cortext_cli is a small public-API smoke test and a useful local memory tool.
It writes durable memories to a SQLite file and supports ephemeral recall.
./build/tools/cli/cortext_cli --db bailey.db remember \
"Bailey is allergic to bee stings and needs Benadryl within 10 minutes."
./build/tools/cli/cortext_cli --db bailey.db remember \
"The vet appointment for Bailey is on July 12 at 9am with Dr. Okafor."
./build/tools/cli/cortext_cli --db bailey.db recall \
"what should the vet know about the dog?"Corrections supersede stale facts:
./build/tools/cli/cortext_cli --db bailey.db remember \
"Correction: the vet appointment was moved to July 14 at 2pm."
./build/tools/cli/cortext_cli --db bailey.db recall \
"when is the vet appointment?" --top 1Other CLI commands:
./build/tools/cli/cortext_cli --db memory.db repl
./build/tools/cli/cortext_cli --db memory.db remember - < facts.txt
./build/tools/cli/cortext_cli --db memory.db consolidaterecall is ephemeral by default. Pass --durable if you also want the recall
query stored under the cli/recall source.
Cortext is built around a local feedback loop:
- Durable memory: signal metadata in SQLite, payloads in sqlite-objstore, and vector retrieval through sqlite-vec.
- Multimodal embeddings: text, audio, speech, and image inputs share one AIST-87M GGUF retrieval space.
- Three control knobs: Focus (F), Sensitivity (S), and Stability (T) derive thresholds, decay, storage cadence, consolidation, and retrieval behavior.
- Graph-native context: memories are connected by reinforcement, sequence, soft anchors, consolidation, and supersession edges.
- Small native surface: C++ facade, stable C ABI, and bindings for Python, Go, JavaScript/TypeScript, Dart, and WebAssembly.
- Research traceability: experiments, ablations, and manuscript sections
live in
docs/paper/next to the implementation.
Use Cortext when an app or agent outlives its context window. Instead of resending tens of thousands of history tokens or maintaining a separate RAG pipeline, you ask Cortext for the current memory packet and inject the returned retrieval results into your model or UI.
Requirements:
- C++20 compiler
- CMake 3.16+
- Git and Python 3 for dependency/model bootstrap
Standard debug build:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build -j
ctest --test-dir build -R cortext_tests --output-on-failureModel-free CI-style gate:
./build/tests/cortext_tests '~[aist]' --reporter compactBuild examples:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DCORTEXT_BUILD_EXAMPLES=ON
cmake --build build -j --target cortext_topical_chat_analysis
./build/examples/topical_chat_analysis/cortext_topical_chat_analysis --helpBuild an installable CLI with Zig:
zig build -Doptimize=ReleaseFast -Dshared=false -Dcli=true -Dfetch-aist-model=false
./zig-out/bin/cortext_cli --helpCross-build CLI artifacts:
zig build -Dtarget=x86_64-linux-gnu -Doptimize=ReleaseFast -Dshared=false -Dcli=true -Dfetch-aist-model=false
zig build -Dtarget=aarch64-linux-gnu -Doptimize=ReleaseFast -Dshared=false -Dcli=true -Dfetch-aist-model=false
zig build -Dtarget=x86_64-windows-gnu -Doptimize=ReleaseFast -Dshared=false -Dcli=true -Dfetch-aist-model=false
zig build -Dtarget=x86_64-macos -Doptimize=ReleaseFast -Dshared=false -Dcli=true -Dfetch-aist-model=false
zig build -Dtarget=aarch64-macos -Doptimize=ReleaseFast -Dshared=false -Dcli=true -Dfetch-aist-model=falseImportant CMake options:
CORTEXT_BUILD_TOOLS=ON: build command-line tools.CORTEXT_BUILD_EXAMPLES=ON: build examples and benchmark demos.CORTEXT_FETCH_AIST_MODEL=ON: download AIST during build.CORTEXT_AIST_MODEL_QUANT=q8_0: chooseq8_0,q5_1, orall.CORTEXT_FETCH_GGML=ON: fetch and build bundled GGML.CORTEXT_USE_SYSTEM_GGML=ON: use a preinstalled GGML for packagers.CORTEXT_EXPERIMENT_HOOKS=OFF: compile out eval-only ablation hooks.
#include <cortext/cortext.hpp>
#include <iostream>
#include <string>
std::string MemoryText (const cortext::Cortext::Context::Memory &memory)
{
std::string text;
for (const auto &blob : memory.content)
{
if (!text.empty ())
{
text.push_back (' ');
}
text.append (blob.begin (), blob.end ());
}
return text;
}
int main ()
{
cortext::Cortext::Config cfg;
cfg.focus = 0.7;
cfg.sensitivity = 0.5;
cfg.stability = 0.8;
auto engine = cortext::Cortext::Create (cfg, "memory.db");
engine->ProcessText ("The garage door code is 8841.", "chat/main");
auto ctx = engine->ProcessText (
"garage door code",
"chat/query",
cortext::Retention::Ephemeral);
for (const auto &memory : ctx.retrieved_memory)
{
std::cout << memory.relevance << " " << MemoryText (memory) << "\n";
}
if (ctx.consolidation_recommended)
{
engine->Consolidate ();
}
engine->Flush ();
}Public entrypoints:
- C++ API:
include/cortext/cortext.hpp - C API:
include/cortext/capi.h
Core calls:
ProcessText,ProcessAudio,ProcessImage: process a signal and store it by default.Retention::Ephemeral: process and retrieve without storing the input.EmbedText,EmbedAudio,EmbedImage: embedding-only calls that do not mutate memory state.Consolidate: explicit shallow consolidation.Flush: commit pending episode writes.Reset: reset volatile processor state while keeping durable memory.
Processing calls return Cortext::Context in C++ and JSON through the C API
and language bindings.
Top-level fields include:
retrieved_memory: long-term memories selected for the current signal.working_memory: active short-term memory slots.embedding: the current signal embedding when requested.should_interrupt,interrupt_aborted,at_boundary: realtime behavior.consolidation_recommended,consolidation_required: maintenance hints.output: scores, write decisions, operation timings, and storage ids.encode_ms,process_ms,hydrate_ms,total_ms: latency breakdown.
Each memory entry includes provenance, modality, stored content, retrieval scores, usage counts, and optional soft-anchor metadata:
{
"id": 1,
"source_id": "chat/main",
"timestamp": 1783463360158,
"modality": "text",
"mimetype": "text/plain",
"content": [
{
"base64": "VGhlIGdhcmFnZSBkb29yIGNvZGUgaXMgODg0MS4=",
"size_bytes": 29
}
],
"relevance": 0.96,
"salience": 0.0,
"contradiction": 0.0,
"retrieved_count": 1,
"used_count": 0,
"soft_anchors": []
}For C++ callers, Memory::content is already raw bytes. For JSON callers,
decode content[].base64 according to mimetype.
- Python:
bindings/python, published asaugmem.cortext - JavaScript/TypeScript:
bindings/javascript, published as@augmem/cortext - Go:
bindings/go - Dart:
bindings/dart - WebAssembly:
bindings/wasm
Build Python wheels with bundled native libraries:
python3 scripts/build_python_package.py --zig /path/to/zig --skip-modelsBuild the npm package:
python3 scripts/build_javascript_package.py --zig /path/to/zig --skip-modelsRegistry packages do not embed the 135 MB AIST q8_0 model. Python and npm
wrappers resolve a bundled/local model if present, otherwise download and
checksum-verify q8_0 into the user cache on first engine creation. Native C++
and CLI users should keep the model under models/ or set
CORTEXT_AIST_MODEL_PATH.
Cortext requires the AIST-87M GGUF encoder. The runtime searches:
CORTEXT_AIST_MODEL_PATHmodels/AIST-87M-GGUF/AIST-87M_q8_0.ggufmodels/AIST-87M-GGUF/AIST-87M_q5_1.gguf
The tokenizer vocab is expected under models/mdbr-leaf-ir/vocab.txt.
AIST maps text, audio, and images into one retrieval space. Audio inputs are 16 kHz mono float32 PCM. Image inputs are row-major RGB/RGBA bytes with explicit width, height, and channel count.
Every database pins the encoder fingerprint that produced its embeddings. Changing encoder assets for an existing database fails loudly instead of silently comparing vectors from different spaces.
Useful environment variables:
CORTEXT_AIST_MODEL_PATH: explicit model file.CORTEXT_AIST_THREADS: native runtime thread count.CORTEXT_AIST_N_GPU_LAYERS: GPU offload layer hint.CORTEXT_AIST_CONTEXT_LENGTH: tokenizer/runtime context length.CORTEXT_SQLITE_*,CORTEXT_OBJSTORE_*: storage tuning for packagers and profiling.
Cortext separates metadata from payload storage:
cortext::Store/cortext::Transaction: database boundary.SQLiteStore: built-in metadata store.cortext::ObjectStore/cortext::ObjectTransaction: payload boundary.SqlObjectStore: built-in sqlite-objstore implementation.
Store and transaction instances are single-owner handles. Use a single writer per database; Cortext does not merge concurrent writer state.
Long-horizon evals replay multi-session conversations through each memory system. At probe points, a judge LLM blind-scores each context packet for relevance, sufficiency, and noise.
Headline hosted frontier judge run on a public Meta Multi-Session Chat slice: Cortext won 7 of 9 probes by majority and 21 of 27 blind judgment rows, using 998 context tokens per turn versus 49,196 for traditional chat+RAG.
| Eval | Result | Context Cost |
|---|---|---|
| MSC hosted frontier judge, 9 probes, 3 reps | Cortext 7/9 probe wins, 21/27 row wins | 998 tokens vs 49,196 for chat+RAG |
| MSC 128k RAG ablation, 6 systems | Cortext 6/9 probe wins, 19/27 row wins | 816 tokens; compaction 7,110; rolling window 15,999 |
| One-year sparse replay, local Gemma4 judge | Cortext 47/93 raw wins | 467 tokens vs 7,447 for chat+RAG |
| Long-horizon mechanism sweep | No removal improved the stack | Mechanisms retained under the hard-cut rule |
Full protocols, caveats, and artifacts are in
docs/paper/sections/9_experimental.qmd and
docs/paper/_manuscript/index.md.
flowchart TD
input["input<br/>(text / audio / image)"] --> perception[perception]
perception --> accumulator[stream accumulator]
accumulator --> wm[working memory]
wm --> retrieval[graph retrieval]
retrieval --> ctx[context out]
wm --> consolidation[shallow consolidation]
consolidation --> ltm[long-term store]
retrieval -. usage / prediction error .-> control
ltm -. storage pressure .-> control
control["homeostatic control<br/>F / S / T"]
control -. write gates / thresholds / decay / cadence .-> perception
control -.-> accumulator
control -.-> wm
control -.-> consolidation
The production loop is composed from small operations in src/operations/.
Retrieval combines embedding similarity, graph edges, temporal scoring,
supersession demotion, soft anchors, and working-memory state. Feedback updates
F/S/T so later writes, decay, thresholds, attention width, and consolidation
cadence adapt to the stream.
The browser build uses Emscripten and emits an ES module plus .wasm payload:
./build-wasm.shThe wrapper lives in bindings/wasm/cortext.js; the browser demo lives in
examples/web/. For demos, either select the AIST model file in the UI or
preload it:
./build-wasm.sh -DCORTEXT_WASM_PRELOAD_MODEL_ASSETS_DIR="$PWD/models"
python3 -m http.server 8000Then open http://localhost:8000/examples/web/.
- Context reduction over maximal sufficiency. Cortext is optimized to return a small, relevant packet. Full history can be more complete if you can afford the tokens and prefill latency.
- Pinned local encoder. Databases are tied to the embedding model fingerprint that produced them.
- Single writer per database. Multi-device sync and concurrent-writer merge are not implemented.
- Source-backed traces. v1 stores and retrieves observed signals; it does not run an LLM fact extraction layer that rewrites memories.
- Native runtime. C++20 and local model assets are part of the core deployment story.
include/,src/: public headers and C++ implementation.src/operations/: control-loop and memory pipeline operations.tests/: Catch2 test suite.examples/: benchmarks, demos, and smoke tests.bindings/: Python, Go, JavaScript/TypeScript, Dart, and WebAssembly FFI.scripts/,tools/: CLI, release packaging, experiment harnesses, and offline utilities.docs/paper/: manuscript source, generated markdown, and artifacts.models/,third_party/: local model assets and vendored dependencies.
The architecture and experimental record are specified in the manuscript:
QUARTO_DISABLE_GIT=1 QUARTO_DISABLE_GITHUB=1 quarto render docs/paperStart with docs/paper/_manuscript/index.md, or edit source sections under
docs/paper/sections/.
Cortext began for a personal reason. In 2022, my father-in-law was diagnosed with dementia. The long-term goal is memory augmentation that helps people preserve continuity, confidence, and independence.
The same architecture is useful for long-horizon LLM memory, but the primary motivation is human: a realtime system that notices what matters, surfaces relevant context, and does not force the user to manage memory by hand.