Skip to main content

Memory infrastructure for personal AI — bi-temporal facts, honest contradictions, autonomous maintenance, real forgetting. MCP-native, multi-tenant, multilingual.

Project description

gnokee

Memory infrastructure for personal AI — bi-temporal facts, honest contradictions, autonomous maintenance, real forgetting. MCP-native, multi-tenant, multilingual.

PyPI npm License: Apache-2.0

Status: v0.7 — v0.1 core surface (ingest + recall + MCP) plus v0.2 typed clinical-data reads (gnokee_lab_query / gnokee_med_query), v0.3 lite-mode ingest for high-cadence sources, v0.4 encrypted-body branch (content xor encrypted_body; gnokee never holds keys), v0.5 read-side hardening (declarative gnokee_query envelope, per-claim citations, recency-proxy confidence, Obsidian adapter, refusal posture), v0.6 ingest hardening (storage-first ingest + adaptive TPM-aware retry, ADR-0023; recall@5 17.6% → 100% on LongMemEval-S), and v0.7 durability + lineage: ingest crash-recovery journal + gnokee.resume_ingest (ADR-0024), gnokee_history_of supersession-DAG MCP tool, and hard-removal of the v0.6-deprecated GNOKEE_INGEST_STRICT env var. See docs/specs/v0.1.md for the core surface and docs/README.md for the full doc map.

┌─────────────────────────────────────────────────────────┐
│  Adapters (thin shims; consumer-owned)                  │
│  files / md-vault / api-push / rss / email / pulse-sdk  │
└────────────────┬────────────────────────────────────────┘
                  ↓ ingest_episode (full or lite)
┌─────────────────────────────────────────────────────────┐
│  gnokee core                                            │
│    • bi-temporal store, supersession, contradiction     │
│    • retrieval: pgvector cosine + Cypher narrow         │
│    • forgetting: tombstones + crypto erasure            │
│    • MCP server (5 tools, token-efficient)              │
└────────────────┬────────────────────────────────────────┘
                  ↓
┌─────────────────────────────────────────────────────────┐
│  Backends (pluggable)                                   │
│  Postgres + pgvector  •  Neo4j Community (Graphiti)     │
│  bge-m3 via TEI / Ollama  •  consumer-supplied LLM      │
└─────────────────────────────────────────────────────────┘

Quickstart

Requirements: Docker, Python 3.10+, an OpenAI-compatible LLM API key (gpt-4o-mini per Q4).

# 1. Bring up Postgres + Neo4j + TEI
make up

# 2. Install (editable) and run the demo
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[mcp,dev]"

# 3. Configure env
cp .env.example .env
# edit .env to set GNOKEE_OPENAI_API_KEY (or GNOKEE_LLM_API_KEY)

# 4. Apply migrations and run the demo
make migrate
make demo

The demo ingests five episodes about a person, runs a recall, and prints any contradictions. Output is plain stdout — gnokee is a library + MCP server, not a UI.

MCP server

python -m gnokee.mcp        # stdio (default; for Claude Desktop / Code / Cursor)
GNOKEE_MCP_HTTP=1 python -m gnokee.mcp   # streamable-http (production-ready, v0.12+)

Production deploys MUST set bearer-JWT auth and terminate TLS at a reverse proxy (gnokee never holds keys). The startup gate (_assert_http_auth_safety) refuses to launch when GNOKEE_MCP_HTTP=1 is set without GNOKEE_MCP_AUTH_KIND — a clear ValueError at boot beats an accidentally-exposed production server. Minimal production env:

GNOKEE_MCP_HTTP=1
GNOKEE_MCP_HOST=127.0.0.1                         # default; loopback-only behind reverse proxy
GNOKEE_MCP_PORT=8000                              # default
GNOKEE_MCP_AUTH_KIND=bearer-jwt
GNOKEE_MCP_JWT_PUBKEY_PATH=/etc/gnokee/idp-pubkey.pem
GNOKEE_MCP_JWT_ALG=RS256                          # or ES256/ES384/ES512/PS256/PS384/PS512
GNOKEE_MCP_JWT_AUDIENCE=gnokee-mcp                # optional
GNOKEE_MCP_JWT_ISSUER=https://idp.example.com     # optional
GNOKEE_MCP_AUTH_ISSUER_URL=https://idp.example.com
GNOKEE_MCP_AUTH_RESOURCE_URL=https://gnokee.example.com

Algorithm choice: production MUST use an asymmetric algorithm (RS*/ES*/PS*). HMAC algorithms (HS*) are construction-refused unless the caller passes _allow_hmac=True to BearerJWTBackend — intentional, because HMAC requires gnokee to hold the same secret the issuer signs with, contradicting "gnokee never holds keys".

Full deployment guide (reverse-proxy + systemd + compose + healthz/readyz): docs/deployment-mcp-http.md. Auth contract: ADR-0030. Threat model: docs/security/multi-tenant.md.

Drop-in client config snippets for Claude Desktop, Claude Code, and Cursor live under examples/03_mcp_clients/.

Tools surfaced:

Tool Purpose
gnokee_ingest_episode Store a fact / event / observation in bi-temporal memory.
gnokee_recall Natural-language fact retrieval with provenance handles.
gnokee_fact_provenance Fetch the original episode body behind a fact_uuid.
gnokee_lab_query (v0.2) Typed clinical-lab reads: latest | history | min | max | avg | count over lab_record.
gnokee_med_query (v0.2) Typed medication-history reads: active | history | allergies | switches over med_record.
gnokee_wiki_export (v0.5) Markdown wiki view of a tenant's memory (index.md + log.md + entities/<slug>.md). ADR-0015.

Core schemas in docs/specs/v0.1.md §6; v0.2 typed reads documented in ADR-0009 + ADR-0010; v0.5 wiki export in ADR-0015.

llms.txt manifest

gnokee ships an llms.txt manifest listing the MCP tool surface, identity model, and red lines so agents can discover gnokee without reading the full README. Two static files ride along with every release:

File Purpose
static/.well-known/llms.txt Full structured manifest (tools, ADR index, identity, red lines).
static/.well-known/gnokee.txt Pointer file (manifest: ./llms.txt) for agents probing <project>.txt.

Both files ship inside the PyPI sdist + wheel at <site-packages>/gnokee/.well-known/{llms.txt,gnokee.txt} (see pyproject.toml [tool.hatch.build.targets.wheel.force-include]). gnokee itself does NOT publish a webserver; self-hosters wire their own static-file route at /.well-known/llms.txt if they want the manifest reachable over HTTP. Docker users find the same files in the in-repo static/.well-known/ path of the gnokee install.

Environment variables

Var Purpose
GNOKEE_PG_DSN postgresql://…
GNOKEE_NEO4J_URI / GNOKEE_NEO4J_USER / GNOKEE_NEO4J_PASSWORD Bolt + auth
GNOKEE_TEI_URL TEI base URL (e.g. http://localhost:8080)
GNOKEE_EMBED_MODEL default bge-m3 (1024-dim, locked)
GNOKEE_OPENAI_BASE_URL / GNOKEE_OPENAI_API_KEY consumer-supplied LLM (alias: GNOKEE_LLM_*)
GNOKEE_LLM_MODEL default gpt-4o-mini
GNOKEE_TENANT_DEFAULT demo + tests only; production paths require tenant_id explicitly
GNOKEE_MCP_HTTP 0 for stdio, 1 for streamable-http (production-ready v0.12+)
GNOKEE_MCP_HOST bind address; default 127.0.0.1 (loopback). Set 0.0.0.0 only with auth enabled.
GNOKEE_MCP_PORT TCP port; default 8000
GNOKEE_MCP_HTTP_ALLOW_UNAUTHENTICATED escape hatch — set to 1/true/yes to allow HTTP without auth behind a trusted reverse proxy. Emits a WARNING log line at boot.
GNOKEE_MCP_AUTH_KIND bearer-jwt to enable auth; unset/empty for library/stdio mode
GNOKEE_MCP_JWT_PUBKEY_PATH PEM file path; required when auth enabled
GNOKEE_MCP_JWT_ALG default RS256; one of RS*/ES*/PS*. HMAC (HS*) refused unless _allow_hmac=True is set on BearerJWTBackend (test-only).
GNOKEE_MCP_JWT_AUDIENCE / GNOKEE_MCP_JWT_ISSUER optional JWT aud / iss checks
GNOKEE_MCP_JWT_TENANT_CLAIM default tenants; JWT claim listing allowed tenant_ids
GNOKEE_MCP_AUTH_ISSUER_URL / GNOKEE_MCP_AUTH_RESOURCE_URL OAuth Protected-Resource metadata (advertise only; gnokee never issues tokens)
GNOKEE_LOG_LEVEL default info

Tests

make test-unit             # no compose required
make up && make test-integration   # needs LLM key + compose stack

What gnokee is

A memory layer that treats facts the way infrastructure treats state: declared, versioned, reconciled, garbage-collected. It ingests episodes from any source (files, APIs, event streams), stores them with bi-temporal validity, detects contradictions at write and surfaces them at read, supersedes facts explicitly rather than overwriting, forgets verifiably when asked, and runs maintenance autonomously.

MCP-native. Multi-tenant from day one. Multilingual by default (bge-m3). Built on top of Graphiti's bi-temporal knowledge graph primitive.

Two ingest modes:

  • Full (extract=True, default): full Graphiti narrative extraction + contradiction detection. p50 ≈ 4.5 s, p95 ≈ 7.1 s. For one-off / low-cadence sources.
  • Lite (extract=False, v0.3+): skip the LLM-bound stages; Postgres + TEI only. p50 ≈ 200 ms. For telemetry / wearable summaries / log scrapes. Pair with gnokee.maintenance.run_deferred_extraction to backfill narrative facts on a schedule. See docs/integration_patterns.md.

Encrypted-body branch (v0.4+): pass encrypted_body=... instead of content=...; gnokee stores ciphertext, never decrypts, never sees the DEK. Recall surfaces ciphertext verbatim — consumer decrypts with their own KMS via key_id. See docs/architecture.md §Encrypted-body lifecycle.

What gnokee is not

  • Not a chat UI (use any MCP client)
  • Not an LLM host (use Ollama, LiteLLM, direct APIs)
  • Not a sync engine, workflow engine, agent framework, document parser, vault editor, auth provider, federation layer

See docs/architecture.md for the full refusal list.

Status

  • Namespace claimed (PyPI, npm, GitHub org omurlabs, domains gnokee.com/.dev/.io)
  • Q1 Graphiti spike — ADOPT as storage primitive (ADR-0001)
  • Q2 bge-m3 cross-lingual — ADOPT (100% top-1 via direct cosine); retrieval reassigned to gnokee (ADR-0004)
  • Q3 MCP token-efficiency — ADOPT gnokee response shape (60% token reduction at 91.7% top-3 recall vs Graphiti-raw 50%)
  • Q4 contradiction-classifier smoke test — ADOPT gpt-4o-mini (8/10 = 80% accuracy on labeled pairs)
  • Q5 forgetting hard-delete propagation — ADOPT (2/2 probes; Neo4j cascade + retrieval-surface clean)
  • Q5 storage adapter audit (FalkorDB) — Neo4j for v0.1; FalkorDB swap deferred to v0.2 (Graphiti-internal API differs; gnokee's Cypher is portable)
  • v0.1 spec finalized (docs/specs/v0.1.md)
  • v0.1 implementation — ingest + recall + MCP + contradictions, integration tests on real compose stack
  • Q7 clinical-labs spike — OFF-RAMP at 13.3 %; typed lab_record table per ADR-0009
  • Q8 med-supersession spike — ADOPT_WITH_GAPS at 53.3 %; typed med_record table per ADR-0010
  • Q9 wearable-throughput off-ramp (ADR-0011)
  • v0.2 typed clinical reads landed (gnokee_lab_query + gnokee_med_query); Q7 lifted to 66.7 % ADOPT_WITH_GAPS, Q8 lifted to 93.3 % ADOPT
  • Eval suite formalised across cross-tool (vs Mem0 / Graphiti-alone / Zep-OSS / basic-memory) — Stage A 2026-05-09 (10 Q × 10 sessions, 3 SUTs, double-run judge agreed); Stage C-pilot 2026-05-10 (30 Q × 20-session, 3 SUTs, double-run judge agreed) confirms magnitude — all three SUTs 0/30 strict on LongMemEval-S; gnokee REJECT for v0.2.x retrieval surface (ADR-0012 Accepted). Q10.1: Zep-OSS + basic-memory adapters wired + smoked (5 wired SUTs). Bottleneck moved from retrieval to synth-prompt abstention bias (#62); full-pilot Stage C (100 Q × ~47-session × Track 1 + Track 2) tracked under #63
  • First tagged release

Roadmap

Phase Milestone
Spike Q1 — Graphiti's bi-temporal model fits Omur + personal corpora
v0.1 Single-tenant, single-binary; ingest + retrieval + MCP; basic forgetting; Apache 2.0
v0.2 Typed clinical reads (labs + meds) per ADR-0009/0010; structured Postgres siblings to graphiti's narrative
v0.3 Omur consumes gnokee; multi-tenant validation; encrypted-body branch
v1.0 API stability commitment; published evals vs Mem0 / Graphiti-alone / basic-memory

Documentation

docs/README.md is the entry map — audience-grouped index of every doc in this repo. Quick links:

Project name

gnokee = gno (Greek γνῶσις, "knowledge") + kee (English keep, custodian). Pun: "no key" — gnokee never holds keys, never decrypts (see docs/architecture.md § Privacy). Originally drafted as Veda; rebranded after namespace collision.

License

Apache-2.0. See LICENSE.

Contributing

Open with guardrails. Bug fixes, docs, tests, eval improvements, and adapters via PR; new MCP tools, breaking changes, and new ADRs require maintainer pre-approval. The AGENTS.md "do not" list (no UI, no LLM hosting, no auto-resolve, no key holding, no supersession-by-deletion) is normative for every PR.

See:

Source of truth

Design documents live in Notion (private) until first commit; from this point forward the repo is canonical. See AGENTS.md for the convention.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gnokee-0.12.2.tar.gz (730.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gnokee-0.12.2-py3-none-any.whl (277.7 kB view details)

Uploaded Python 3

File details

Details for the file gnokee-0.12.2.tar.gz.

File metadata

  • Download URL: gnokee-0.12.2.tar.gz
  • Upload date:
  • Size: 730.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.2.0 CPython/3.14.5

File hashes

Hashes for gnokee-0.12.2.tar.gz
Algorithm Hash digest
SHA256 88b950a03092c84a54420064b2de1b8520c2137f1defa42e7c39fbf3bda33fa5
MD5 3b2fe8bfb398eedf808153f2592f332a
BLAKE2b-256 67012f02492526abc4403a1c06c2b87971cb9dd75fd2615523370bf5b51be4cd

See more details on using hashes here.

File details

Details for the file gnokee-0.12.2-py3-none-any.whl.

File metadata

  • Download URL: gnokee-0.12.2-py3-none-any.whl
  • Upload date:
  • Size: 277.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.2.0 CPython/3.14.5

File hashes

Hashes for gnokee-0.12.2-py3-none-any.whl
Algorithm Hash digest
SHA256 6a55feb014514f240ac9f67223d7a04585406b14a421dbeec8538f0edf6a6607
MD5 4ce4474b172598fe76ce4b6d815226b4
BLAKE2b-256 152b28126726f3dce61853286a71fff791dcf1fe27beaf9b4fa63c5e9a6c8efb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page