self-hosted · MCP native

One memory for you, your team and your agents

aizk keeps what you and your agents learn, returns it as sourced evidence when it is asked for, and never lets a memory cross a boundary you did not choose. It runs on your own hardware, on one PostgreSQL database, behind row level security that the database itself enforces.

recall p50
~0.7 s
tools
4
databases
1
licence
MIT
aizk · one round trip
agent › aizk.remember(
          text="We moved extraction to GLiNER2 because the LLM
                lane cost 4.1s per chunk and GLiNER2 costs 0.3s
                at the same grounding rate. #project: aizk",
          scopes=["Book Club"])
✓ stored  019f7a2c…  →  scope { Book Club }
  queued  chunk → gate → extract → ground → consolidate
agent › aizk.recall(query="why did we drop the LLM extractor?")
## Evidence
- Source excerpt · scope Book Club
    We moved extraction to GLiNER2 because the LLM lane cost
    4.1s per chunk and GLiNER2 costs 0.3s at the same
    grounding rate.
- Derived memory · scope Book Club
    [aizk, world] (uses) aizk uses GLiNER2 for extraction.
  1.4s · 6 of 2048 tokens · 3 lanes hit

How it works

Writing and reading are two paths across one database. Tap any box to jump to the part of the docs that explains it.

How aizk fits together, from an agent through the store and back to evidencerememberrecallprojectscopesyour agentLogto identitywrite pathread pathgate → extract → groundone PostgreSQLautonomous passessourced evidence

Sharing is a set, not a switch

Every row in aizk carries the set of organizations it belongs to. Reading requires standing in all of them, so naming two organizations produces a cell that only people in both can reach. Nothing here is an application-level check that a bug could skip. PostgreSQL evaluates the rule itself, on every table, with row level security forced on.

  • Writing names one destination. An agent picks the scope deliberately and the default is private.
  • Reading spans everything visible. One question searches the union of what you can see, and the answer says where each piece came from.
  • Sharing copies, it does not move. The private original stays yours and unchanged.
How scopes work
                       ┌───────────────┐
                       │  { A , B }    │   both organizations
                       │  intersection │   the narrowest shared cell
                       └───────┬───────┘
                   ┌───────────┴───────────┐
             ┌─────┴─────┐           ┌─────┴─────┐
             │   { A }   │           │   { B }   │
             │  one team │           │  one team │
             └─────┬─────┘           └─────┬─────┘
                   └───────────┬───────────┘
                        ┌──────┴──────┐
                        │  { you }    │   private
                        │  one person │   the default
                        └─────────────┘

    a reader sees a row only when they stand in every scope it names
A fact valid from March, recorded in June, corrected in July without deleting the first version MarJunJulnowrecordedvalid"the extractor is the LLM lane""the extractor is GLiNER2"learned Juncorrected Jul

Corrections keep the past

aizk records two clocks for every claim. One is the time the statement was true in the world, the other is the time aizk was told. Correcting something closes the old range and opens a new one, so yesterday's answer can still be reconstructed and nothing is silently overwritten.

That matters when memory drives decisions. You can ask what the team believed in June and get June's answer, not today's, and you can see exactly when the belief changed.

How time works

What you get

Four tools, nothing else

status, recall, remember and share. Any MCP client gets the whole product without an adapter.

Sources stay authoritative

The text you wrote is kept exactly. Everything the engine derives from it is a rebuildable projection that can be thrown away and rebuilt.

Every lane runs

No query router decides what to search. Dense, lexical, graph, community, summary and working memory all run, then one reranker sorts them by merit.

Grounded extraction

A fact is only written when the model can quote the span of text it came from. Ungrounded output is dropped rather than stored.

Files stay immutable

An original is scanned, hashed and stored behind an opaque key. Conversion produces derivatives beside it and never replaces it.

Speaker aware

Memory separates what is objectively true from what a particular person observed, prefers or experienced, so a team memory does not flatten into one voice.

Bounded answers

Recall returns the longest prefix of ranked evidence that fits a token budget you control, so it never floods a context window.

Autonomous upkeep

Communities, summaries, profiles and decay run on a schedule under the same scope rules. There is no review queue and no human in the loop.

One database

PostgreSQL does the filtering, ranking, temporal logic and authorization. There is no second store to keep in sync and nothing to reconcile.

Forced row level security

The application role cannot bypass policy. A missing WHERE clause returns nothing rather than everything.

Measured, not asserted

A retrieval bench, an extraction bench and an external benchmark adapter decide what ships. Claims without a number stay off these pages.

Runs on your metal

Compose brings up PostgreSQL, the object store, the scanner, the converter and the model lanes. Nothing calls out to a vendor.

How it differs

This table compares mechanisms, not scores. aizk has no head-to-head benchmark result against these systems yet, because an honest one needs the same imported histories, the same answer model, the same judge and the same hardware budget across all of them. Until that run exists, what follows is a description of design choices rather than a claim of winning.

capabilityZep and GraphitiMem0GraphRAGaizk
temporal factstemporal graphmemory updatesnovalid and recorded ranges
consolidationmodel drivenadd, update, deletenorules first, model on ambiguity
speaker semanticslimiteduser namespacenoauthor snapshot and epistemic kind
authorizationapplication layerapplication layernoforced PostgreSQL row security
overlapping scopesnononoarbitrary nonempty scope sets
retrievalgraph and textvectorcommunity summariestyped hybrid plus graph lanes
local operationservice orientedoptionalbatch orientedPostgreSQL and local models

More graph machinery is not automatically better. The ACL 2026 studyDoes Memory Need Graphsfinds that raw session evidence with independent summaries and facts is a strong baseline, and that graph summaries can improve retrieval metrics while hurting answers when they crowd raw evidence out of the prompt. aizk keeps raw source chunks primary and makes every graph lane earn its place in ablation.

The full comparison

Standing on published work

aizk did not invent memory research. It adopts mechanisms that have been measured elsewhere and records which is which, so you can tell a borrowed design from an original one. A citation here means the idea shaped the code, not that the project endorses aizk.

The full lineage map

Built on

The second design principle is to minimize our own work. Identity, conversion, scanning, object storage, vector indexing, job queuing and model serving are all somebody else's maintained project, and aizk owns only the parts that are actually about memory.

Connect in one command

Every client points at the same URL and discovers aizk as an OAuth protected resource. There is no API key to paste and no per-client integration to write.

claude mcp add --scope user --transport http --callback-port 8912 \
  aizk https://aizk.phvv.me/mcp
claude mcp login aizk

Then ask it to complete its own setup with "Ask AIZK how to do AIZK onboarding and follow it."

Full setup
# .codex/config.toml
mcp_oauth_credentials_store = "file"
mcp_oauth_callback_port = 8912

[mcp_servers.aizk]
url = "https://aizk.phvv.me/mcp"
auth = "oauth"
oauth_resource = "https://aizk.phvv.me/mcp"
scopes = ["control", "offline_access", "openid"]

Then run codex mcp login aizk. The fixed callback port keeps remote development predictable.

Full setup
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "aizk": { "type": "remote", "url": "https://aizk.phvv.me/mcp", "enabled": true }
  }
}

Then run opencode mcp auth aizk, and opencode mcp debug aizk if it will not connect.

Full setup
git clone https://github.com/phvv-me/aizk && cd aizk
cp src/deploy/.env.example .env   # fill in the secrets it names
docker compose -f src/deploy/docker-compose.yml --profile public up -d

Two GPUs, one PostgreSQL, no vendor. The hardware page sizes it before you start.

Full setup