What this local build actually runs on: process, files on disk, HTTP contracts, and what is deliberately not a database yet. Frozen for the portal demo on 2026-09-21. Neighbouring platform teams have not signed these contracts.
1. Runtime
| Piece | v0 choice |
|---|---|
| Language | Python ≥ 3.12 |
| HTTP | FastAPI + Uvicorn, bind 127.0.0.1:8008 |
| Schema / validation | Pydantic v2 (akb.schema) |
| UI | Static HTML + fetch (src/akb/static/), no JS framework |
| Package | uv run akb portal --workdir data/portal --port 8008 |
| GPU / LLM | None. Skill-opt records teacher/student names and rewrites locally. |
2. Storage — there is no database server
Two stores, both local files under the portal workdir (default data/portal/). The packed demo traces ship inside the package so the portal runs without the intern-project tree.
2.1 Raw layer (episodes) — append-only log
Class: akb.store.raw.RawStore. This is the closest thing to a database table for “what the agent actually did.”
| File | Role |
|---|---|
raw/episodes.jsonl | One JSON Episode per line. Append only. Never updated, never deleted. |
raw/manifest.jsonl | episode_id + SHA-256 of the canonical JSON + received_at. Duplicate ids are rejected. |
PII scrub runs before a row lands. The raw layer never sees the un-scrubbed text. Same episode_id twice is an error, not an overwrite.
2.2 Cell store (AKB knowledge) — versioned documents
Class: akb.store.cells.CellStore. A cell is replaced as a new version; the previous JSON is archived. Nothing is mutated in place.
| File | Role |
|---|---|
cells/{cell_id}.json | Current cell document (dual representation: exemplars + failure modes). |
cells/versions/{cell_id}.vN.json | Previous versions. Rollback copies an archive forward as vN+1. |
cells/index.json | One-line index per cell for the read API. |
cell_id uses | in the schema (reader|llm_only|eval) and __ on disk so it is a legal filename.
2.3 Portal side files
| File | Role |
|---|---|
src/akb/assets/collected.json | 92 packed episodes shipped with the wheel. This is the portal’s source of traces. |
build-report.json | Last Generate-knowledge metrics (counts, token compression). |
jobs/{job_id}.json | Skill-opt job record (config, steps, skill before/after). |
skills/{mode}.md | Rewritten SKILL.md for that failure. |
2.4 What a later “real database” would replace
Today Later (same contracts) ───────────────── ──────────────────────────────────────── episodes.jsonl → Postgres/object-store of Episode rows manifest.jsonl → unique index on episode_id + content hash cells/*.json → document store or Postgres JSONB + blob for exemplars jobs/*.json → job table No cache → optional Redis for the read API, not for writes
The ingest contract stays “streaming or batched JSONL of Episode.” The read contract stays the cell API below. Do not couple producers to a SQL schema.
3. Data model
From the research plan §§2.2 and 4.4. Axes in this repo: 5 personas × 6 intentions × 6 topics = 180 possible cells.
| Object | What it is |
|---|---|
| Episode | One agent session: turns (user / assistant / tool), outcome, timing, optional skill_id. |
| Cell | All episodes attributed to one (persona, intention, topic). Dual representation: k weighted exemplar trajectories + structured insight (failure modes, tool profile, index line). |
| Failure mode | Named root cause + failing sequence + recovery + anti-pattern + support count. |
| Skill job | Teacher / student / optimizer + rewritten markdown. Live jobs keep a per-iteration unified diff. The Cursor token is never written here. |
persona ∈ { reader, coder, terminal, deep_loop, chat_only }
intention ∈ { deep_loop_read, llm_only, multi_cycle_edit,
multi_cycle_other, deep_loop_failures, deep_loop_run }
topic ∈ { skillmesh, agent_studio, routing, eval, distill, prune }
cell_id = "{persona}|{intention}|{topic}"
4. HTTP surface
One FastAPI app. Portal UI at /. Older synthetic process demo at /process. This page at /spec.
Portal (this demo)
| Method | Path | Does |
|---|---|---|
| GET | /v1/portal/traces | Catalog + episode cards from collected.json |
| GET | /v1/portal/traces/{id} | Turns for one episode |
| POST | /v1/portal/build | Scrub → raw JSONL → cells on disk |
| GET | /v1/portal/knowledge | Cells + build report |
| GET | /v1/portal/failure-modes | Named failures, sorted by support |
| GET | /v1/portal/models | Default teacher / student / optimizer names (local catalog) |
| POST | /v1/portal/cursor-key | Test a Cursor token (eval-platform: this run only). Returns models from GET /v1/models. Key is not stored. |
| POST | /v1/portal/skill-opt | With a key: live iterations, each with a SKILL.md diff. Without: local template rewrite. |
Read API (frozen interface 0)
| Method | Path | Who |
|---|---|---|
| GET | /health | any |
| GET | /v1/index | any |
| GET | /v1/cells, /v1/cells/{id} | payload depends on persona |
| GET | /v1/cells/{id}/exemplars | developer (user: 403) |
| GET | /v1/cells/{id}/failure-modes | any |
| POST | /v1/datasets | developer — register a training set from cells |
| GET | /v1/economics | manager — GPU knapsack / shadow price |
Header: X-Persona: manager | developer | user.
5. Auth
Nokia SSO is not wired. The persona header is a stand-in so the three payloads exist before three teams have tokens.
| Persona | Sees |
|---|---|
| user (product owner) | Index lines + named failure modes. No raw trajectories, no provenance (PII lived there). |
| developer | Full cell, exemplars, dataset registration. |
| manager | Spend / GPU / shadow price. Does not need to know what a cell is. |
6. Neighbouring platform contracts
Markdown in the repo specs/. Locally frozen 2026-09-17; not agreed with other teams.
| Id | Name | v0 stub |
|---|---|---|
| 0 | Cell read API | This FastAPI app |
| 1 | Upstream ingest | RawStore.append — JSONL of Episode, PII first, no overwrite |
| 2 | Training platform | POST /v1/datasets returns a dataset id. No real training job. |
| 3 | Inference / economics | GET /v1/economics + knapsack. Not on the live request path. |
| 4 | Evaluation | akb smoke / akb eval JSON report (M1.1–M1.4). No LLM judge. |
7. Not in v0 (on purpose)
- No RDBMS, object store, or message bus.
- No Nokia SSO, GKE, or oncall.
- No teacher/student GPU run. Skill-opt with a Cursor key calls that key’s chat endpoint; without a key it is a local template rewrite.
- No Agent Studio production dump — portal traces are packed from Liang’s collected files.
- Insight retention on synthetic data uses a planted oracle, not a live judge.