Skip to main content

Why I Built My Family a Private AI Assistant Instead of Handing Them ChatGPT

· AI Alejandro Cantero Jódar

Why I Built My Family a Private AI Assistant Instead of Handing Them ChatGPT

The easy thing would have been to create a few ChatGPT accounts and move on. My family would have had a very capable assistant in about ten minutes, and I would have started paying a subscription per head for the privilege. I did not do that. Over roughly two months and nearly 800 commits I built Lalo instead: a private, self-hosted AI assistant that lives on our phones, remembers who each of us is, and answers only to a server I control.

This is the story of why that trade made sense to me, and an honest look at what it actually costs to make “private” more than a marketing word.

Renting a brain you do not own

When you give someone a login to a hosted assistant, you are not giving them a tool. You are enrolling them in a service. Their conversations leave the house, land in infrastructure governed by someone else’s retention policy, and become one more line item in a business model that is not aligned with them. The model is shared with everyone on Earth, so it knows nothing about my mother’s projects or my own until each conversation re-explains it from scratch. And the whole thing can change its terms, its price, or its personality overnight, without asking.

I have written before about the risk of centralizing our tooling around a single provider and about national efforts to keep AI sovereign . Lalo is the same argument scaled down to a household. If sovereignty matters for a country’s language model, it also matters for the assistant your family talks to every day. The point is not paranoia. It is ownership: our conversations sit on a node I run, under a policy I wrote, and nobody gets to rewrite that from a boardroom.

What “private” actually buys a family

Three things, concretely.

Control over the data. Chats live in a PostgreSQL database on my server. Uploaded files sit on that machine’s disk. There is no third party in the loop reading, training on, or reselling any of it. When someone in my family asks Lalo something personal, that sentence does not travel further than it has to.

Personalization that persists. Lalo has two memory systems. A per-user core memory holds stable facts (your name, your work, your preferences) that get injected into the system prompt at the start of every turn, so it behaves differently for each member of the family. On top of that, a semantic recall system lets it search across your previous conversations: when you say “the project we talked about last week,” it can actually go find it. A rented, shared model cannot do this without you rebuilding context by hand each time.

Radical simplicity. One instance. One database. Local file storage. No queues, no Redis, no horizontal scaling. Because exactly one person maintains it and a handful of people use it, I get to make decisions that would be irresponsible at scale and are exactly right here.

Meet Lalo

Lalo is a PWA you install on your home screen, so it feels like an app rather than a website. I gave it a personality on purpose: a warm science-communicator tone, inspired by the public figure of Eduard Punset , curious and calm, good at explaining hard things in plain language. It is not a product name and not a mascot. It is a first name, because I wanted my family to feel like they were talking to someone, not querying an API.

Lalo's home screen: a warm science-communicator avatar above a Spanish prompt inviting you to ask a question or hand it a task.

Under that friendly surface, though, is a real piece of engineering. This is the part people underestimate: the chat box is the easy 5%. Making it genuinely useful and genuinely private is the other 95%.

Under the hood: what it takes to make it real

Lalo is a Next.js App Router app talking to models through the AI SDK . The interesting parts are not the framework choices, they are the systems you need once a chatbot has to actually do things.

One turn in Lalo: it reasons for a few seconds, calls an image-search tool, renders the photo inline, and then explains, all without leaving the chat.

An agent harness, not a single completion. Each turn runs through a tool-calling loop (the AI SDK’s ToolLoopAgent) with a hard ceiling of 50 steps and a serial turn queue so two messages in the same chat can never interleave and corrupt each other’s state. That queue sounds trivial until you have watched a user fire three messages at a backgrounded PWA and seen what happens without it.

Tools that reach the world, carefully. Web search fans out across providers with fallback (Firecrawl, then Brave, then scraping DuckDuckGo), and page fetching runs behind a full anti-SSRF layer: no private IP ranges, no credentials in URLs, DNS pinned between validation and connection so nothing can rebind to 169.254.169.254 and read cloud metadata. When you let a model make outbound requests on your server, that guard is not optional.

A real computer per chat. For anything involving files (analyze a spreadsheet, convert a deck to PDF, run Python) each chat gets an isolated E2B sandbox: a Linux box with Python, LibreOffice, and a pile of data tooling, mounted at /workspace, destroyed when you delete the chat. The model explores it before acting rather than assuming what is there.

Memory backed by real vectors. Recall is not a gimmick. Conversations are embedded with Mistral’s embedding model into 1024-dimensional vectors and stored in pgvector , and recall runs a cosine-similarity search across your past chats, filtered by a relevance threshold. Same Postgres instance, one extension, no separate vector database.

The unglamorous streaming details. Responses stream over SSE and can resume after the phone backgrounds the app, the network drops, or you navigate away, because the server keeps a buffer of the in-flight stream. A stop button aborts generation on the server independently of the browser closing the connection. There is voice in both directions (Whisper for dictation, Mistral TTS for reading answers), multimodal attachments, push notifications when a long answer finishes off-screen, and scheduled tasks that wake Lalo up on a cron to do something and ping you.

Squeezing the model economics. All three model tiers (fast, medium, smart) are OpenRouter presets, and the app injects explicit prompt-cache breakpoints and sticky session routing so repeated turns reuse a cached prefix instead of paying full price every time. Running your own assistant means you also own its bill, so this matters.

Where it earns its keep: spreadsheets and office work

Some of the people who use Lalo do office work all day: spreadsheets, reports, the slow grind of numbers that have to become something presentable. This is where the per-chat sandbox stops being a nice-to-have and becomes the whole point. Ask Lalo for “a twelve-month sales sheet with totals and an average by formula and a bar chart,” and it does not fake it: it loads its spreadsheet skill, works inside its Linux workspace, writes a real .xlsx with live SUM() and AVERAGE() formulas (not pasted numbers), draws the chart, and hands back a file you can download and keep editing. Upload your own messy export and it will read it, clean it, pivot it, and give it back usable. For a family member who lives in Excel, that single capability outweighs every clever chat answer combined.

Lalo handling an office task: it loads a spreadsheet skill, works in its per-chat sandbox, and builds a real Excel file with formulas and a chart to download.

Cheaper than a stack of ChatGPT subscriptions

Here is the part that surprised me: running Lalo is not only about control, it is genuinely cheaper than paying for the alternative. Two reasons. First, usage is pooled. Instead of a subscription per person, the whole family shares one metered bill, and a household’s real usage is bursty and modest, nowhere near what per-seat pricing assumes. Second, it runs on models with an absurd intelligence-to-price ratio: the tiers currently point to MiniMax M3, which delivers near-frontier quality for a small fraction of the token cost of the big hosted assistants. Fold in the prompt-cache tricks from earlier and the monthly total lands comfortably under what a single ChatGPT Plus seat costs, let alone one per family member.

Lalo's model picker: fast, medium, and smart tiers, each labelled by cost so the running bill stays visible and in your hands.

An internal product that grows itself

Because Lalo is an internal product with exactly one set of stakeholders to please, I get a flexibility no external service can offer. When a family member says “I wish it could do X,” X becomes a feature that week, shaped to precisely how they work, not to a roadmap that has to average a million strangers. It is never “done.” It grows in the direction the family actually pulls it.

It also, increasingly, grows itself. A small pipeline of agents runs on my own machine on a schedule: at night, read-only agents scan the codebase and open issues for bugs, refactors and improvements (capped so the backlog never balloons); a later pass takes the highest-priority ones, implements each in an isolated git worktree, runs the full quality gates, and opens a pull request; a separate agent keeps existing pull requests mergeable by resolving conflicts and fixing red CI. It never merges anything. I review and merge every change by hand. So most mornings I wake up to a short queue of proposed improvements to an assistant that, in a real sense, is helping to build itself.

The trade-offs I chose on purpose

Here is the honest part, the part I think most “I built my own X” posts skip.

Lalo is deliberately a single node, and several of its decisions would fail an interview at scale:

  • The rate limiter lives in memory (per process). Add a second replica and it stops making sense.
  • The SSE resume buffer is also in memory. If the process dies mid-answer, that stream is gone.
  • Uploads are on local disk, so in Docker I have to mount a persistent volume or lose them.
  • There is no admin panel and no public sign-up. I create users from the command line with a script. Administration is me, SSH, and SQL.

None of this is an accident or a corner I did not see. It is the whole design thesis. For one maintainer and a few relatives, a Redis cluster and a multi-region object store would be pure ceremony: more moving parts to break, more surface to secure, more money, for zero benefit anyone in my family would ever feel. Engineering maturity is not always adding robustness. Sometimes it is refusing complexity you do not need and writing down why, so the next person (probably future me) does not “fix” it into something worse. I keep the documentation as the source of truth precisely for that reason: if it ever lies about the system, I treat that as a bug.

Was it worth it?

If you price my evenings, building it was not the rational move: a subscription would have been answering questions in ten minutes. But the moment it exists, the maths flips. The monthly bill comes in under paying per seat, it keeps improving on its own, and it does things (real spreadsheets, private memory, scheduled tasks, its own skills) that no consumer subscription bundles for a whole family.

And the running cost was never really the point anyway. What I got is a thing my family owns. It knows them. It keeps their conversations at home. Its personality, its price, and its rules do not change unless I change them. And in exchange for those two months, I now understand every layer between a typed message and a streamed answer, which is worth something on its own.

Sovereignty is easy to say and expensive to practice. Lalo is what it looks like when you actually pay for it: not a slogan about who should control AI, but a small server that quietly answers to me.

Quick Takeaways

  • Handing your family a hosted assistant rents them a brain they do not own, governed by someone else’s policy and price.
  • A private assistant buys real things: data control, per-user memory that persists, and a bill that stays small.
  • The chat box is 5% of the work. The sandbox, vector recall, SSRF guards and resumable streaming are the other 95%, and that sandbox builds real spreadsheets with live formulas, not just talk.
  • Pooled family usage on cheap models (MiniMax M3) makes it cheaper to run than a ChatGPT seat per person.
  • As an internal product it grows with the family’s needs, and a supervised agent pipeline proposes its own fixes nightly (I still merge every one by hand).
  • Single-node trade-offs (in-memory rate limiting, local uploads, no admin panel) are correct at family scale and wrong at company scale. Choosing them on purpose is the point.
  • Sovereignty is not a slogan. It is a server you maintain and a policy you wrote.

Conclusion

I did not build Lalo because it was the rational economic choice. I built it because I wanted my family’s AI to belong to my family, and because I would rather own the whole stack than rent a personality that can be revoked. If the industry keeps concentrating around a few providers, the most radical thing an individual developer can do is quietly run their own.


If you built a private assistant for the people around you, what would you refuse to compromise on: the privacy, the personality, or the price?

Related posts

Continue reading