Work
Two of these I am paid for and still run today. Client and product names are left out on purpose. The numbers are not, and I am happy to walk through any of them on a call.
Document-AI platform
2025 to nowAI engineer
Classifies and splits scanned German occupational pension paperwork. Multi-tenant, Azure, queue-driven.
A few hundred scanned pages arrive as a single PDF. The pipeline has to work out where each document ends, decide which of 54 types it is, and pull the fields out of it. Then it has to do that for several tenants who are not allowed to see each other’s data.
I own the AI half and most of the backend underneath it: the DSPy pipeline, the evaluation harness, the cost telemetry, the Azure Functions that run the whole thing, and the Postgres that pushes live updates to the front end through LISTEN/NOTIFY instead of a Redis nobody wanted to operate.
Most of the job is making a non-deterministic system safe enough to deploy on a Friday. That means an evaluation harness whose tests still hold when the model answers differently twice in a row.
- 54 document types, 438 tests running in CI.
- Cut inference cost 5.7× per document by designing around a cheaper model instead of buying a better one.
- Shipped the cheaper pipeline over a more accurate ensemble that cost 40% more and added 170 seconds of latency per document.
- Contained a DSPy major-version break and a compromised litellm release inside an hour each, before either reached a user.
Python · DSPy · GPT-4o vision · Azure Functions · FastAPI · PostgreSQL · Docker · GitHub Actions
Real-estate AI platform
2026 to nowAI technical lead, only engineer
A CRM, a public listings site, and sales agents that answer on WhatsApp and by voice. I am the entire engineering function.
The company sells property and had no engineers. Staff worked across seven or so tools that did not talk to each other, and the sales team answered the same handful of questions on WhatsApp until midnight.
I built the replacement and I still run it. Twenty API services and eighteen data models behind row-level multi-tenancy, per-tenant encrypted credentials, WebSockets for the live views, FastAPI and Celery in Docker. On top of that sit the agents: WhatsApp and inbound voice, Claude for tool use, Deepgram and ElevenLabs on the phone side, qualifying leads and booking viewings at 2am. Anything a customer can act on is bounded in code rather than in a prompt.
The rest is plumbing that non-technical staff never have to think about. Two-way Microsoft 365 and SharePoint sync over the Graph API, generated listing copy, auto-publishing to the public Next.js site, and ad performance from several platforms collected in one place.
- 20 API services and 18 data models, row-level multi-tenant, per-tenant encrypted credentials.
- Replaced roughly seven manual tools for a company with no other engineers.
- Migrated a WordPress property database that kept about 90% of every record inside one serialized PHP blob.
- Moved the live domain, and the Microsoft 365 mail riding on it, between registrars with no downtime.
- Absorbed a Meta WhatsApp API migration and a voice-stack rewrite without users noticing either one.
Python · FastAPI · Celery · PostgreSQL · Next.js · Claude tool-use · WhatsApp Business API · Deepgram · ElevenLabs · Microsoft Graph · Docker
Supportly
2026Personal project
A retrieval-augmented email assistant that drafts replies from your own past threads.
Gmail in, retrieval over your own history, a draft out. DSPy runs the multi-stage pipeline on Llama 3 70B through Groq, Qdrant holds the vectors, FastAPI and Next.js hold everything else.
It is in the portfolio for how it failed. Three weeks of fluent, confident drafts built on embeddings that were random numbers will change how you write tests.
- Ran three weeks on random-number embeddings before anyone noticed, because the drafts still read as confident.
- That failure is the reason the project now asserts on retrieval quality instead of on response shape.
Python · DSPy · Qdrant · Groq · Llama 3 70B · Gmail API · FastAPI · Next.js
Open source
2026Fixes to projects I run myself, which is the only reason I found the bugs.
Both of these are small patches to the kind of bug that does not announce itself: one crashes at the last possible moment, the other never crashes at all and pays the wrong people.
- Chutes: passing a Pydantic model class as an output schema stored the class object itself, so deploying crashed on JSON serialization. Converted at construction, with a fallback handler behind it. Merged.
- Macrocosmos data-universe: miners could inflate their job coverage rate by uploading parquet files with zero rows, because coverage counted file paths rather than content. Coverage now requires at least one row. Open.
Python
Earlier
About a year of freelance and contract work came before this. A crypto-exchange platform with real-time pricing, KYC and fiat-to-crypto rails. Fine-tuning smaller models for client applications. ML and AI workshops that reached more than 50 students.
Further back there is a GPT-2 implementation written from scratch, with its own tokenizer and distributed data parallelism, plus a Socratic tutoring app, a PDF question-answering bot, and a malware classifier built on LSTM and BERT variants. The code is on GitHub if you want to read it. That last group is student-era work and I would not put it forward as evidence of anything I do now.