Skip to main content

Engram

Give your model a memory, local or cloud. One process, one SQLite file, zero code changes.

ci PyPI docs license

The Engram memory observatory: memories orbiting a neural core at radii set by their live activation The built-in observatory at /engram/ui: memories orbit by activation, reinforced ones fall inward, decaying ones drift out.

A selected memory with its hebbian web lit and the full dossier panel Hovering a mote shows its id, status, live activation, and title

Click a memory and its hebbian web stays lit, dossier alongside; hover any mote for its status, activation, and title.

Engram is a transparent proxy that sits between any client and Ollama. It recalls relevant memories from past sessions and injects them before the model answers (~22 ms overhead, no LLM on the request path), then summarizes each exchange in the background - using the same small model you're chatting with.

                 ┌─────────────────────────────┐
  client ──────► │ engramd :11435              │ ──────► ollama :11434
  (curl,         │  recall → inject → forward  │
   openclaw,     │  response tee → episode log │
   hermes)       │  idle-time summarizer       │
                 └──────────┬──────────────────┘
                            └── engram.db (SQLite: FTS5 + vectors + queue)

Install

pip install engram-proxy    # or: uvx --from engram-proxy engram up
ollama pull qwen3:1.7b qwen3-embedding:0.6b

Quick start

engram up

# in another terminal - stock ollama, now with memory:
export OLLAMA_HOST=127.0.0.1:11435
ollama run qwen3:1.7b "I'm Sam. My cat is Miso and I'm badly allergic to peanuts."
# ... later, in a NEW session:
ollama run qwen3:1.7b "Ordering Thai tonight - anything I should avoid?"

Requires Ollama with qwen3:1.7b (summarizer) and qwen3-embedding:0.6b (retrieval) - ollama pull qwen3:1.7b qwen3-embedding:0.6b, ~2 GB total. Field-tested defaults: sub-1B summarizers garble facts, so qwen3:1.7b is the default; without it, summaries fall back to extractive, which also preserves facts. Set ENGRAM_SUMMARIZER_MODEL / ENGRAM_EMBED_MODEL to override (nomic-embed-text is ~3x faster to embed but measurably worse at admission).

CLI

engram up               run the proxy (default :11435 -> :11434)
engram list             recent traces (title + gist + access stats)
engram recall "query"   dry-run recall with per-candidate scores
engram why              explain the last injection, score by score
engram stats            store counts, queue depth, degraded recalls
engram bench            measure embed + recall latency on your machine
engram lme              LongMemEval-S subset run (dataset auto-detected in .lme/)

Numbers and methodology: BENCHMARKS.md. Headline: LongMemEval-S, all 500 questions: 98.1% evidence retrieval into a ~2300-token block against 115k-token haystacks; 66.4% judged answers with a frontier answering model, above published full-context frontier results at roughly 2% of the tokens. Losing categories and all 9 retrieval misses published.

Why answers trail retrieval, measured and ranked in BENCHMARKS.md: the benchmark ingests with extractive summaries whose truncation loses details at write time (21 of 37 analyzed misses; doubling the block budget recovered nothing, so it is not a selection problem), the answering model's own reading ability (same blocks: 62.8% frontier vs 33.8% for a 1.7B), the deliberate user-fact-primacy trade (assistant-side knowledge forms weakly because that grammar is what memory poisoning looks like), and consolidation never running inside a benchmark that never idles. Production's LLM summarizer distills instead of truncating, so the published number is a floor for the real write path.

Design in one paragraph

Every exchange becomes an episode (verbatim, SHA-deduped). A write-behind worker - running only when the GPU is idle - asks qwen3:1.7b for two plain lines (TITLE: / GIST:; never JSON, with a deterministic extractive fallback) and embeds the gist (qwen3-embedding, Matryoshka-truncated to 256d). Recall is hybrid BM25 + dense with admission on raw thresholds (unrelated turns inject nothing) - exact search below 50k memories, a pure-numpy IVF index past it (~86ms p95 at 250k traces, still embed-bound) - ranked by relevance + ACT-R activation B = ln(Σ w·t^-0.5) - frequent-and-recent memories surface first, unused ones sink, and injection itself reinforces at only 0.15 weight (capped per session) so the rich-get-richer loop stays closed. On big-budget tiers each rendered gist quotes cue-relevant verbatim sentences from its source episode (the gist indexes, the record testifies), user words only, secrets never travel. Idle-time consolidation maintains a user profile and topic summaries; silent memories resurrect on strong cues. Injection is budgeted for small models: ≤2 gists + 2 titles, ≤350 tokens, placed first in the system message. Failures fail open: a slow or broken pipeline degrades to a plain proxy.

Full architecture spec: see the published design document.

For coding agents

The repo ships an agent-consumable skill at skills/engram-integration/SKILL.md (standard SKILL.md format: Claude Code, OpenClaw, and Hermes all read it). Point your agent at it, or just say "integrate engram into my setup", and it walks the full recipe: preflight, install, per-client wiring, verification, and the gotchas that cost us real debugging time.

Cloud models

Engram can give a cloud model the same memory, with background work staying local and free:

# route Anthropic-protocol traffic (/v1/messages) to a cloud endpoint,
# or OpenAI-protocol traffic (/v1/chat/completions) to any OpenAI-compatible
# provider; whichever you skip keeps hitting local Ollama
ENGRAM_ANTHROPIC_UPSTREAM=https://api.minimax.io engram up
ENGRAM_OPENAI_UPSTREAM=https://openrouter.ai/api engram up

# point your client's base_url at Engram:
#   Anthropic protocol (e.g. Hermes + MiniMax): MINIMAX_BASE_URL=http://127.0.0.1:11435/anthropic
#   OpenAI protocol (OpenRouter, DeepSeek, ...): base_url=http://127.0.0.1:11435/v1

Auth headers pass through untouched; embeddings and summarization always run on local Ollama (ENGRAM_SERVICES, default http://127.0.0.1:11434), so the only added cloud cost is the injected block itself (≤350 tokens, ~1% of a typical agent prompt). Big-prompt injection rides the newest message, so provider prompt caches - and their cache-read discounts - survive.

Endpoints

  • POST /api/chat - Ollama-native NDJSON, memory-enabled
  • POST /v1/chat/completions - OpenAI-compatible SSE, memory-enabled (local or cloud upstream)
  • POST [/prefix]/v1/messages - Anthropic Messages (local or cloud upstream), memory-enabled
  • everything else (/api/generate, /api/tags, /api/show, /v1/models, embeddings) - byte passthrough
  • GET /engram/stats, GET /engram/why - local introspection
  • header X-Engram: off bypasses memory per-request; X-Engram-Session pins session identity

Metadata

Release files for engram-proxy 0.7.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for engram-proxy 0.7.0
File Size Uploaded
engram_proxy-0.7.0.tar.gz 90.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for engram-proxy 0.7.0
File Interpreter ABI Platform
engram_proxy-0.7.0-py3-none-any.whl Python 3 none any Details

Total release size: 173.8 kB

Release files / engram_proxy-0.7.0.tar.gz

Download URL engram_proxy-0.7.0.tar.gz
Size 90.0 kB
Tags Source
SHA-256 checksum
How to use checksums
afa7224776a570cd11193164d74a3d28587482895d2aea41a00391ccc939abb6
BLAKE2b-256 checksum
How to use checksums
62a6d831861eb4c76fc5d8d598f1efb3cb4cd0f581a850e864054468fcfe5215
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.7

Release files / engram_proxy-0.7.0-py3-none-any.whl

Download URL engram_proxy-0.7.0-py3-none-any.whl
Size 83.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
10c0e488ba3ae0c3313446b71294f9bb1e916c81ee3f57aac9e701b2d09925d4
BLAKE2b-256 checksum
How to use checksums
79223b8fb6c67daf065727854950b59bccdc02a361cf9318ab4dc7657e3d0771
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.7

Release history Release notifications | RSS feed

This release

0.7.0 This release

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page