Skip to main content
Open Source · AI

docu-ai-flow

A .NET 10 Worker Service that watches a folder, extracts PDF invoice data via Google Document AI, persists it in SQLite, and sends quarterly ZIP archives to your tax advisor by email. What makes it singular: every development phase was planned and executed by a Claude Code agent flow — orchestrator, planners, coders and reviewer — following strict TDD.

The problem

Managing supplier invoices is repetitive manual work: downloading PDFs, opening them one by one, copying data into a spreadsheet, sending everything to the advisor each quarter. One mistake at any step means incorrect tax filings. I needed a system that did this work automatically — and that would also serve as a real-world test bed for an AI-assisted development workflow.

The solution

  • Folder watcher

    Detects PDFs in ./data/inbox/ in real time. A filesystem watcher plus a polling fallback guarantee no invoice is ever missed. A concurrency gate prevents processing the same file twice.

  • AI extraction

    Google Document AI (Invoice Parser) extracts supplier, tax ID, invoice number, date, net amount, VAT and total as typed fields, behind a single IInvoiceDataExtractor port. The LlamaParse adapter is kept as a reference. A configurable confidence threshold automatically discards uncertain extractions and moves them to ./data/failed/.

  • Excel export

    ClosedXML generates a quarterly Excel file with native types — real dates and numbers ready to sort, filter and sum. A cumulative master spreadsheet is regenerated on every new invoice.

  • Advisor dispatch

    Resend packages the quarter's PDFs into a ZIP and emails them to the tax advisor. If the ZIP exceeds Resend's 40 MB limit, it splits automatically by month and sends one email per part.

Tech stack

Backend

  • .NET 10
  • C#
  • Hexagonal
  • Result/Error
  • SQLite
  • Google Document AI
  • Resend
  • Polly

Tests

  • xUnit
  • NSubstitute
  • WireMock.Net
  • NetArchTest

AI Workflow

  • Claude Code
  • Agents
  • Skills
  • TDD

Technical decisions

  • Hexagonal architecture

    Google Document AI, SQLite, the file archiver and Resend are swappable adapters behind interfaces (ports). Application use cases know no implementation detail. A NetArchTest architecture test enforces these boundaries on every build.

  • Swappable extraction

    The extractor started out as LlamaParse, but its accuracy fell short. Swapping it for Google Document AI was a single line in the composition root: the domain, the use cases and the pipeline tests were left untouched, because they depend on the IInvoiceDataExtractor port, not the provider. LlamaParse stays in the repo as a proof-of-result, with its contract tests still green.

  • Result/Error for business failures

    A low-confidence extraction, incoherent total or missing invoice number is an expected business case, not an exception. Result<TValue, TError> expresses it as a return value. Exceptions are reserved for transient failures — API down, disk full — which Polly retries automatically.

  • Built with Claude Code agents

    Every feature followed the same cycle: the orchestrator explored and debated the approach, planner-backend designed the architecture, coder-backend implemented in TDD, and reviewer audited against the approved plan. The result: consistent code and a commit history that tells the story of every decision.

Built with Claude Code

The project is also an experiment in how to organise AI-assisted development. The agents and skills live in .claude/ and are part of the public repo.

  • Orchestrator

    Coordinates the full flow: explore, debate, plan, implement, review. No phase starts without explicit human agreement. The plan lives in workflow/ and moves through plans/ → in-progress/ → reviewing/ → done/.

  • Specialised agents

    planner-backend designs the architecture and contracts; coder-backend implements in strict TDD; reviewer audits against the approved plan. Each agent has its own system prompt under .claude/agents/.

  • Reusable skills

    Markdown skills loaded at session start: commit.md defines the commit format, tdd.md encodes the Red-Green-Refactor cycle, orchestrate.md the full orchestration flow.

  • AI-assisted TDD

    Every feature starts with a failing test. The coder writes the minimum code to pass, then refactors. 111 tests across three layers: Domain (pure), Application (use cases with NSubstitute doubles) and Integration (SQLite, Excel, zip, watcher, mapper golden-master and an end-to-end pipeline driven by a fake extractor).

Interested in the AI workflow?

The repo is public. The agents, skills and orchestration flow are in .claude/ alongside the source code. Use them as a template for your own projects.