Dev.to AI 🤖 Ai 👁 0 📖 12 min read

I Built a Company Brain on FalkorDB: Cited Answers, Real Expertise and Decisions That Stay Current

TL;DR — For the WeMakeDevs × FalkorDB hackathon (Track 03: Company Brain) I built Hivemind, an agent that stores a company's documents, tickets, chats, meeting notes and GitHub activity as a FalkorDB knowledge graph. It

I Built a Company Brain on FalkorDB: Cited Answers, Real Expertise and Decisions That Stay Current

TL;DR — For the WeMakeDevs × FalkorDB hackathon (Track 03: Company Brain) I built Hivemind, an agent that stores a company's documents, tickets, chats, meeting notes and GitHub activity as a FalkorDB knowledge graph. It answers questions like "Who should I ask about Kafka?" or "Why did we choose Postgres — and is that still true?" by walking the graph, cites every source, finds knowledge risks with graph algorithms, and generates sprint plans and PRDs from the same data. It runs in the cloud or fully offline with one Docker command.
💻 Code: github.com/Utkarsh2730/hivemind
🎬 Demo video: https://youtu.be/2Omuy6xe5dk
📦 Run it offline: hivemind-offline.tar.gz — no accounts or API keys needed

The problem: the facts exist, the connections don't
Every company I've seen has the same knowledge problem. The information is written down — in Confluence pages, Jira tickets, Slack threads, meeting notes, pull requests — but the relationships between those pieces live only in people's heads:

A new engineer hits Kafka consumer lag. The runbook exists, the fix was discussed in Slack, someone was thanked for solving it last time — but which of the 40 people in the channel actually knows Kafka?
The team debates moving off Postgres. Didn't we decide this in March? Who decided? Was it later reversed?
The checkout launch is "blocked". By what? Who owns the blocker?
Sprint planning starts from a blank page every two weeks, even though every ticket, dependency and decision is already in the system.
Search returns documents. What people need are answers that follow relationships: person → wrote → runbook → about → Kafka; decision → made in → meeting → replaced by → newer decision; ticket → blocks → launch → assigned to → person.

That's a graph problem. So I built the product around a graph database instead of bolting a graph onto a vector store.

Why a graph (and why FalkorDB)

Question What it really needs
Who should I ask about Kafka? People connected to Kafka through evidence: what they authored, were assigned, were thanked for
Is the Postgres decision still current? Decision → SUPERSEDES chain → the latest active decision
Why is checkout blocked, and who can unblock it? Project ← mentioned by ← ticket ← BLOCKS ← ticket → assigned to → person
What happens if Tomas goes on leave? How many knowledge paths run through Tomas (betweenness centrality)
FalkorDB gave me everything I needed in one engine: openCypher for multi-hop traversals, full-text indexes for finding entry points, built-in graph algorithms (betweenness, PageRank, connected components), multiple isolated graphs per database (perfect for multi-tenancy), and a read-only query mode I could hand to an AI agent safely. It also runs anywhere — FalkorDB Cloud, Docker, or embedded on a laptop.


The rule I set myself, which is also the hackathon's rule: if the product still works without FalkorDB, the graph isn't doing real work. In Hivemind, every answer, ranking, decision trail, risk report and plan is a graph traversal.

What Hivemind does
The demo company is Lumen Pay, a fictional fintech: 12 people, 4 teams, 6 projects, 11 systems, and 27 documents, tickets, chat messages and meeting notes containing 7 decisions.

Ask with sources. "Who should I ask about Kafka consumer lag?" → Tomas Silva, because he wrote the consumer runbook and library and owns the Kafka upgrade — cited DOC-3, PLAT-21, MSG-2, MSG-3. Priya Nair formally owns the Event Bus, and Hivemind shows that too: knowing and owning are different edges.
Decision history. "What changed about customer login?" → the original Auth0 decision (now outdated) and the move to Keycloak (current), with the reasons and the meeting, RFC and message that recorded it.
Knowledge risks. Graph algorithms surface key connectors, systems only one person understands, stalled tickets and knowledge nobody is linked to.
Sprint plans and PRDs. Pick a project; Hivemind follows its tickets, BLOCKS chains, decisions and experts, schedules blockers first, suggests owners, and cites every line.
Stays current. Post "We're moving the ledger from Postgres to CockroachDB" and the old Postgres decision is marked outdated; the next ledger sprint plan already includes the migration.
Any company, any data. Create a private workspace, paste or upload documents, import a GitHub repo, or connect Slack, Jira, Linear and GitHub webhooks.

The graph model
Everything hangs off eight node types and a handful of relationships:


(Person)-[:MEMBER_OF]->(Team)-[:OWNS]->(Project)<-[:LEADS]-(Person)
(Project)-[:USES]->(System)
(Person)-[:AUTHORED]->(Source)-[:MENTIONS]->(Person|Project|System|Team)
(Source)-[:ASSIGNED_TO]->(Person)
(Source)-[:BLOCKS|REFERENCES]->(Source)
(Person)-[:MADE]->(Decision)-[:DECIDED_IN]->(Source)
(Decision)-[:AFFECTS]->(Project|System)
(Decision)-[:SUPERSEDES]->(Decision)
A Source is any piece of knowledge — a doc, a ticket, a chat message, meeting notes, a GitHub issue or PR. When something new arrives, Hivemind links it to the people, projects and systems it mentions (names, aliases, @handles, ~100 well-known technologies, and AI extraction when a Claude key is configured), detects whether it records a decision, and connects it.

Deep dive 1: expertise from evidence, not the org chart
The question "who knows X?" is where a graph shines. Instead of trusting a owner field, Hivemind collects evidence paths and weights them:

// wrote about it (weight 3)
MATCH (p:Person)-[:AUTHORED]->(s:Source)-[:MENTIONS]->(e)
WHERE e.key IN $k RETURN p.key AS person, s.key AS ev

// was assigned work on it (weight 2)
MATCH (s:Source)-[:ASSIGNED_TO]->(p:Person) MATCH (s)-[:MENTIONS]->(e)
WHERE e.key IN $k RETURN p.key AS person, s.key AS ev

// was named or thanked by a colleague in that context (weight 2)
MATCH (a:Person)-[:AUTHORED]->(s:Source)-[:MENTIONS]->(p:Person), (s)-[:MENTIONS]->(e)
WHERE e.key IN $k AND a <> p RETURN p.key AS person, s.key AS ev

// made decisions about it (weight 2)
MATCH (p:Person)-[:MADE]->(d:Decision)-[:AFFECTS]->(e)
WHERE e.key IN $k RETURN p.key AS person, d.key AS ev


Each piece of evidence counts once, scores are summed, and the top people are returned with their evidence keys — so the answer can cite exactly why Tomas ranks first. Formal owners come from a separate LEADS query and are shown alongside, because the gap between the two is often the most useful insight.

Deep dive 2: decisions that stay current
Decisions are first-class nodes. Each one points to where it was made and what it affects:

MATCH (p:Person)-[:MADE]->(:Decision {key: $k}) RETURN p.name, p.role
MATCH (:Decision {key: $k})-[:DECIDED_IN]->(s) OPTIONAL MATCH (a)-[:AUTHORED]->(s)
RETURN s.key, s.title, a.name
MATCH (n)-[:SUPERSEDES]->(:Decision {key: $k}) RETURN n.key, n.title


When new content records a decision, Hivemind looks for active decisions touching the same systems (and the same project, when both name one) and marks them replaced:

MATCH (d:Decision {status: 'active'})-[:AFFECTS]->(e)
WHERE e.key IN $affects RETURN d.key, d.title, collect(e.key)

MATCH (n:Decision {key: $new}), (o:Decision {key: $old})
SET o.status = 'superseded' MERGE (n)-[:SUPERSEDES]->(o)
The hard part wasn't the query — it was false positives. My first decision detector treated "PR approved, thanks!" and "we'll look into it" as decisions. I narrowed it to phrases that actually record a choice ("we decided", "we're moving", "going with", "switching to"…), added tests for the phrases that must not trigger it, and made every change reversible: removing a decision (or the message that created it) restores whatever it had superseded. A knowledge base people can't correct is one they stop trusting.

Deep dive 3: retrieval, and the bug my eval caught
Graph traversal needs good entry points. FalkorDB's full-text indexes provide them:

CALL db.idx.fulltext.createNodeIndex('Source', 'text', 'title')
CALL db.idx.fulltext.queryNodes('Source', $term) YIELD node, score
I built a small accuracy check — 10 questions about the demo company, each requiring specific facts and specific citations. It scored 9/10. The failure was "What do we know about the Stripe retry storm incident?": the most relevant ticket, which matched every word of the question, wasn't in the top results.

Two causes. First, my result formatting re-sorted sources by date, throwing away relevance. Second, a single OR-style query (Stripe|retry|storm|incident) didn't reward documents matching more of the terms. The fix: query each term separately, then rank by how many terms a node matched, and by summed score as a tie-breaker. The eval went to 10/10 and has stayed there. Small evals are cheap, and they find real bugs.

Deep dive 4: knowledge risks with graph algorithms
This is the feature only a graph can do. FalkorDB ships algorithms as procedures:

// key connectors: people on the most paths between knowledge
CALL algo.betweenness({
nodeLabels: ['Person','Source','Project','System','Decision'],
relationshipTypes: ['AUTHORED','MENTIONS','LEADS','USES','MADE','AFFECTS','DECIDED_IN','ASSIGNED_TO']})
YIELD node, score WHERE node:Person
RETURN node.name, score ORDER BY score DESC LIMIT 5

// central topics: what most work depends on
CALL algo.pageRank(null, null) YIELD node, score
WHERE node:Project OR node:System RETURN node.name, score ORDER BY score DESC LIMIT 5

// unconnected knowledge: items outside the main component
CALL algo.WCC({nodeLabels: ['Person','Team','Project','System','Source','Decision']})
YIELD node, componentId RETURN componentId, collect(node.key), count(node)
Combined with the expertise query (a system where one person holds almost all the evidence) and a Cypher check for tickets that are blocked, long in progress, or blocking others, "Where are our biggest knowledge risks?" returns things like: Tomas, Maya and Lena are key connectors; only Noor has hands-on evidence on Auth0 and Keycloak; PAY-52 is blocking the checkout launch.

Deep dive 5: sprint plans from BLOCKS chains
Planning is a traversal too. For a project, Hivemind gathers the tickets that mention it, plus anything that blocks them even if it belongs to another team:

MATCH (b:Source)-[:BLOCKS]->(s:Source)-[:MENTIONS]->(:Project {key: $k})
OPTIONAL MATCH (b)-[:ASSIGNED_TO]->(a)
RETURN b.key, b.title, b.status, a.name, s.key AS blocks
Priorities fall out of the graph: work that blocks other work is P0 and goes first, blocked work is P0 right after it, in-progress work is P1, the rest P2. Owners come from assignees, or — if a ticket is unassigned — from the person with the most hands-on evidence for the systems it mentions. Recent technical decisions with no ticket yet become rollout items. That's why, after the CockroachDB message, the ledger's sprint plan includes "Plan and roll out: Move the ledger from Postgres to CockroachDB" without anyone writing a ticket.

The agent: tools over a graph, with or without an LLM
The agent gets a small, specific toolset instead of raw database access:

search_knowledge — full-text entry points
entity_profile — everything about a person, project or system
who_knows — the expertise ranking above
decision_trail — decisions, sources and supersession
company_insights — the graph algorithms
run_cypher — read-only escape hatch
Every agent query runs through FalkorDB's read-only mode (GRAPH.RO_QUERY) and write keywords are rejected, so a model can never modify the graph. With an Anthropic API key, Claude plans the tool calls and writes the answer; without one, a rule-based planner calls the same tools — that mode answers all 10 eval questions correctly, which is what makes the fully offline build useful. The UI streams each tool call as it happens and highlights the subgraph the answer used, so you can see how it got there.

Multi-tenant by design: one graph per company
Any company can register a private workspace. Each one is a separate FalkorDB graph (cb_), so data never mixes; a registry graph stores only SHA-256 hashes of access keys. From there, knowledge flows in from paste and upload, a GitHub import (issues, PRs and comments become tickets, docs and messages; contributors become people), a Slack app (signature-verified events, a /hivemind slash command, history import or an export zip), and Jira/Linear/GitHub webhooks. Decisions can be announced back to Slack, Teams, Discord or Google Chat, and an MCP server lets Claude Desktop or Cursor query the brain directly.

Shipping it offline (and proving it works)
I wanted judges — and companies that can't send data to the cloud — to run Hivemind with no internet and no accounts. That meant three things:

No runtime CDN calls. Fonts, the graph library and images are bundled; I verified both pages render with every external host blocked.
One-command self-hosting. docker compose up -d starts FalkorDB (with a persistent volume) and the app.
An air-gapped bundle. A script saves both Docker images and an installer into one 204 MB archive.


I didn't have Docker on my laptop, so I let GitHub Actions prove it instead. On every push and release, CI runs the unit tests and the accuracy check against a real FalkorDB server, starts the Docker stack, builds the offline bundle, deletes the images, reinstalls the bundle from scratch exactly as a judge would, and runs a smoke test: landing page, bundled assets, demo data, a cited answer, the graph-algorithm insights, a sprint plan and creating a workspace. Only then is the bundle attached to the release.

Testing
21 automated tests: workspace isolation, access keys, people de-duplication ("Arjun", "arjun", "Arjun R." and "Arjun Rao" are one person), decision detection and reversal, deletion, cited answers, sprint ordering, PRD structure, the graph algorithms, the full API including streamed answers, Slack signature verification and slash commands, Jira/Linear/GitHub/generic webhooks, and the notification host allowlist.
Accuracy check: 10/10 demo questions with the required facts and citations.
Scale: 400 items import in under a second; above 450 nodes the graph view shows an overview and loads only the subgraph behind each answer.
Real data: importing FalkorDB/falkordb-py produced 61 items from 18 contributors, an expertise ranking and a sprint plan from open issues.
What I learned
Model the evidence, not the conclusion. Storing "Tomas is the Kafka expert" would go stale. Storing what Tomas wrote, fixed and was thanked for lets the graph recompute the conclusion every time.
Make the graph correctable. Decision detection will sometimes be wrong. Undo, and restoring what was superseded, mattered more than a smarter regex.
Show the path. Highlighting the exact subgraph and citing every claim did more for trust than any wording in the answer.
Graph algorithms answer questions people don't know to ask. Nobody types "compute betweenness centrality", but everyone wants to know who the single point of failure is.
Write the eval early. Ten questions caught a ranking bug I would never have noticed by clicking around.
Let CI test what you can't. The offline Docker path was tested end to end on GitHub's runners before any judge touched it.
What's next
SSO and roles instead of private links, encrypted connection secrets, Confluence and Notion connectors, local embeddings for semantic linking without internet, and one-click "Add to Slack" distribution.

Try it
Watch: https://youtu.be/2Omuy6xe5dk
Run offline: download hivemind-offline.tar.gz, then tar -xzf hivemind-offline.tar.gz && cd bundle && ./install.sh and open http://localhost:8000
From source: git clone https://github.com/Utkarsh2730/hivemind.git && cd hivemind && docker compose up -d
Read the code: github.com/Utkarsh2730/hivemind — the README lists every Cypher query the product depends on.
Built for the WeMakeDevs × FalkorDB hackathon, Track 03 — Company Brain. Lumen Pay and everyone in it are fictional. In line with the hackathon rules: I built Hivemind with an AI coding assistant, Anthropic's Claude (via Claude Code), which helped debug code, tests, UI and documentation; I chose the problem, directed the product and design decisions, and reviewed and tested the result.

Thanks to FalkorDB and WeMakeDevs for the hackathon. If you build something on a knowledge graph, I'd love to see it — find me on GitHub at @Utkarsh2730.

📰 Read the original article on Dev.to AI

Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.