← Work

Case study · Live — Web; iOS in review

Agence

Twelve agents, one ranked insight feed.

Agence screenshot

Agence is a personal finance and investing app. Twelve analysis agents read your bank, budget, and brokerage data, and an LLM judge ranks what they find into one feed of the things actually worth your attention.

The problem

Spending, budgets, debt, taxes, savings goals, and a brokerage account usually live in different tools. Each shows its own numbers, and working out which one matters today is left to you.

How it works

Bank accounts link through Plaid, and brokerage accounts link directly or read-only through Plaid. Twelve agents run over that data: spending, anomalies, recurring charges, budgets, goals, debt, taxes, portfolio, market context, watchlist, autopilot, and a cross-domain agent for patterns that span more than one account.

Their output goes to an LLM judge that scores every insight and streams back a single ranked feed. Around it sit a chat assistant that answers from your real data, budgets and goals, shared households, and rule-based trading automations.

Engineering decisions

  1. Agents are pure functions

    Each agent takes user and market data and returns insights — no database calls, no API calls, no side effects. All twelve carry property-based tests, and mutation testing checks those tests actually catch regressions.

  2. One failing agent can't sink the feed

    Every agent runs inside its own guard, so bad data from one provider drops that agent's insights instead of taking the whole feed down with it.

  3. A judge, not a summarizer

    The model scores each insight from 1 to 5 on actionability, urgency, cross-domain relevance, and confidence, then ranks by the total. An agent's own severity is a floor the judge can't lower, and if the model is unavailable the feed falls back to unscored insights rather than failing.

  4. AI consent enforced on the server, failing closed

    Most model calls run automatically — feed refreshes, briefs — not from a button press, so a consent prompt in the UI couldn't cover them. The server checks consent before every call and refuses by default.

  5. Grounding through structure, not prompt rules

    The chat assistant has to look figures up through tools instead of recalling them, reads tax limits from a table, and does arithmetic with a calculator tool instead of in generated text.

  6. SQL quarantine, enforced by a test

    Every query lives in one module, and a test checks that each query on a per-user table filters by the user — so a missing ownership check fails the test suite instead of leaking data.

  7. Guardrails on real money

    Paper and live trading are set per linked account, and live trading requires explicit consent. On live accounts, automations only notify — you confirm every trade — and the chat assistant can place orders on paper accounts only.

Stack

Frontend
React 19, Vite
Native
Capacitor (iOS + Android)
Backend
Node.js, Express
Database
PostgreSQL
Hosting
Vercel (web), Render (API + database)
Data
Plaid, Finnhub, Alpha Vantage, FRED, SEC EDGAR
AI
Anthropic Claude
Billing
Stripe (web), RevenueCat (app stores)
Testing
Jest, Supertest, fast-check, Stryker, Playwright