System map
This is the map of the whole engine, and the first page to read before you open any other developer page. It assumes you know what a scope is and that you can read SQL. Everything below points at a real module or a real container, so you can check any claim against the tree yourself.
Three roles with profile-specific services
Section titled “Three roles with profile-specific services”All AIZK code ships as one package with three roles. Compose runs each as its own container. The AWS profile serves the browser API and MCP surface from one public Lambda and runs the worker in a second private Lambda.
| Process | Command | What it owns |
|---|---|---|
| MCP server | aizk admin server mcp |
the agent-facing tool surface |
| Browser API | aizk admin server api |
the JSON API the web app calls |
| Worker | aizk admin server worker |
the queue drain and the scheduled passes |
Each one calls Runtime.assemble(settings) in src/aizk/runtime.py exactly once, which builds
the database handle, the byte store, the artifact services, the Logto client, and the four model
clients for embedding, reranking, gating, and generation. Nothing else in the codebase constructs
those. Design principles explains why that rule exists and
where it is bent.
The surrounding services depend on the selected profile. The self-hosted profile uses PostgreSQL with VectorChord, SeaweedFS, ClamAV, Docling and local model services. The AWS profile uses CockroachDB Cloud, C-SPANN, S3 and hosted model endpoints. Logto provides identity in both. Database profiles owns the comparison, while Deployment topology owns the Compose service list.
The write path
Section titled “The write path”A keep call lands on Memory.keep in src/aizk/memory.py, the one service both the
MCP server and the browser API share. Plain text and a file take different routes from there.
caller │ keep ▼ Memory.keep ├── text ──────────▶ extract.ingest ──┐ │ │ └── uri or file ──▶ ArtifactIntake │ │ scan, then │ │ convert │ ▼ │ Markdown ───────────┤ ▼ document and chunks │ enqueue ▼ durable queue │ worker ▼ gate ─▶ extract ─▶ ground ─▶ consolidate │ ▼ entities and factsText goes straight to extract.ingest.ingest_text, which writes the document and its chunks and
embeds them. A URI or an upload goes to the artifact intake first, which scans the bytes before
storing them and converts them to Markdown only after the scan passes, then feeds the Markdown
back into the same ingest path. Intake and
Artifacts cover both.
The transaction that writes the document ends there. enqueue_document puts a job in the active
durable queue. PgQueuer owns that work on PostgreSQL, while AIZK queue tables and the portable
worker own it on CockroachDB. A caller never waits for graph extraction.
Extraction and the gate covers the job, and
The job system covers both queue implementations.
The read path
Section titled “The read path”A find call is synchronous and touches no queue. Memory.find calls
retrieval.find, which runs the lanes in src/aizk/retrieval/lanes/, fuses them, reranks the
survivors with a cross-encoder, and packs the highest-merit prefix that fits the token budget.
The result is rendered from src/aizk/retrieval/templates/find.md.j2 into one prompt-ready
Markdown string.
The retrieval plan decides which lanes run. The full PostgreSQL plan can run every lane and use a cross-encoder to order the fused candidates. The bounded AIZK plan disables measured high-cost lanes and can skip reranking. How find runs owns the shared path, and Retrieval tuning owns the switches.
The identity boundary
Section titled “The identity boundary”aizk stores no users, no organizations, and no memberships. src/aizk/auth.py verifies the
bearer token against Logto, and User.authorized in src/aizk/store/identity/user.py derives a
stable UUID5 identity and the caller’s organization standing from the verified claims alone.
bearer token ──▶ Auth.verify_token ──▶ claims │ ▼ User.authorized(...) │ ┌────────────────────────────┴───────────────┐ ▼ ▼ app.orgs (readable) app.writable_orgs └──────────────┬─────────────────────────────┘ ▼ every protected row policy reads theseUser is an rls.Context subclass with the prefix app. The PostgreSQL adapter binds those
settings directly. The CockroachDB adapter carries the same authority through a transaction-local
connection setting that its policies parse. The application role cannot bypass row security, so
code that forgets to filter returns nothing instead of returning everything. The Logto boundary and
Row level security go deeper.
Background work has no bearer token, so it uses User.system() or User.private(user_id)
instead, which is a separate and deliberately narrow door.
Background work explains what each one may see.
What the transports may not do
Section titled “What the transports may not do”The MCP server and the browser API are thin. Neither builds a SQL statement and neither opens a
session, which is enforced by src/aizk/mcp/ruff.toml and src/aizk/api/ruff.toml banning
sqlmodel.select, the session classes, and Database inside those two packages. Both reach the
store through model classmethods and User.exec.
Layers and import contracts has the wider version of that rule.
- Layers and import contracts shows what may import what.
- Repository tour says which directory to open for a change.
- The data model explains the content and claim split underneath everything here.
- Deployment topology lists every container and how they connect.