Engineering

Skill Graphs - Building the Foundation

February 17, 2026

Architecture designed yesterday, building today. Handed the architecture doc to Claude and said "build it." This is where having AI collaborators genuinely shines - the tedious part of translating a design into migrations, models, services, and tests just... happens.

Claude one-shotted the entire data model. Five migrations, five models, all the relationships, all the casts. I reviewed it, tweaked a couple of column names, and we moved on. What would have been a full day of work took about twenty minutes of steering.

The database - five tables

Think of these as the filing cabinets:

  • Skill Graphs - The filing cabinet itself. Each user can have multiple graphs (e.g., "DevOps Knowledge", "Cooking Recipes", "Personal Finance").
  • Nodes - The individual cards inside. Each one holds a piece of knowledge with a title, body text, type, and trigger keywords.
  • Edges - The strings connecting cards together. Directed (A points to B) with a weight (how strong the connection is).
  • Embeddings - A mathematical fingerprint of each node's meaning. Used for the "meaning match" scoring from yesterday.
  • Node Versions - Every edit creates a snapshot. Like version history in Google Docs - you can always see what changed.
  • Retrieval Logs - A record of every time the system pulled knowledge for Iris. Which nodes were selected, what scores they got, how long it took. Essential for tuning.

The wikilink trick

This is my favourite design decision. Connections between nodes are created automatically from the text you write.

If you are writing a node about Docker Compose and you mention [[container-networking]] in the body, the system automatically creates a connection to the Container Networking node. No need to manually draw lines between cards - just write naturally using [[double-bracket]] links (like in Obsidian or Wikipedia) and the graph builds itself.

It is like writing a wiki article: every time you link to another page, the system knows those two topics are related. The graph grows organically as you add content.

The service layer

Claude built five specialised services, each with one job:

  • SkillGraphService - Creates and updates nodes, handles the wikilink-to-edge sync, triggers embedding generation, saves version history. The workhorse.
  • RetrievalService - Given a question, scores every node in the graph and returns the best matches. The talent scout.
  • TraversalService - Takes the best matches and walks the graph outward, collecting connected nodes within budget. The explorer.
  • InjectionFormatter - Takes the collected nodes and formats them into clean, structured text for Iris. The editor.
  • GraphContextProvider - The orchestrator that calls the others in order, caches results, and logs everything. The manager.

The traversal service was the most interesting piece. It uses breadth-first search (think ripples spreading from a stone dropped in water) with score decay - the further you get from the seed node, the lower the relevance score. MOC (Map of Content) nodes propagate better because they are natural hubs.

Configuration

Everything is tuneable without touching code:

  • Feature flag - Turn skill graphs on/off globally
  • Shadow mode - Log what would be injected without actually injecting it. Perfect for testing in production without risk. Like a dress rehearsal before opening night.
  • All the budget numbers (seeds, hops, nodes, tokens) are configurable so we can experiment and find the sweet spot.

Solid day. The entire backend went from nothing to fully functional in one session. Claude did the heavy lifting, I did the taste-testing.