I shipped a seemingly small change to Sabine yesterday that's been on my mind for weeks: the Phase 2 classifier is now wired directly into the file upload endpoint.
Here's what that actually means. Before this change, when you uploaded a document to Sabine—a receipt, an email, a product spec—the file went into storage, but the classification step happened separately. Sabine would eventually figure out what kind of document it was, but there was a gap. That gap meant queries like "what did I spend on groceries this month?" might miss recently uploaded receipts because they hadn't been categorized yet.
Why This Was Hard
The classifier itself has been working for months. The challenge was integration architecture. The upload endpoint is a performance-critical path—users expect files to upload quickly. Running a full LLM-based classification pass on every upload could introduce latency or, worse, fail silently and lose classification data.
I considered making it async—upload succeeds immediately, classification happens in the background. But that reintroduces the gap problem. The whole point was to eliminate the window where a document exists but isn't queryable.
The solution was to optimize the classifier itself. I reduced token usage by refining the prompt, added result caching for similar document types, and introduced a fast-path for obvious categories (receipts with currency symbols, emails with headers). Now classification adds less than 800ms to most uploads—acceptable for the accuracy gain.
What Changed for Users
From a user perspective, nothing changed—and that's the point. You upload a file, it's immediately queryable with correct context. No waiting. No manual tagging. The intelligence is just built into the flow.
This is one of those changes that makes the system feel smarter without being flashy. Sabine now knows what you uploaded the moment you upload it. That means better answers, fewer "I don't see that document" responses, and one less thing I have to think about when dumping receipts and emails into the system.
What's Next
This unlocks a few things I've been waiting to build. First, category-specific validation—rejecting uploads that don't match expected schemas for things like receipts or invoices. Second, automatic extraction pipelines—once we know a document is a receipt, we can immediately extract vendor, total, and date without waiting for a query.
The bigger pattern here is moving intelligence upstream. Every time we can make a smart decision at ingestion instead of query time, we reduce latency and improve accuracy. This is the first of several planned changes that follow that principle.
It's not the flashiest feature. But it's the kind of plumbing that makes everything else work better.