Skip to main content
Back to projects

Gary

AI Agent for Company Knowledge

An AI agent for company knowledge. Gary reads Slack, Jira, Notion, meeting notes and GitHub into a FalkorDB graph, then answers by walking it: what is true right now, what used to be true, who decided it, why, and which docs are quietly lying.

Gary homepage
12
Fixed graph tools
~20 ms
Graph time per answer
65
Synthetic records
5
Source tools

Demo video

A three-minute walkthrough of Gary on the Kitestring demo company.

Overview

Every company has a Gary. He has been there since the early days. Ask him why the refund window is 14 days and he tells you the whole story in two minutes: the refund abuse in July, the Slack thread where the CEO approved the change, and the old Notion page you should stop trusting.

The day Gary goes on holiday, things slow down. The day he leaves, the company simply forgets. So I built a Gary that never leaves.

Instead of throwing every document into a search index, Gary builds a graph of people, teams, systems, projects, every record, and most importantly the decisions people made and which older decisions they replaced. Questions are answered by walking that graph, so every answer carries its path.

Built for Graph Hacks 2026, the FalkorDB and WeMakeDevs hackathon, in October 2026. Main track: Company Brain.

The Problem

Company knowledge does not live in one place, and it does not stay true.

In the demo company, a Notion page from February says customers can get a full refund within 30 days. In June, a pricing meeting changes the rule for annual plans. In August, the CEO cuts the monthly window to 14 days in a Slack thread because of refund abuse. Nobody updates the Notion page, the support playbook or the public help center article.

Now support asks: “Can a customer get a full refund after 20 days?” A normal document chatbot finds the pages with the right words and says yes, 30 days. Very confident. Completely wrong.

Similarity search can find text that sounds like the answer. It cannot tell you which of three contradicting documents is still true, because that information lives in the relationships between them, not in the words.

Goals of the Project

GoalHow it is met
Know what is true right nowEvery decision is linked to the one it replaced, so answers follow SUPERSEDES to the current one.
Find stale docs on its ownAny doc that still ASSERTS a replaced decision is flagged, together with its author.
Never invent a connectionThe model picks from 12 fixed, parameterised Cypher tools and never writes its own queries.
Show the workEvery step lists the exact Cypher, the row count and the time it took.
Say “I don't know”Names are resolved against the graph first. Anything unknown is reported as unknown, not guessed.
Work with other agentsThe same tools are exposed over MCP for Claude Desktop, Claude Code or any MCP client.

System Architecture

Records flow in through one ingestion pipeline and come out as nodes and edges. Questions flow through an agent that can only read the graph through a fixed tool catalogue, and every answer is checked against the rows those tools returned before it reaches the screen.

System architecture

Decision extraction is the interesting part of ingestion. The language model reads each record while looking at the decisions currently in force, so it can say which older decision a new one replaces, why it was made and which docs repeat it. Reads go through GRAPH.RO_QUERY, so the agent side physically cannot write.

The Graph Model

Gary's graph model: Person, Team, Project, System, Topic, Records, Decision and Finding nodes, with the SUPERSEDES and ASSERTS relationships highlighted
Everything the agent knows lives in FalkorDB. Answers are walks along these relationships.
NodeWhat it is
Person, TeamWho works here, who leads what, and when they joined or go on leave
System, Project, TopicThe things people work on and talk about, like ledger-db or the refund policy
Message, Ticket, Doc, Meeting, PREvery record from the five tools, with its author, date and link
DecisionA rule, plan or date someone agreed on, with the day it started and the day it was replaced
FindingGary's own memory of past answers

Two relationships carry most of the weight. SUPERSEDES links a newer decision to the one it replaced, and it is the heart of Gary. ASSERTS links a doc or ticket to a decision it repeats, so the moment that decision is replaced, the doc is stale.

Key Features

Decision lineage and stale docs

Gary answers with the decision that is in force today, shows the chain of decisions it replaced, and lists every living doc that still states an old one. Fix it opens a ticket for each stale doc, assigned to the person who wrote it.

Gary's workspace answering the refund question, with the current decision, the replaced one, three stale docs, and the plain RAG answer underneath; the company graph on the right highlights the nodes used
The answer, its lineage, three stale docs and the plain RAG answer for the same question.

The time machine

Gary never deletes a decision. A replaced decision stays in the graph with the date it stopped being true, so the whole company can be rewound to any day. Press play and records appear on the day they were written, people show up when they joined, decisions turn grey when they are replaced and docs turn red on the day they went stale.

The time machine tab showing the Kitestring graph as of 1 July 2026, with the refund policy that was in force that day and the docs that were already stale
“What was our refund policy on July 1?”, answered and rewound to that day.

Who actually knows, and risk radar

Not the org chart. Expertise is weighted by role, with authored work counting more than reviewed work and asking a question counting less than answering one, and older work fades over about four months. If one person holds most of the knowledge about a system and is about to go on leave, Gary flags it and suggests backups computed in Cypher.

Gary ranking who knows about ledger-db, with Tomasz Novak at 55 percent and a warning that he is unavailable from November 2
One engineer holds 55% of the ledger-db knowledge and goes on leave in the middle of the cutover.

Memory that expires

Every answer is saved as a Finding node that CITES the decisions it relied on. When one of those decisions is superseded, the memory is flagged as outdated instead of being trusted blindly.

An earlier answer about the refund policy marked OUTDATED after the live feed posted a new refund decision
A new Slack message changed the policy, so the earlier answer is marked outdated.

More of what Gary can do

  • Catch up: “I'm back from three weeks off, what did I miss?” returns only the changes in your part of the company.
  • The real why: usage pricing launches on December 1 because the ledger migration moved, which moved because of the SOC2 audit freeze. Three hops, all walked.
  • Live feed: post a new Slack message and the graph updates in milliseconds, superseding old decisions on the spot.
  • Graph algorithms as tools: shortest path, betweenness centrality and label propagation run as FalkorDB procedures.
  • MCP: every tool is available to Claude Desktop, Claude Code or any MCP client.

Proof the Graph Does the Work

A fair test for any graph project is simple: take the graph away and see what breaks. The app runs a plain document chatbot next to Gary with the same records, the same language model and FalkorDB's own full-text index, just without the relationships.

QuestionPlain RAGGary
Can a customer get a full refund after 20 days?Yes, 30 daysNo, 14 days since August 12, decided by the CEO in #billing, and three docs still say 30
Who should I talk to about ledger-db?Whoever is mentioned mostTomasz, but he is on leave from November 2, so here are two backups
Who owns the mobile app?A plausible-sounding teamThere is no mobile app in the graph

Current versus replaced decisions, stale documents, who knows what, single points of knowledge, the time machine, multi-hop “why” answers and memory that expires are all walks through the graph. None of them can come from text similarity alone.

The Cypher Behind It

The agent picks from 12 tools: decision_lineage, who_knows, profile, connect, risk_radar, real_teams, as_of, catch_up, search, open_ticket, fix_stale_docs and remember. Each one is a fixed query with parameters. Three of them do most of the heavy lifting.

MATCH (s:Entity {key:$key})
MATCH (cur:Decision {status:'active'})-[:ABOUT]->(x)
WHERE x = s OR (s)-[:USES]->(x)
OPTIONAL MATCH chain = (cur)-[:SUPERSEDES*1..6]->(:Decision)
WITH cur, chain ORDER BY length(chain) DESC
WITH cur, collect(chain)[0] AS longest
RETURN cur.key AS key, [n IN nodes(longest) | n.key] AS lineage
Decision lineage: the longest SUPERSEDES chain behind each active decision about a subject.
MATCH (cur:Decision)-[:SUPERSEDES*1..6]->(old:Decision) WHERE cur.key IN $heads
MATCH (doc:Doc {living:true})
WHERE ((doc)-[:ASSERTS]->(old) OR (old)-[:DECIDED_IN]->(doc))
  AND NOT (doc)-[:ASSERTS]->(cur)
OPTIONAL MATCH (a:Person)-[:AUTHORED]->(doc)
RETURN DISTINCT doc.key AS doc, doc.title AS title, old.key AS old,
       cur.key AS current, a.name AS author
Stale docs: living docs that still state a replaced decision and not the current one.
MATCH (s:Entity {key:$key})
MATCH (d:Decision)-[:ABOUT]->(x)
WHERE (x = s OR (s)-[:USES]->(x))
  AND d.at <= $t
  AND (d.superseded_at IS NULL OR d.superseded_at > $t)
OPTIONAL MATCH (n:Decision)-[:SUPERSEDES]->(d)
RETURN d.statement, d.at, n.statement AS later_replaced_by, n.at AS replaced_on
Time travel: decisions are never deleted, only stamped, so “what was true on date t” is one filter.

Application Flow

One question, end to end

Challenges and Solutions

ChallengeSolution
The model inventing graph connectionsNo model-written Cypher. The model chooses from 12 fixed, parameterised tools.
Real citations next to an invented teamMy own demo recording caught a made-up “Product-Mobile team”. Every proper name in an answer must now exist in the graph or the turn's tool results, otherwise the answer is rebuilt from the rows.
Guessing when a subject does not existNames are resolved first: exact, then alias, then full-text with at least 50% word coverage. No match means unknown_subject.
The model getting supersessions wrongExtraction ran with gpt-oss-120b and was reviewed by hand. One PR was wrongly treated as replacing the release policy and was fixed.
Rate limits on free model hostingA fallback chain from gpt-oss-120b to gpt-oss-20b to qwen3.8-27b, and cached extractions for the seed data.
Remembered answers going quietly wrongMemory is just nodes. A Finding CITES its decisions and expires when any of them is superseded.
Visitors breaking the shared demoA Reset demo button rebuilds the whole graph from the raw data in a few seconds.

Tech Stack

LayerChoiceWhy
GraphFalkorDB on FalkorDB CloudCypher, graph algorithms and full-text search in one database
FrameworkNext.js 16, App RouterAPI routes stream NDJSON agent events as they happen
LanguageTypeScriptOne language across ingestion, tools, agent and UI
LLMGroq: gpt-oss-120b with fallbacksAny OpenAI-compatible endpoint works, including local Ollama
Graph viewreact-force-graph-2dHighlights exactly the nodes an answer used
AgentsModel Context Protocol SDKGary as a company brain for other agents
MotionMotion, anime.js, LenisThe landing page, the live graph and the time machine
HostingVercelThe app and the API routes

Deployment and Data Ethics

The app runs on Vercel against a FalkorDB Cloud instance, and the same graph can be run locally with Docker Compose, which also brings up the FalkorDB Browser for poking at the graph directly. One graph per company is already supported through GRAPH_NAME.

All data is synthetic. Kitestring is a made-up 21-person billing startup with 65 records across Slack, Jira, Notion, meetings and GitHub. Its storylines, like two refund policy reversals, a SOC2-delayed migration and an engineer going on leave mid-cutover, are written so the right answer always depends on how things connect. No private, personal or scraped data is used anywhere.

Conclusion

Most “chat with your docs” tools treat company knowledge as a pile of text. Gary treats it as a history of decisions, and that one change is what lets it tell current from replaced, find the docs that are lying, and admit when it does not know.

Next up are real connectors with webhooks instead of exported files, permissions that travel with every record so people only see what they are allowed to see, and a multi-tenant UI on top of the one-graph-per-company support that already exists.