How We Won at Botathon 2026: The FileMind Story
Top 5 in the Apify track, Top 10 in the Superplane challenge, a bag full of goodies, $100 in API credits, and a project I am genuinely proud of. Botathon 2026 was one of the more memorable things I have done this year, and FileMind is the reason why.
This is the story of what we built, how close we came to not finishing it, and how Shashank saved the whole thing in the final hours.
The Problem We Wanted to Solve
Every codebase investigation tool I have used does the same thing: pre-index everything into vector embeddings, then run similarity search when you ask a question. The answer comes back fast, but you have no idea how it got there. You get a file path and a confidence score and you are supposed to trust it. When the embedding is stale or the similarity threshold is slightly off, the answer is just wrong, quietly.
We wanted something different. Instead of pre-indexing, what if the agent navigated the codebase the same way a senior developer actually would? You start at the root, look at the structure, read the files that seem relevant, grep for the thing you care about, follow imports to their definitions. Every step is visible. Every decision is traceable. Nothing is pre-computed and nothing goes stale.
That idea became FileMind.
Four Phases, Three Completed
Shashank and I sat down before writing a single line of code and mapped out four phases. Phase one was the core agent loop with the five primitive tools: tree, read, grep, jump, and summarize. Phase two was the session layer and the import graph that makes jump actually useful. Phase three was the frontend with real-time SSE streaming so you could watch the agent think. Phase four was the external integrations: Apify for pulling in remote repositories and Superplane for the sponsor integration layer.
I took phases one through three. That was already a lot of ground to cover and I moved through it faster than I expected in some places and much slower in others.
The Parts That Actually Hurt
The agent loop itself came together relatively cleanly. Claude Opus 4.5 with tool use running up to 25 iterations, picking one or more tools per iteration, updating state, emitting events. The architecture is not complicated. Getting it to behave reliably was a different matter.
The first real wall I hit was SSE. Server-Sent Events should be simple: open a connection, stream newline-delimited JSON, close when done. Except Express and Next.js have opinions about buffering, proxies have opinions about timeouts, and browsers have opinions about reconnection. I spent more time than I want to admit getting the stream to actually flush in real time instead of batching everything and dumping it at the end. The fix was straightforward once I found it, but finding it took way too long.
The import graph was the other place I got stuck. The idea is that every time read parses a file, it extracts imports and exports and wires them into a graph. Then jump can do instant go-to-definition without re-reading anything. That sounds clean. In practice, resolving import paths consistently across different module systems, handling re-exports, and making sure the graph stayed coherent as the agent read more files was finicky work. I had a version that worked for simple cases and broke in subtle ways on anything more complex.
Then there was the session state. I wanted every update to be immutable, so the agent could always reconstruct what it knew at any point in time. That meant being very deliberate about never mutating a FileRecord or a session object in place. Every change produces a new object. It sounds like extra work for no reason until you are debugging a multi-step agent loop and you can actually replay state at any step because nothing was modified in place.
Getting the Haiku summarization cache right was also more annoying than expected. The idea is that summarize calls Claude Haiku 4.5 and stores the result on the FileRecord. If you summarize the same file again you get the cache. Simple enough. The issue was making sure the cache key was stable and that the caching did not accidentally serve a summary from a different file when paths had trailing slashes or different relative forms. Small thing but it took a debugging session I did not budget for.
The Breaking Point
By the time I had the first three phases working end to end, I was at my limit. The core agent was solid. Streaming worked. The frontend was showing live tool calls. But phase four, the Apify integration for remote repos and the Superplane sponsor layer, was still completely untouched. And we were running out of time.
That is when Shashank stepped in.
I handed off what I had and he just took it from there. He wired up the Apify actor to pull remote repositories on demand, which is genuinely one of the more interesting parts of the project because it means FileMind can investigate a codebase it has never seen before without you cloning anything locally. He got the Superplane integration in. And then he deployed the whole thing to Vercel and got it live.
Without that final push we would not have had a complete project. We would have had a good demo with a gaping hole where the sponsor integrations were supposed to be. Shashank clutched it.
How FileMind Actually Works
The full stack is a Next.js frontend talking to an Express server over HTTP and SSE. The Express server exposes a handful of routes: a blocking POST /query endpoint, a streaming GET /query/stream endpoint, a session lookup endpoint, and a health check. The streaming endpoint is the interesting one because it lets you watch the agent work in real time.
Browser (Next.js :3000)
|
| HTTP / SSE
v
Express Server (:3001)
|
v
FileMindAgent (Claude Opus 4.5 + tool use)
|
tree read grep jump summarize
|
Claude Haiku 4.5
(cached per file)
The five tools are the interesting design decision. tree gives the agent a structural overview without reading anything. read returns file content and automatically updates the import graph as a side effect. grep does pattern search across the codebase. jump uses the import graph to navigate to a definition instantly. summarize calls Haiku and caches the result. Every single one of these steps shows up in the SSE stream so you can follow exactly what the agent is doing and why.
The alternative, the embedding approach, would have been faster to build. You pre-index, you query, you return results. But you lose the audit trail entirely and you are always fighting staleness. Navigating on demand is slower on the first query to a codebase, but the answers are grounded in what is actually in the files right now.
What Winning Feels Like
Top 5 in the Apify track. Top 10 in the Superplane challenge. A bag of swag and $100 in API credits. Those are still results I am genuinely proud of, and the goodies did not hurt. More than the placement though, I came out of Botathon with a project that actually works and a cleaner idea of how to build agentic systems that are auditable by design rather than as an afterthought.
The thing that stuck with me most is how much the team dynamic mattered. I planned and built the core. Shashank finished what I could not. Neither of us would have gotten there alone. That feels like the honest takeaway from the whole experience.
You can try the live demo at botathon-nine.vercel.app.
