Engineering teams already have the facts. They are just split across Discord, GitHub, and docs. Someone says Priya will take the frontend. A pull request lands. An issue mentions billing. A week later nobody can answer "what is blocked?" or "who actually knows authentication?" without scrolling.
SigmaAgent is a Discord bot that treats that mess as one graph. Mention @SigmaAgent in plain language. It answers from tasks, people, commits, issues, docs, and chat that live in FalkorDB, one graph per Discord server.
A few posts on DEV pushed me toward a graph instead of another vector index. Prabhu used FalkorDB so an agent could remember interactions as edges and walk them with Cypher. sznimperial made the same move for ownership: chunks guess, edges say who owns what. Razeef Shaikh put it in one line I kept coming back to: search finds documents, a graph finds consequences.
That last one is the product. "What is blocked?" is a consequence question.
Who it is for
Software teams that already run the day in Discord and GitHub. The bot is the project brain for that server: assignments said in chat, dependency edges, GitHub activity, and the question you would otherwise ask in a standup.
There is no slash-command menu. You talk to it:
| You say | What happens |
|---|---|
Priya will do the frontend |
Creates or assigns the task |
T3 is blocked by T1 |
Writes a BLOCKED_BY edge |
mark T2 as done |
Updates status |
what is blocked? |
Lists blocked tasks and why |
explain T5 |
Dependency chain with owners |
who knows about billing? |
Ranks people from six kinds of evidence |
bottlenecks |
PageRank over the dependency graph |
who are the contributors? |
Commit counts, ranked |
what bugs are open? |
Issues filtered by label |
summarize issue #6 |
Summary plus the latest discussion |
compare alice and bob |
Contribution scoreboard |
sync github owner/repo |
Pulls commits, issues, and docs into the graph |
Friend scores are computed in the graph, not in a spreadsheet: commits count as 3, closed assigned issues as 2, plus open assigned issues and issues opened.
How a message gets an answer
Most questions never call a model. The path is:
Discord, GitHub webhooks, or the REST API → a deterministic router → FalkorDB, or Gemini only when the router cannot answer → that server's graph.
The router matches task, blocker, contributor, and issue phrasing with patterns and returns the graph result with zero LLM tokens. Gemini is the failover: it reads a report the graph already computed (owners, dependencies, impact, bottlenecks, critical path) and writes the sentence a person would say in chat.
POST /investigate returns the answer, the sources, and the Cypher that produced them, so a reply can be audited instead of trusted as a hallucination.
Four processes make that work:
- FastAPI on port
8000for investigation, GitHub, sync, and Discord ingest. - A context API on port
8001that turns chat into blocker and decision evidence. - The Discord bot, which mentions the API rather than querying the database itself for every path.
- An optional Next.js site on port
3000.
GitHub push, issues, and pull request webhooks upsert as they arrive. A background syncer retries with exponential backoff when a webhook is missed. Garbage collection deletes orphaned nodes so a server graph does not keep evidence that nothing points at anymore.
What the graph stores
Each Discord server gets its own FalkorDB graph, named with a prefix plus the guild id (Sigma_<guild_id>). Ingest writes the same kinds of facts every time:
- A developer is
ASSIGNED_TOa task. - A task
BLOCKED_BYanother task. The edge points at the work it is waiting on. - A commit
TOUCHESa file. An issueMENTIONSa task. - A document is
STORED_ASa file, and sections hang off the doc. - A Discord message
SUPPORTSa claim, so chat is evidence, not a second source of truth. - A GitHub login is
SAME_ASa developer, so commit authors and Discord names can be the same person.
Full-text indexes on those nodes let a question like "billing" hit docs and chat, then hop back to the people and tasks those nodes connect to.
Questions that are traversals
The bot does not invent a dashboard for each question. The critical path is the longest chain of unfinished tasks:
MATCH p = (:Task)-[:BLOCKED_BY*1..20]->(:Task)
WHERE all(n IN nodes(p) WHERE coalesce(n.status, 'todo') <> 'done')
WITH [n IN nodes(p) | n.id] AS chain, length(p) AS hops
RETURN chain, hops
ORDER BY hops DESC
LIMIT 1
Bottlenecks are PageRank on the same edge. Rank flows toward the open tasks that other open tasks are waiting on:
CALL algo.pageRank('Task', 'BLOCKED_BY') YIELD node, score
WITH node, score
WHERE coalesce(node.status, 'todo') <> 'done'
OPTIONAL MATCH (waiting:Task)-[:BLOCKED_BY*1..20]->(node)
WHERE coalesce(waiting.status, 'todo') <> 'done'
RETURN node.id, node.title, score, count(DISTINCT waiting) AS waiting_count
ORDER BY score DESC
Impact is the other direction: given one task id, which unfinished tasks reach it within 20 hops, and how far away they are. Weakly connected components on Task / BLOCKED_BY split workstreams that can proceed in parallel because nothing in one component waits on another.
Expertise is six walks, then an edge
"Who knows authentication?" does not ask the model to guess from a bio. It ranks developers from six evidence types:
- Tasks they own whose text matches the topic.
- Commits that touch files related to the topic.
- Issues they opened or were assigned.
- Docs and sections they are linked to.
- Chat messages that mention them next to the topic.
- Team membership, so "Priya joined the payments team" changes later rankings.
The result is written as EXPERT_IN edges and then rebuilt on the next ranking pass. The following question can start from those edges instead of re-walking every commit.
Why a graph, for this bot
A vector store would have retrieved the message where someone said the billing API was stuck. It would not have told me that three open tasks wait on that one, that the same person also owns the highest-PageRank node, or that the docs mentioning auth were written by someone who has not touched the repo in a month.
select_graph made multi-tenant isolation boring, which is what I wanted. The API, the Discord client, and the GitHub ingest all call FalkorDB(...).select_graph(name) and run Cypher. There is no separate query service. A local FalkorDB listens on port 6379. A cloud instance uses the host and port from the dashboard, which is often not 6379. Copy .env.example to .env and fill in the Discord token, the Gemini key, and the API keys the bot and the context service share. Do not commit that file.
Two things I still want from the database: errors that name the bad label when algo.pageRank or a full-text index call fails, and vector search beside full-text so keyword hits and embedding similarity land on the same nodes.
Try it
The repo is Sumit884-byte/sigmaAgent. Clone it, install the three requirement files (the API, context retrieval, and discord-bot), start FalkorDB, then:
uvicorn api:app --host 0.0.0.0 --port 8000
uvicorn api:app --host 127.0.0.1 --port 8001 --app-dir "context retrieval"
cd discord-bot && python bot.py
In a server, mention the bot:
- "What is blocked?"
- "Who knows about billing?"
- "Priya will do the frontend"
The first two read the graph. The third writes it.
Top comments (0)