Case study · Live — Web; iOS in review

Agence
Twelve agents, one ranked insight feed.

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
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.
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.
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.
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.
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.
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.
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