Clawdia: The AI Assistant That Texts You Security Reports at Breakfast
Building an AI home assistant on UbuntuClaw with local LLM inference, Piper TTS, Whisper ASR, and WhatsApp integration. Because your network anomalies deserve a Welsh accent.
The most useful thing an AI lab can do is tell you something you didn’t already know. For most assistants, that means answering questions when you ask them. For Clawdia - the lab’s AI assistant running on UbuntuClaw at 172.16.50.2 - it meant sending me an unprompted morning voice note about what happened on the network overnight, in a Welsh accent, over WhatsApp.
It’s less unhinged than it sounds. Here’s how it worked.
The Architecture
Clawdia ran on NanoClaw (an OpenClaw fork), a self-hosted assistant framework built for home labs. The UbuntuClaw VM ran five services:
- NanoClaw (
nanoclaw.service) - the agent runtime - Piper TTS - local neural text-to-speech for voice replies
- Whisper ASR on port 9000 - local speech-to-text for incoming voice notes
- WhatsApp Bridge - messaging transport
- Home Assistant MCP -
stdioMCP server wrapping the Home Assistant REST API
The LLM backend was the local vLLM instance serving Gemma4-26B in WSL2 at http://172.16.50.5:8000. Queries stayed inside the house, there was no cloud API key to rotate, and time-to-first-token sat around 800ms even if the internet was down.
Piper TTS: The Voice Layer
Piper is a fast local neural TTS engine with a wide catalogue of voice checkpoints. I tested five of them:
en_GB-cori-high- Welsh female (Clawdia’s default)en_GB-alba- Scottish femaleen_US-lessac-high- American maleen_US-ljspeech-high- neutral American femaleen_GB-jenny_dioco- Irish female
I picked the Welsh voice after an evening of side-by-side listening tests. Once you’ve heard a polite British Isles accent deliver “Your Synology NAS SMART health check has returned no errors”, it’s very hard to go back to a flat American synth voice. That’s completely subjective and I stand by it.
Piper runs locally on CPU with sub-100ms synthesis for short replies, and the resulting audio goes straight out through the WhatsApp bridge as a voice note.
Whisper ASR: Listening
OpenAI’s Whisper model (running locally on port 9000) handled the reverse path. Whenever I sent a voice note from my phone, Whisper transcribed it to text and handed it to NanoClaw, which sent the reply back through Piper as audio.
That gave me a hands-free voice assistant on my phone with zero smart-speaker microphones in the house and zero audio leaving the LAN.
The Daily Security Summary
The feature I used the most was the daily 12.15pm AEST network summary. A systemd timer fired a simple five-step job:
- Fetch today’s discovery JSON from the KaliLinux VM (
http://172.16.50.4:8080/scan_YYYY-MM-DD.json) - Fetch yesterday’s JSON for comparison
- Pass both to the local Gemma4-26B model to summarise the diff in plain English
- Render the summary as a Piper voice note (
en_GB-cori-high) - Send it to WhatsApp
A typical message sounded like this:
“Good morning. Overnight network scan complete. 63 hosts responded, up one from yesterday. The new host on the IoT VLAN has an Espressif MAC address - likely an ESP32 device. Four hosts from the previous scan did not respond: these appear to be laptops that have been powered off. No unexpected services detected on the VM estate. The Synology NAS and Juniper switches are responding normally. Weekly GVM scan scheduled for Sunday.”
The whole run took about 15 seconds from timer trigger to phone notification. On three separate occasions it caught a host that didn’t belong - once a neighbour’s phone that briefly hopped onto the wrong SSID before I locked it down, once an IoT gadget that landed on the main VLAN instead of the IoT VLAN, and once a mystery MAC that vanished before I got home and never came back.
Home Assistant Integration
Clawdia also talked to Home Assistant through a small stdio MCP wrapper (ha-mcp-stdio.js) over the Home Assistant REST API:
- “Turn off all the lights downstairs” - one message, no app menus
- “What’s the temperature in the comms cupboard?” - reads the rack sensor
- “Is the front door locked?” - checks the lock entity state
Because it used the same MCP protocol as the network servers, checking a light switch and checking a firewall rule looked identical to the agent.
The Service Account Design
The assistant’s Linux user on UbuntuClaw is a local account rather than an Authentik LDAP account. That’s deliberate: if DebIdentity is rebooting or LDAPS is unreachable after a power outage, the assistant service still needs to come up cleanly at boot so it can tell me what’s broken.
Local user, Docker group membership, no sudo.
The Use Case: Ambient Awareness
The whole point of this setup is keeping an eye on a busy home network without spending my evenings staring at dashboards. A 20-second voice note on a messaging app I already have open tells me if anything shifted overnight without opening a browser.
Update - August 2026
Clawdia is gone. I deprecated her on 11 June 2026, a month after writing this post, and purged the stack on 8 July.
Her replacement is Homer, a Hermes Agent instance running in Docker on the same VM. I planned to run the side-by-side evaluation for two weeks and called it on day one - not because Hermes was ten times smarter, but because its scheduler, MCP wiring, and voice loop worked out of the box while NanoClaw had accumulated too much hand-rolled glue code to justify keeping both alive.
The cleanup reclaimed about 14GB of Docker layers. I deleted the old bot account myself, which is the closest thing home lab software gets to a funeral. As a bonus, an end-of-life PostgreSQL 9.6 container that my security scan had complained about turned out to be part of the old NanoClaw stack and disappeared with it. Decommissioning is underrated as a security control.
What carried over, and what changed
- Local-only inference stayed - Homer talks exclusively to the local vLLM instance on REX and nothing else. No LiteLLM proxy, no cloud fallback. If Homer throws an inference error, I only have to look in one place.
- The voice moved from Wales to Scotland - Piper and Whisper still run locally, with the default voice switched from Cori to Alba (
en_GB-alba). - WhatsApp is gone - Telegram is the only channel - I briefly looked at Synology Chat and dropped it without installing it.
- The 12.15pm summary became a 7am morning digest - Instead of diffing two Nmap JSON files, Homer called the Aruba, Synology, Juniper, and Home Assistant MCP servers directly and summarised the state.
- The 7.55am health check went silent-on-healthy - A separate check at 7.55am only messages me if something is actually broken. A daily “everything is fine” ping is the fastest way to train yourself to ignore a channel right before the morning something catches fire.
For the same reason, new-device alerts from the Kali scanner stopped going through the LLM. Kali pushes them straight through Homer’s Telegram gateway as plain text - a new MAC address is a fact, and asking a language model to rephrase a MAC address only gives it a chance to hallucinate a digit.
One failure worth recording
In early July the morning digest started reporting that the Juniper switch was unreachable while every other check passed. The cause was a routing-engine firewall filter I’d added to the switch a few days earlier to restrict management SSH to the server subnet - which accidentally locked out the assistant VM sitting on the lab subnet. ping still worked because the filter allowed ICMP, so only SSH timed out.
When Homer suggested adding a narrow exception for its own IP, I just removed the filter instead - a reasonable trade-off for a one-person lab, and a good reminder that a monitoring check that can’t reach its target looks identical to a target that’s down.
Operational notes on Hermes
Environment variable updates need a full docker compose up -d --force-recreate rather than a plain container restart, and numpy has to stay pinned in the external voice library volume or Whisper fails quietly.
Update - October 2026
Two big changes landed after August: I took the LLM out of the scheduled jobs completely, and I replaced the Scottish Piper voice with an actual Homer Simpson voice pipeline.
- Scheduled jobs now run deterministically with
--no-agent- In mid-August, Homer’s scheduled LLM runs developed what I can only call “tool-call rot”: the cron scheduler kept firing on time for eight days while the model made zero tool calls and cheerfully hallucinated a clean health report from memory. I rewrote all four scheduled jobs - the 7am morning report (which checks 20 signals across four infrastructure groups), the WAN failover watchdog, the 5G modem thermal sampler, and the CrowdSec watcher - as deterministic Python and bash scripts that query the APIs directly and format the output with no LLM in the loop. The local model (Swift-Qwen3.8-27B) is now strictly for interactive Telegram chats. - Alerting follows two simple rules - One scheduled report a day at 7am, and outside 7am, only edge-triggered critical alerts when something changes state (WAN failover/recovery, NAS unreachable, non-routine security blocks, or gateway health failures).
- The voice pipeline is now two-stage Piper + RVC - Instead of using a stock Piper voice, TTS now runs through a warm
piper-ttsdaemon (with custom phoneme splicing so"Mmmm"comes out as a hum instead of spelling out"em em em em") and feeds into a persistent Retrieval-based Voice Conversion (rvc-homerd) daemon running a 600-epoch Homer Simpson model. End-to-end voice notes land in Telegram in under ten seconds.