A personal AI agent with a face — and the face grows itself: new skills declare their own dashboard tabs.
I run an AI agent around the clock on a Mac mini — morning briefings, food and macro tracking, shopping lists. It worked, but everything lived in Telegram, and chat is a terrible place to read state: yesterday's grocery list is forty messages up. So I gave the agent a backend and a web face — Charlos. Commands still arrive by chat; what the agent knows lives on a screen built for reading.
Chat writes, dashboard reads: a Telegram command lands in the DB, and the dashboard renders from the same source of truth — briefings, meals, lists, each with direct CRUD on the web side.
Deterministic core: skills compute and CRUD in plain code — the LLM parses intent, it never does the math.
Skills declare their own UI: each new skill maps onto a fixed set of panel types, and its dashboard tab renders from that definition — no hand-built screens per capability. Deterministic end to end: the LLM parses intent; it designs nothing.