
The problem
I was earning a salary every month and had no idea where it went. I wanted visibility, but I knew how finance apps usually end: you install one, use it for a few weeks and forget it exists. Choosing where to track was only half the problem. Sticking with it was the other half.
The idea: fit into a tool I already use
I changed the question. The system had to be compatible with what I already use every day. I open Telegram all day anyway, so the whole tracker lives there. I text a message like "lunch 850", in Darija, French or English, and it is logged in my own database. I can also ask questions about my money in the same chat.

Technical depth
Capture: free text to structured data
A Gemini model in JSON mode turns each message into a record with a date, type, category, amount and a short description. The prompt copies category names from a closed list character by character, and anything that is not clearly about money returns an IGNORE flag instead of a guess. That keeps the table clean enough to run analytics on without any cleanup step.
Pay cycles instead of calendar months
My month starts on payday, not on the 1st. Each record gets a financial month and a financial year, computed in a code step, and every cycle question filters on both columns together. The advisor also knows how far into the current cycle we are, so it flags a half-finished cycle instead of comparing it to a complete one.

Intent routing
Before anything touches the database, a first model classifies the message into one of four intents: small talk, advice that needs no data, a data lookup, or a data question that also needs advice. A router sends only the last two to the database. The intent flag also tells the advisor how to answer: numbers only for a lookup, numbers plus advice and the user profile for the rest.

Conversation memory
Each user gets a window of recent messages keyed by their Telegram id. The router keeps a short window and the advisor a longer one, so follow-ups like "and last month?" work without repeating the context.
Safeguards
- Closed category list: the model cannot invent categories.
- Non-money messages are ignored, so chit-chat never becomes a record.
- Query guard: model-written SQL is checked for destructive keywords such as DROP, DELETE and UPDATE before it runs.
- Readable errors: database and network failures are mapped from Postgres, PostgREST and HTTP codes to a clear message.
- Clean output: replies are stripped of markdown so they render properly in Telegram.

The advisor
The advisor answers in the language the user writes in, shows amounts with thousands separators and leads with the numbers before any insight. It checks the SQL and its description before drawing a conclusion, and it divides multi-cycle totals before comparing them to monthly income.

Skills used
- Workflow automation with n8n, webhooks and the Telegram Bot API
- LLM prompt design: structured JSON output, closed vocabularies, intent classification, system prompts for an advisor
- PostgreSQL on Supabase: schema design, SQL, RPC functions
- Text-to-SQL with guardrails and error handling
- Conversation memory design and multilingual input (Darija, French, English)
- Data modelling for non-calendar periods
- Product thinking: reducing friction so people keep using the system
Value for a company
- Adoption comes from low friction. Data only exists if people enter it. Putting capture inside a tool people already open all day is how I kept it going for a year, and the same idea applies to expense reports, field notes or support logs.
- Free text becomes structured, analysis-ready data. A closed vocabulary and an ignore rule produce clean tables without manual cleanup.
- Numbers for non-technical people. Anyone can ask a question in plain language without knowing SQL, and the access path is guarded.
- LLM features that are safe to ship. Intent routing, query checks and error handling are the pieces that turn a demo into something dependable.
- Fast, low-cost build. Low-code orchestration plus a managed Postgres took a working system from idea to daily use quickly.
A natural next step is the same pattern for solo entrepreneurs and small shops that have no time for accounting software, using a chat they already use every day. That is an idea I want to explore, not something I have built.
Results
I used it for a year. At my yearly review the data answered three questions I could never answer before: which categories drain my bank account, how my spending splits across them, and how to lower my costs and where. For the first time I was not guessing.
What I would improve next
- Compute totals and percentages in SQL and let the model only explain them, because language models can slip on arithmetic.
- Filter every generated query by user and use row-level security instead of a broad service key, so the advisor is safe for several users.
- Replace the keyword blocklist with an allow-list or parameterised read-only queries.
- Apply each user's own pay-cycle day in the cycle logic, which today is fixed in code.
- Add an audit log and automated tests for the prompts.