
Your Obsidian Vault Is Already a Graph. Stop Feeding It to the Model Flat.¶
I wired an LLM into my Obsidian vault a while back, the PARA-plus-LLM setup I wrote about in Your Second Brain, Now With an AI Inside It. It's genuinely useful. It's also, if I'm honest about the mechanics, wasteful in a way I didn't notice until I started thinking in graphs for a different reason entirely.
Ask it a question and you've got two bad options. Paste in the relevant folder, or the whole vault if you're not sure which folder, and burn tokens on notes that turn out to have nothing to do with the answer. Or let a "chat with your notes" plugin do semantic search over embeddings, which retrieves whatever's nearby in vector space, and vector space doesn't know the difference between "these two notes discuss similar-sounding infrastructure concepts" and "these two notes are actually about the same thing."
The number that made me rebuild the retrieval step
Running the same anchor note through a plain 2-hop graph traversal instead of dumping the vault: 6 notes instead of 17, 367 tokens instead of 949 (a 62% reduction), and every note in that neighborhood was there because I linked it there on purpose, not because an embedding model thought it looked similar.
There's a better retrieval mechanism sitting in the vault already, and you built it yourself, one [[link]] at a time.

The Problem With Feeding a Vault to a Model Flat¶
Two options, both bad in their own way. Option one: dump a folder, or the whole vault, into context. Token cost scales with how big your vault has gotten, not with how relevant any of it is to the question you're asking, and vaults only grow.
Option two: semantic search, which is what most "chat with your notes" plugins actually do under the hood. Embed the query, embed every note, retrieve the nearest neighbors. This has a specific failure mode worth naming: embedding similarity measures how similar two pieces of text sound, not whether you actually meant them to inform the same answer. A note about Kubernetes RBAC and a note about AWS IAM will sit close together in embedding space because they use similar vocabulary — access control, policies, roles — even though you never linked them and never meant them to be read together. Meanwhile two notes you did deliberately connect can sit far apart in embedding space if you phrased them differently on different days.
Why this matters more than it sounds
Embedding similarity is a proxy for relevance, computed after the fact by a model that never read your notes the way you did. The links in your vault are the actual ground truth of relevance, because you're the one who drew them, at the moment you understood the connection.
Your Vault Already Has a Declared Topology¶
This is the same claim from graph engineering: declare the topology instead of discovering it at runtime. In an agent system, that means writing down nodes and edges before anything executes. In your vault, you already did the declaring — every [[link]], every entry in a Map-of-Content note, is an edge you drew on purpose, at the moment you understood the connection between two ideas.
That makes a vault's link graph a GRAPH.md, just written by hand over months or years instead of in one sitting. Nobody had to infer it from clustering behavior. You made it while you were thinking.
[[Harness Engineering]] <-> [[Graph Engineering]] <-> [[Obsidian Retrieval]]
| |
[[Stripe Blueprint]] [[PARA Method]]
A 2-hop traversal starting from [[Graph Engineering]] should pull in exactly that cluster — Harness Engineering, Obsidian Retrieval, and one hop further, Stripe Blueprint and PARA Method. Nothing about bodybuilding, nothing about your recipe notes, even though they all technically live in the same vault.
The note that ruins this if you're not careful
Every real vault has at least one Map-of-Content note that links to everything "so nothing gets lost." Traverse through it unprotected and one hop pulls in your entire vault regardless of relevance: the exact problem you were trying to avoid, just relocated from "the whole vault" to "the whole vault, but it took an extra step to get there."
Retrieval as Traversal, Not Search¶
The mechanism: resolve an anchor note — the one you're currently looking at, or the best keyword match for the query — then walk the graph outward by real links, both forward links and backlinks, collecting only that neighborhood as context. No vector database, no embedding step. Parse [[wikilinks]] directly out of the markdown, build an adjacency structure, and do a breadth-first walk N hops out from the anchor.
The part that actually matters is what happens at the hub note. A note is still included in the results if you land on it — you did link to it, after all — but traversal doesn't continue through it once its own link count crosses a cutoff. That's the whole fix: the hub shows up, the five hundred notes it fans out to don't.
# simplified sketch — full version in the ai-capabilities repo
def traverse(adj, anchor, hops, hub_cutoff):
visited = {anchor}
frontier = deque([(anchor, 0)])
order = [anchor]
while frontier:
node, depth = frontier.popleft()
if depth == hops:
continue
if depth > 0 and len(adj.get(node, [])) > hub_cutoff:
continue # don't traverse through a hub note
for neighbor in sorted(adj.get(node, [])):
if neighbor not in visited:
visited.add(neighbor)
order.append(neighbor)
frontier.append((neighbor, depth + 1))
return order
See it running
The full CLI, plus a 17-note sample vault with a hub note built in, is a runnable example in the ai-capabilities repo. It's the tool that produced every number in this post.
What You Get: Tokens Down, Relevance Up¶
Here's the same 17-note vault, a 6-note cluster about graph engineering, ten completely unrelated personal notes, and one Map-of-Content hub, traversed two different ways.
Unprotected, hub-cutoff effectively disabled:
Neighborhood: 17 notes (2 hops)
Approx tokens for this neighborhood: 949
Approx tokens for the whole vault: 949
Reduction: 0%
Every unrelated note rides in through the hub. Bodybuilding programming, a sourdough starter recipe, a travel itinerary: all present, all irrelevant, all costing tokens.
With the hub excluded from further traversal:
Neighborhood: 6 notes (2 hops, hub-cutoff=4)
- Graph Engineering (anchor)
- Harness Engineering
- MOC - All Posts
- Obsidian Retrieval
- Stripe Blueprint
- PARA Method
Approx tokens for this neighborhood: 367
Approx tokens for the whole vault: 949
Reduction: 62%
Same anchor, same vault, one line of protection against traversing through a hub. The neighborhood is exactly the cluster you'd draw on a whiteboard if someone asked you "what's related to graph engineering in my notes" — because that cluster is precisely what you built when you wrote the links.
Where This Fits the Rest of the Stack¶
This is graph engineering applied to retrieval instead of multi-agent coordination: same claim, different substrate. The Second Brain post covered the reasoning layer: PARA for structure, an LLM as the CPU in Karpathy's LLM OS model, the CODE workflow automated. This post is the layer underneath that — how the model actually gets the right notes into its context window in the first place, rather than what it does once they're there.
And it isn't specific to Obsidian. Any linked-markdown corpus has the same property: a docs site with cross-references, a wiki, even a well-linked set of READMEs across a monorepo. Wherever humans have deliberately connected ideas with links, that link structure is a better retrieval signal than re-deriving relevance from scratch with embeddings.
FAQ¶
Doesn't this only work if I've been diligent about linking my notes?
Yes, and that's the point rather than a limitation. If you haven't linked two notes, the system correctly doesn't treat them as related — which is more honest than an embedding model guessing they're related because the vocabulary overlaps. The traversal is only as good as your linking habit, but that's true of your own recall too.
What about notes that should be related but I never got around to linking?
Nothing stops you from combining approaches: use traversal for the graph you've built, fall back to a keyword or embedding search for the anchor note resolution step itself, or as a secondary pass. The claim here isn't "never use search," it's "don't make search do the whole job when you already have better ground truth."
How do I pick the hub cutoff?
Look at your vault's actual link counts. A personal Map-of-Content note is often linked from and to dozens of other notes; a well-scoped topic note might have three to ten. Set the cutoff between those two populations. The sample vault in the ai-capabilities repo uses 4 against a 16-link hub to make the effect obvious — your real number will depend on how you use MOC notes.
Do I need to migrate away from my vector-search plugin?
No — this is a different tool for a different job, not a wholesale replacement. Vector search is still useful for the cold-start problem of finding an anchor note in a vault you don't remember well enough to search by title. Traversal takes over from there.
The vault was never the second brain. The links were. Feeding a model the notes without the connections between them is like handing someone your bookshelf with the spines torn off. Technically all the content's there, but you've thrown away the one thing you actually organized.
For more on the underlying claim, see From Harness to Graph: The Fourth Era of Working With AI. For the reasoning-layer half of this setup, see Your Second Brain, Now With an AI Inside It.