Graph Databases

I built an app just to break my own knowledge graph format

Read-only was fine, until it wasn't

KGL started life as a read-only format: plain-text files as nodes, folders as namespaces, links as edges, and an OpenCypher-style query engine to read it all back without a database anywhere in the picture. That's genuinely useful for structured notes, entity graphs, anything you want to version in git and grep in a pinch. It's not enough for anything that needs to change over time without a human opening a text editor.

KGL 0.2 adds the missing half: CREATE, MERGE, SET, DELETE, DETACH DELETE. A program can now open a graph, find-or-create a node, update its fields, link it to something else, and remove it, through the same Cypher syntax already used for reading. MERGE (n:Person {name: "..."}) INTO "people/priya.kgl" ON CREATE SET ... ON MATCH SET ... either creates the file or updates the existing one, same call either way.

The interesting part isn't the feature list. It's how I decided whether it actually worked before calling it done.

Why I didn't trust my own tests

Unit tests check that code does what you told it to do. They can't tell you what you forgot to tell it to do, and a parser and writer tested only against the cases their own author thought of will always have a blind spot shaped exactly like that author's assumptions.

So before shipping the write layer, I built something else on top of it, on purpose: kgl-memory, a graph-native memory system for AI agents, giving them persistent facts, preferences, and conversation history stored entirely as KGL files instead of a database. Every message an agent logs, every fact it extracts, every preference a user states, gets written through the exact CREATE/MERGE/SET/DELETE surface I'd just finished building.

That was the whole point. A real, independent consumer with its own requirements was always going to find the rough edges faster than another test file I wrote myself, because I already know what I meant by my own code. Software that only ever gets exercised by its author's own imagination stays untested in exactly the places that matter.

What it found

Seven bugs, before anyone outside my own machine ever touched the write layer.

The clearest one: any field value starting with # — a hex colour, say color: #ff69b4 — got read back as a tag, and the field vanished from the file entirely. No error. The value was just gone. This one didn't even come from kgl-memory — it turned up independently, the same week, in a completely unrelated project (a colour-coded map feature) that happened to hit the same code path. Two projects finding the same hole a few days apart says more about how narrow one test suite's imagination is than either project does on its own.

A quieter one surfaced while writing kgl-memory's own extraction pipeline: MATCH (n) WHERE n.name = "..." matched nothing. Ever. For every query, silently. The query engine checked every field a node had except the one thing anyone would reach for first, its own name.

And one that only a real, sustained write pattern would ever have caught: appending a second message to the same session file quietly corrupted the first message's stored content with a phantom blank line, because the writer's "insert a new node here" logic and the parser's "where does a body end" logic disagreed, ever so slightly, about where one node stopped and the next began. A single write-then-read test never appends a second node. An actual conversation always does.

None of these are exotic. They're the specific kind of bug that a hand-written test file never exercises, because whoever wrote the test already knew, without thinking about it, not to do the thing that breaks it.

Where it landed

All seven are fixed in KGL 0.2, out now on PyPI as kgl-langkgl the name was already taken by an unrelated package, so pip install kgl-lang is what gets you the kgl command and the kgl Python package underneath it, just not the PyPI listing you'd type first.

kgl-memory itself is still one door down, not published yet, still living entirely inside the project it was built to test. That's tomorrow's post: what it actually looks like to give an AI agent real, git-trackable, per-project memory, built on nothing but files you could open and read yourself.

← Back to all posts