---
title: "The knowledge graph layer above the vault"
canonical: https://dxdev.com/blog/2026-05-02_graph-layer-above-the-notes-repo/
datePublished: 2026-05-02
---
Somewhere in the middle of a long mobile session pushing work on a content pipeline, I stopped arguing about where the knowledge graph should live and saw what it actually is. It is the graph above the vault, a layer rather than a future repo or a competitor to anything I already run.

Until that afternoon I had been treating it as a storage problem. Where do the nodes live. Which database. Postgres or SQLite or duckdb or some embedded thing. Markdown front matter or a real schema. Should it own session transcripts or just point at them. Months of that.

The storage argument dissolved the moment the job description got clear.

## the wrong model

The model I had been carrying was that this knowledge graph was a future codebase. Some repo that did not exist yet, that would eventually replace or absorb pieces of the vault and the agent system and maybe parts of JIRA. I kept stalling on the design because every storage decision implied a migration plan, and every migration plan ran into the fact that the vault already works.

That was wrong. The vault is not a thing to migrate away from. It is a thing that should stay exactly where it is, doing exactly what it does. Markdown files, human-readable, git-versioned, grep-able. The vault wins on every axis it competes on.

JIRA wins on its own axes too. Workflow state, transitions, sprint membership, custom fields for all the domain-specific metadata that accumulates over time. I am not going to outbuild Atlassian on issue tracking from a personal workstation.

The session transcripts are already a system. Claude Code writes them, my hooks read them, work logs get generated nightly. That pipeline ships.

What I did not have was anything that could see across all four at once: a goal in the vault, a ticket in JIRA, the session that pushed it, the agent memory that fired during the work. Each surface knew its own slice. None of them knew the others existed in any structured way.

That is the graph. That is what the knowledge graph layer is for.

## what changed when I named the layer

The reframe is not cosmetic. It changes what the graph layer is allowed to own and what it is not.

It owns edges. A goal node points at the ticket node points at the session node points at the memory node. The edge says what the relationship is. The node identity belongs to whichever system already owns it. JIRA owns a ticket. The vault owns its corresponding markdown file. The session manifest owns the session ID. The graph layer owns the fact that those three identifiers refer to the same beat.

It does not own canonical storage. The markdown file in the vault is still the canonical doc. The JIRA ticket is still the canonical workflow record. The graph layer is allowed to read both, write edges across both, and decorate either with derived metadata. It is not allowed to be the source of truth for anything that already has one.

It owns retrieval policy at altitude. "Show me every session that touched this ticket" is a graph query. "Show me every ticket that mentions a goal tagged `agent-system`" is a graph query. "Show me the chain of decisions that led to the current production topology" is a graph query that crosses three repos and four months of session transcripts. None of those queries fit cleanly in vault grep or in JIRA JQL. All of them are natural in a graph.

That is enough job description to start building.

## the gateway poc actually works

The piece that made the reframe stick was a gateway proof-of-concept. A small HTTP service that accepts writes from agents, validates them against a schema, commits to the vault, and pushes to GitHub. Read, write, commit, push, against a live vault, end to end.

It is not the graph yet. It is the ingestion surface that the graph will eventually sit behind. But it proved the architecture is buildable. Agents can already write through it. The vault can already accept those writes without breaking. Git history stays clean because the gateway batches commits and signs them properly.

The remaining blockers are physical, not conceptual. Public ingress is hung up on Cloudflare Access (good for humans, awkward for agent traffic), named tunnel collisions on the local server, and the fact that Tailscale Funnel still wants sudo on every restart. Annoying. Not architectural.

Once the gateway has a stable public URL, the next layer is the graph itself: edge types, embedding strategy, retrieval policy. None of that requires me to argue about storage again, because storage is solved. The vault stores docs. JIRA stores tickets. The session pipeline stores transcripts. The graph layer stores edges.

## what this means for the daily rhythm

The thing I did not expect was how much this clarified everyday work. Before the reframe, every new session forced a small decision: where does this thought belong, vault or the graph layer or somewhere else. After the reframe, the decision is automatic. The thought goes in the vault. The graph layer just makes sure the right edges exist so I can find it again at any altitude.

Goal sprawl was the actual problem I was trying to fix, and goal sprawl turns out to be a symptom of storage ambiguity. When every new captured thought triggers a "where does this go" question, you accumulate sessions faster than you reconcile them. Once storage is unambiguous, capture cost drops to roughly zero and reconciliation can run in the background.

The vault is already where things go. The graph layer just lets me ask the questions that span more than one file.

## the principle

If you are stuck in the same storage argument, stop and map one real chain instead. Pick a single goal, find the ticket it produced, the session that pushed it, and the piece of agent memory that fired during that work, then write down each system's own identifier for that item and the edges connecting them. Do that once, by hand, before you design any schema. It tells you whether you actually need a graph layer or just better cross-references.
