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
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 → consolidateagent › 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 you
│
▼
┌─────┐
│ • │ private
└─────┘Private by default
A memory you write belongs to you alone until you say otherwise. There is no shared bucket that things fall into by accident, and no setting that quietly widens an old note.
Read more ┌───┐ ┌───┐
│ A │ │ B │
└─┬─┘ └─┬─┘
└───┬───┘
┌─┴─┐
│A∩B│Shared on purpose
Sharing names the organizations that may read a note. Name two and only people who belong to both can see it, which is how a memory about one collaboration stays inside it.
Read more ┌───────────┐
│ your host │
├───────────┤
│ postgres │
│ vllm │
└───────────┘Yours to host
One PostgreSQL database holds every byte, the model lanes run on your own GPUs, and nothing leaves the machine. Turn it off and the memory is still a file you own.
Read moreHow 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.
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.
┌───────────────┐
│ { 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 namesCorrections 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 worksWhat 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.
| capability | Zep and Graphiti | Mem0 | GraphRAG | aizk |
|---|---|---|---|---|
| temporal facts | temporal graph | memory updates | no | valid and recorded ranges |
| consolidation | model driven | add, update, delete | no | rules first, model on ambiguity |
| speaker semantics | limited | user namespace | no | author snapshot and epistemic kind |
| authorization | application layer | application layer | no | forced PostgreSQL row security |
| overlapping scopes | no | no | no | arbitrary nonempty scope sets |
| retrieval | graph and text | vector | community summaries | typed hybrid plus graph lanes |
| local operation | service oriented | optional | batch oriented | PostgreSQL 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 comparisonStanding 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.
- Zep and Graphititemporal entity and fact graph
- Mem0add, update and no-op consolidation
- HippoRAG 2associative multi-hop recall
- GraphRAGcommunity summaries
- RAPTORrecursive summary tree
- A-MEMreflective observations
- Collaborative Memoryprivate and shared memory split
- Memoraforgetting-aware scoring
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 aizkThen 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 setupgit 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 -dTwo GPUs, one PostgreSQL, no vendor. The hardware page sizes it before you start.
Full setup