Agent Knowledge Base

Software specification · v0

← Back to portal

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.

Short answer on “what database?” There is no Postgres, SQLite, or Redis in v0. The raw trace layer is an append-only JSONL file. AKB knowledge is a versioned directory of JSON documents (one file per cell). Both can be swapped later for a real store without changing the §2.2 episode schema or the read API.

1. Runtime

Piecev0 choice
LanguagePython ≥ 3.12
HTTPFastAPI + Uvicorn, bind 127.0.0.1:8008
Schema / validationPydantic v2 (akb.schema)
UIStatic HTML + fetch (src/akb/static/), no JS framework
Packageuv run akb portal --workdir data/portal --port 8008
GPU / LLMNone. 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.”

FileRole
raw/episodes.jsonlOne JSON Episode per line. Append only. Never updated, never deleted.
raw/manifest.jsonlepisode_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.

FileRole
cells/{cell_id}.jsonCurrent cell document (dual representation: exemplars + failure modes).
cells/versions/{cell_id}.vN.jsonPrevious versions. Rollback copies an archive forward as vN+1.
cells/index.jsonOne-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

FileRole
src/akb/assets/collected.json92 packed episodes shipped with the wheel. This is the portal’s source of traces.
build-report.jsonLast Generate-knowledge metrics (counts, token compression).
jobs/{job_id}.jsonSkill-opt job record (config, steps, skill before/after).
skills/{mode}.mdRewritten 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.

ObjectWhat it is
EpisodeOne agent session: turns (user / assistant / tool), outcome, timing, optional skill_id.
CellAll episodes attributed to one (persona, intention, topic). Dual representation: k weighted exemplar trajectories + structured insight (failure modes, tool profile, index line).
Failure modeNamed root cause + failing sequence + recovery + anti-pattern + support count.
Skill jobTeacher / 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)

MethodPathDoes
GET/v1/portal/tracesCatalog + episode cards from collected.json
GET/v1/portal/traces/{id}Turns for one episode
POST/v1/portal/buildScrub → raw JSONL → cells on disk
GET/v1/portal/knowledgeCells + build report
GET/v1/portal/failure-modesNamed failures, sorted by support
GET/v1/portal/modelsDefault teacher / student / optimizer names (local catalog)
POST/v1/portal/cursor-keyTest a Cursor token (eval-platform: this run only). Returns models from GET /v1/models. Key is not stored.
POST/v1/portal/skill-optWith a key: live iterations, each with a SKILL.md diff. Without: local template rewrite.

Read API (frozen interface 0)

MethodPathWho
GET/healthany
GET/v1/indexany
GET/v1/cells, /v1/cells/{id}payload depends on persona
GET/v1/cells/{id}/exemplarsdeveloper (user: 403)
GET/v1/cells/{id}/failure-modesany
POST/v1/datasetsdeveloper — register a training set from cells
GET/v1/economicsmanager — 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.

PersonaSees
user (product owner)Index lines + named failure modes. No raw trajectories, no provenance (PII lived there).
developerFull cell, exemplars, dataset registration.
managerSpend / 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.

IdNamev0 stub
0Cell read APIThis FastAPI app
1Upstream ingestRawStore.append — JSONL of Episode, PII first, no overwrite
2Training platformPOST /v1/datasets returns a dataset id. No real training job.
3Inference / economicsGET /v1/economics + knapsack. Not on the live request path.
4Evaluationakb smoke / akb eval JSON report (M1.1–M1.4). No LLM judge.

7. Not in v0 (on purpose)