A demo takes an afternoon. Keeping a language model useful once real users are hitting it — with costs that do not spiral, answers you can trust, and a way to know when a change made things worse — is a different job, and it is the one I do.
LLM products, shipped
Rafael IA is on Google Play: an assistant that answers construction-site questions and runs the material calculations behind them. I also built a nutrition assistant on Gemini that reads a photo of a meal and returns its nutritional breakdown, and transcribes a spoken description when the user would rather talk than type.
Guardrails where the answer must be right
A model that improvises a concrete mix is worse than no app at all. So in Rafael IA the arithmetic is constrained rather than generated: the model handles the conversation, deterministic code handles the numbers. Knowing which half is which is most of the design work.
Measured, not vibed
Prompts under version control, structured output the application can actually rely on, cost tracked per request, and an eval set that tells me when a prompt change made accuracy worse instead of better. Without that last one you are not improving a system, you are redecorating it.
Vision, and knowing when not to store something
In Cidade Cidadã, every photo of a street problem passes through automatic blurring of faces and licence plates before it is ever written to storage. A public complaint feed that quietly becomes a surveillance archive is a failure of engineering, not of policy.
Claude in the daily loop
I work with Claude Code every day, and it is the reason I can quote a fixed price and mean it. This site — three languages, a quote configurator, a build pipeline — was built that way. It does not replace knowing what the code should do; it removes the hours between deciding and having it.
Providers
Claude, Gemini and OpenAI. I build the provider behind an interface so swapping one out is a configuration change, not a rewrite — the pricing and the leaderboard both move too fast to marry any of them.