Source
Where the note came from: a file, an issue, a docs page, a pull request, a generated artifact, or a decision someone made in a meeting. Every note points at one, and you can open it.
notes your agent can't quietly make up
Your coding agent learns things about your repo — that deploys go through GitHub Actions, that the auth module belongs to another team, that you tried Redis and backed it out. Ask it three months later and it will tell you those things back with total confidence, and you will have no way to check any of them.
Knowledge Kit stores each note with the thing it was made from and the date it was made. When a note gets replaced, the one it replaced stays readable instead of disappearing.
$ npm install @kontourai/flow-agents
$ node node_modules/@kontourai/flow-agents/kits/knowledge/adapters/obsidian-store/demo.js
[1/4] Created raw capture: 6c4716e1…
[2/4] Created compiled note: c48498d7…
[3/4] Created placeholder snapshot: 4981bc88…
[4/4] Created final snapshot 55a0c2ae… (supersedes 4981bc88…)
Superseded placeholder archived at: archive/eng/decisions/ci-strategy-snapshot-draft.md
Archived record still queryable via get(): title = "CI Strategy Snapshot — Draft"
Real output from the demo that ships in the package. Record ids shortened; nothing added.
What came out
The transcript lands in the store as a raw capture. A compiled note distils the decision out of it. A snapshot records where the topic ended up — one file, on disk, in the vault you already read.
The snapshot names the note it was made from, twice: once in provenance.source_ids and once as a kind: source link. Six months later you can walk from the decision back to the meeting it came out of without asking the agent to remember.
It also names the draft it replaced. That draft moved to archive/, still answers get(), and carries a log entry saying what superseded it and why.
---
type: snapshot
title: CI Strategy Snapshot — Q2 2026
category: eng.decisions
status: active
provenance:
agent: demo-agent
source_ids: [c48498d7…]
links:
- target_id: c48498d7…
kind: source
- target_id: 4981bc88…
kind: supersedes
mutation_log:
- op: supersede
agent: demo-agent
rationale: Q2 planning meeting resolved the CI strategy;
placeholder superseded by final snapshot.
---
Decision: Migrate from Jenkins to GitHub Actions in Q2 2026.
…
## Sources
[[jenkins-retirement-decision]]
The note as the demo wrote it. Trimmed for length: the record id, timestamps, tags and the rest of the body are elided at the… marks. No line here is anything other than what the run printed.
What a note carries
Where the note came from: a file, an issue, a docs page, a pull request, a generated artifact, or a decision someone made in a meeting. Every note points at one, and you can open it.
Which agent captured it, when it was observed, and what changed on every later edit. The mutation log is append-only — edits get added to it, never written over.
Set how long notes in a category stay good. Past that date the record reads back as stale the moment anything queries it — and the record itself is never rewritten behind your back.
A raw capture, a compiled note, a named concept, or a topic snapshot. When one record replaces another, the older one stays queryable — superseded records are never deleted.
Your store, your shape
Choose the storage experience that fits the team. The default writes portable markdown with frontmatter and a graph index. The Obsidian adapter creates vault-native notes. Both write into a root you configure — there is no default path, and the adapter refuses to start without one. A local, Ollama-backed similarity adapter powers synthesis clustering and contradiction checks while keeping the knowledge on your machine.
The default store: frontmatter records, supersede chains preserved, greppable and diffable like the rest of your repo.
The same gated records as vault-native notes, so your existing knowledge tooling keeps working on content that carries its sources. Shipped and in use; layout refinements and person cards are still landing.
Four passes go looking for trouble: notes past their date, notes that contradict each other, glossary terms that drifted from the doc that defines them, categories that sprawled. Every one is read-only — it hands you a list with the evidence for each item and you decide. Off by default, on per category.
The store is a written contract, not our file format: four record types, the seven operations that can change a record, and the evidence each one has to carry. A backend adopts it without forking any of the kit's flows.
The contract ships as a test suite you point at your own storage — set KNOWLEDGE_ADAPTER to your adapter and it tells you what is missing. The two stores above are just the first two things that passed it.
$ node node_modules/@kontourai/flow-agents/kits/knowledge/evals/contract-suite/suite.test.js
▶ create: required field enforcement
✔ rejects missing provenance.agent
✔ rejects missing category
▶ link: required evidence enforcement
✔ rejects nonexistent target_id
▶ apply: required evidence enforcement
✔ rejects apply when no proposes link exists
▶ identity: alias resolution survives restructure (AC3)
✔ old slug and short-id prefix still resolve after a recategorize
…
ℹ tests 69
ℹ pass 69
ℹ fail 0
When a note goes bad
It told you the deploy pipeline runs on GitHub Actions. Maybe it read that in a doc. Maybe it read it in a doc that was true last year. Maybe it inferred it from a filename. Right now there is no difference between those three, because the answer arrives the same way regardless.
A record past its expiry reads back as stale the moment anything queries it — the store never quietly rewrites the record to say so. A separate pass compares notes filed under the same category and flags pairs that contradict each other, citing both record ids and the reason it fired.
Neither pass can change anything. Both hand you the list and stop; you decide whether a note gets refreshed from its source or retired. Retired notes drop out of the working set and stay queryable — the history is still there when someone asks why the guidance changed.
Already running a memory layer?
Plenty of teams already have something — an OKF-style knowledge bundle, a hosted memory service, or a hook and a folder of markdown. Knowledge Kit is for teams who want the store too. If you already have one, keep using it: Kontour never touches the retrieval side, and there is nothing to migrate.
What Flow Agents adds is a record of the run that came after — the commands the harness actually executed, their exit codes, and which gates let the work advance. That record is a separate artifact from your memory layer, so swapping retrieval out next quarter leaves the evidence already attached to shipped work untouched.
Try it
The demo builds a throwaway vault in your temp directory, writes the four records above, prints the snapshot note verbatim, and deletes the vault on the way out. The contract suite is the same one every store adapter has to pass.
$ npm install @kontourai/flow-agents
# the worked example
$ node node_modules/@kontourai/flow-agents/kits/knowledge/adapters/obsidian-store/demo.js
# the contract every store adapter has to pass
$ node node_modules/@kontourai/flow-agents/kits/knowledge/evals/contract-suite/suite.test.js