Inspiration
Small businesses are horizontal organizations. The owner wears nearly every hat. Working with small business owners, I noticed they spend most of their time on day-to-day operations, since the urgent work is what keeps the business alive. That leaves little to no time for important tasks like admin.
One gap I kept running into was document organization. Solutions exist, but they take time to learn and set up, and that time is scarce for owners who are already doing everything themselves.
So we created Buz, a Business Agent that works in the background. It receives messy, unorganized documents like invoices and receipts, classifies and validates them, and stores them in a structured database. At the end of the month, the owner can hand those records to their CPA for accounting and tax purposes, or use them to better understand their numbers.
The goal is a ready-to-use, frictionless solution that starts working just by chatting.
What it does
Buz helps small business owners organize their documents and handle routine admin. Users can chat with it or email documents in. It reads invoices, receipts, images, and PDFs, then stores the results in a structured database. A few specialized agents share the work:
Router Agent. Reads the request and any attached image, PDF, or audio against the business’s registered clients, suppliers, and profile, and classifies it into a concrete operation.
Validator. Runs deterministic checks before anything is written. It confirms required fields are present, re-sums line items for invoices and quotes against the declared total, and recalculates purchase order totals, so we never rely on the language model to get the math right.
Executor Agent. Carries out the validated operation: writes records to the database, generates PDFs, and prepares companion email drafts (for a quote or purchase order, for example) for the owner to review.
Knowledge Agent. Runs in the background and extracts relationships between business entities, such as a client ordering a product, into a queryable knowledge graph. It supplements the relationships the Executor already writes directly.
Trust boundary. If the model is unavailable or both model tiers fail, Buz does not guess. It returns a predefined clarifying question and flags degraded mode. This is enforced in the model-calling layer, not by a prompt: a failed structured call raises an exception the Router must catch, and the fallback is hardcoded. The same rule applies to emailed invoices. If one is missing information or fails validation, Buz notifies the owner and skips it instead of writing uncertain data.
How we built it
Model layer. Gemini through the @google/genai SDK via Agent Platform. Structured calls (Router and Knowledge Agent) use JSON output with no tools attached, because Gemini does not support combining JSON output with tool use in our configuration. Advisory answers and knowledge queries use a separate freeform mode with Google Search grounding. Structured calls run through a two-tier model fallback before reaching the failure handling above.
Pipeline. One flow, Router → Validator → Executor → async Knowledge sync, shared by the chat interface and the inbound-email webhook. A typed message and an emailed invoice get the same processing and validation.
Data. Google Cloud Firestore holds typed records for clients, suppliers, quotes, purchase orders, invoices, accounting entries, email drafts, generated PDFs, entity relationships, business profiles, notifications, and chat sessions.
Documents. PDFs are generated with pdf-lib. A lightweight Markdown-style parser handles headings, dividers, and bullets, and a text sanitizer normalizes smart quotes, dashes, and other non-ASCII characters so the standard Helvetica font never renders broken text.
Integrations and deployment. Resend receives inbound invoice emails. Email drafts are saved in the workspace for review. The app is a Next.js 16 standalone bundle, built with a multi-stage Docker build and deployed on Google Cloud Run.
Challenges we ran into
What to do when the model fails. A happy path is easy to build, but a business agent needs a predictable failure path that never creates a wrong record. We made callStructured raise a dedicated StructuredCallFailure when both model tiers fail, so every caller has to handle it. For the Router, the only allowed fallback is a predefined clarifying question, never another model-generated guess.
Plausible is not correct. A successful model response doesn’t guarantee its numbers add up. We added deterministic checks that recalculate totals from line items before execution. Coverage isn’t complete yet, and extending it is on our roadmap.
Deciding what the Knowledge Agent should store. Extracting relationships after every interaction sounds useful, but not every interaction adds knowledge, and some facts were already recorded by the Executor. We had to separate what adds context from what duplicates a record.
Accomplishments that we’re proud of
Getting the whole agent pipeline working as one system, from routing a request to validating it, executing it, and syncing relationships in the background. The chat interface and the unattended inbound-email webhook share that pipeline, so there is no separate logic per entry point.
Making validation part of execution, not an optional step. Totals are recalculated before records are written, and when Buz can’t safely process an emailed invoice, it notifies the owner and skips it.
Going beyond a chat that answers questions. Buz records invoices, generates PDFs, prepares email drafts, and ingests emailed documents, the beginnings of a workflow that handles real admin tasks. And it all lives in one simple interface, so an owner or admin worker can get started right away without learning a new system.
What we learned
More agent activity is not more value. Extracting a relationship after every interaction felt like it would build more context, but it sometimes created a second, blurrier copy of something the Executor had already recorded precisely. That led to the Knowledge Agent’s skip-list. Memory needs to be selective.
Clear responsibilities make failures easier to trace. The Router interprets, the Validator checks, the Executor acts, and the Knowledge Agent learns in the background. When each handoff is predictable, it’s easy to see where something went wrong.
Keep interpretation separate from verification. A model’s answer can look right and still have missing fields or bad arithmetic. Deterministic validation after the model gives us a reliable way to catch both.
What’s next
Memory and context engine. Expand the Knowledge Agent beyond per-interaction extraction into a persistent, queryable memory the Router can use directly when classifying new requests.
Pricing. We’re deciding between a flat subscription and credit-based usage. Our working hypothesis is flat, based on what we believe small businesses prefer. If it holds, token efficiency (trimming prompt context, tightening model-tier selection) becomes a near-term priority.
Native mobile apps for iOS and Android.
Expanded validation. Extend the deterministic math audit to the intents that currently bypass it.
Built With
- firestore
- gemini
- genai
- google-cloudrun
- nextjs

Log in or sign up for Devpost to join the conversation.