Case Study · 2025 · Live
Personal Finance Intelligence Agent
An AI agent for your own money. Log spending in plain language, in dollars or pesos. It tracks budgets in real time, warns before you overspend, and answers questions about where the money went. A deterministic TypeScript core does every calculation, so no figure it shows was ever guessed by a language model.
- Role
- Solo: design & build
- Stack
- Next.js 16 · TypeScript · Supabase / Postgres · Claude
- Evidences
- Ships: live, in daily useAI: plain language in, tested code outRigor: the model never does the math
- in daily use, on Vercel
- Livein daily use, on Vercel
- numbers computed by the model
- 0numbers computed by the model
- currencies, one USD source of truth
- 2currencies, one USD source of truth
- tests on the money core
- 71tests on the money core
Demo
See it run: capture, convert, warn, answer.

Recorded against seeded demo data. Every number on screen is fabricated. The peso purchase converts at the rate snapshotted when it was logged. Every figure you see was computed in TypeScript, not by the model.
Problem
Budgeting is tedious. And AI can’t be trusted with the math.
I arrived in the US as an international master’s student in August 2025. A new currency, a budget to rebuild from scratch, unfamiliar costs everywhere. Every budgeting app I tried meant forms, dropdowns and manual categorizing. Pay for the app, still do the work.
The obvious fix is to type what you spent and let AI handle the rest. A few apps do this. But they lean on the language model for everything, including the arithmetic.
That’s the catch. LLMs are excellent with words and unreliable with numbers. Nobody should trust hallucinated math with their money.
Approach
The model handles language. Code handles every number.
The agent splits cleanly in two.
A language layer (Claude) turns “$200 pesos en tacos” into structured meaning (amount, currency, merchant, category) and answers questions in plain English.
A deterministic core (TypeScript) does all the money math: sums, budget variance, currency conversion, projections. The model never computes a number, so every figure is reproducible and testable.

Architecture
One request, two layers, a clean handoff.
"$200 pesos en tacos"
│
▼
┌─────────────────────────────────┐
│ LANGUAGE LAYER · Claude │
│ reads & explains, │
│ never does the math │
└────────────────┬────────────────┘
│ amount · currency · merchant · category
▼
┌─────────────────────────────────┐
│ DETERMINISTIC CORE · TS │
│ sums · variance · FX · │
│ projections: all the math │
└────────────────┬────────────────┘
▼
┌─────────────────────────────────┐
│ POSTGRES · per-user RLS │
│ one row per purchase │
└─────────────────────────────────┘Words become structured data in the language layer. The core takes it from there and owns every calculation. Each purchase is one row, isolated per user by Postgres row-level security, so a report you ran last month reproduces exactly today.
What it does
Type a purchase. Get answers.
- Log spending in plain language, in dollars or pesos.
- Automatic categorization. Budgets that update as you spend.
- Overspend warnings before you blow the budget, with end-of-period projections.
- Ask “how much on dining this month?” and get a grounded answer: computed by code, phrased by the model.
Engineering rigor
Trustworthy by construction.
- Money is never a bare number. Every amount carries its original currency, a USD conversion, and the FX rate snapshotted at log time. Last month’s report still reproduces today.
- A pure, testable core. The money engine takes the clock and the time zone as arguments and never reads them itself, so budget periods, conversion and pace projections are covered by 71 headless tests rather than trusted.
- Per-user isolation by Postgres row-level security, with allowlisted Google sign-in. The access boundary is a database policy, not middleware someone can forget.
- Ten decision records covering the genuinely contested calls: the currency model, the fixed budget envelope, and why the language model stays away from the arithmetic.
Go deeper