The Universal Sass Gateway
I taught a local AI to roast me and then gave it control of my entire life.
I need to tell you about the dumbest smart thing I’ve ever built.
It started, like all bad decisions, with a reasonable idea: I wanted my homelab to send me notifications. Weather alerts. Tesla reminders. Homelab status. Normal stuff. But somewhere along the way I decided these notifications needed personality. Not “Battery low.” More like “Hey genius, your car is at 12%. Were you planning on Flintstone-ing it to work?”
And because I am fundamentally incapable of doing anything the simple way, I now have a single AI-powered workflow that processes every notification in my life through a sarcastic language model before it reaches my phone.
I call it the Universal Sass Gateway and I am not okay.
The Before Times
Picture this: five Home Assistant automations, four n8n workflows, a pile of shell commands, rest commands pointing everywhere, four different ntfy topics — all independently talking to Ollama, all independently sending notifications, all independently finding new and creative ways to break.
Every notification was a special little snowflake with its own pipeline. Adding a new one meant writing a new automation, a new workflow, new YAML, new rest commands. It was spaghetti. Sentient, angry spaghetti.
So I did what any reasonable person would do: I burned it all to the ground.
Five Nodes in a Trench Coat
The replacement is one workflow. Five nodes. A straight line. Something wants to send a notification? Hit the webhook with a source name and some data. The AI writes the roast. ntfy delivers the emotional damage. Done.
Nine notification types funnel through this thing now. Weather alerts, Tesla stuff, homelab reports, Home Assistant updates — all of it gets the sass treatment before it reaches my phone. Adding a new source takes five minutes instead of an evening of YAML therapy.
Getting here nearly killed me.
qwen3.5 Is an Unmanageable Employee
The AI powering all of this is qwen3.5:9b running on Ollama. Its entire personality comes from a twelve-word system prompt:
“You are Dave’s Tesla advisor. Sarcastic but helpful. Swear occasionally like a normal person.”
Managing this model is like supervising an intern who’s either brilliant or having a complete psychotic break and you never know which one’s showing up.
Ask it to roast my charging habits? Sometimes you get gold. Sometimes you get a 3,000-word essay analyzing the sentence structure of the input data. I asked for three sentences about my Tesla. It wrote a dissertation about PostgreSQL naming conventions. It had opinions about snake_case. Nobody asked.
Then there’s the thinking problem. qwen3.5 has a habit of doing all its work in a private thinking field and then returning absolutely nothing in the actual response. Like an employee who does the assignment, puts it in their desk drawer, and then tells you they have nothing to report. We had to build logic to check its pockets for the answer.
And it sends its internal monologue to your phone. Your 8 PM charge reminder opens with 800 characters of the AI debating whether “dumbass” is too aggressive for a Tuesday. The model’s therapy sessions are private now. Regex fixed it.
Oh, and when it hasn’t been called in a while? It takes up to ten minutes to wake up. Just dead silence while n8n sits there waiting and the model slowly loads itself back into memory like a bear coming out of hibernation. We had to set a ten-minute timeout so the workflow would stop giving up and walking away.
The Crimes I Committed Along the Way
The string incident: Battery level comes back from TeslaMate as a string. I spent 45 minutes wondering why “47” wasn’t less than 30. Because it’s text, Dave. It’s text and it doesn’t do math and it doesn’t care about you. Nine characters fixed it. I have a degree.
The copy-paste disaster: I was building multiple API nodes at once, copying configs between them. PBS credentials ended up in the Proxmox node. Proxmox headers ended up in TrueNAS. Every node confidently authenticating to the wrong service. Four 401 Unauthorized responses holding hands. I did this to myself, in my own home, on purpose.
The emoji war crime: I put an emoji in an HTTP header. HTTP headers don’t support emoji. The error message was ERR_INVALID_CHAR and nothing else. I aged visibly before figuring it out.
The JSON saga: Newlines in data broke everything. Special characters broke everything. One of n8n’s body modes just straight up didn’t work. We went through three different approaches to “put text in a JSON field” before finding one that didn’t explode.
Then We Got Drunk With Power
Once the gateway was running, we couldn’t stop. Five new workflows in rapid succession, like a man who found a nail gun and suddenly everything looks like a nail:
Morning Brief (6:30 AM) — Weather and five calendars worth of events, roasted. “You have six meetings today. I’m not saying your calendar is a cry for help, but I’m not not saying that.”
Evening Brief (8:30 PM) — Tomorrow’s weather and calendar, roasted. Because why wait until morning to dread your schedule.
Garbage Day Reminder (8:15 PM) — This one calculates whether Friday is a garbage week based on a two-week cycle, checks my work calendar for trips, finds the last free evening before I leave, and fires the reminder then. If I’m gone all week it skips entirely. It’s a garbage reminder with business travel logic and I’m unreasonably proud of it.
Bourbon O’Clock (5:00 PM) — Checks the weather and recommends a specific bourbon matched to the vibe. Every single day. No exceptions. No days off. No opt-out. Rain? Woodford Reserve, neat. Sunny? Something with citrus on the porch. This is peak engineering and I will not be taking questions.
Work Trip Roast (2:00 PM) — Detects when a trip starts tomorrow, pulls the details from my calendar, and reminds me to pack my shit. With attitude.
All five route through the Sass Gateway. All five were built in the same manic stretch. We also had to set up Google Calendar OAuth from absolute scratch — enabling APIs, creating clients, adding test users — because apparently Google thinks connecting your own calendar to your own server should require a small quest.
The 1 AM Babysitter
We also added a daily cron job at 1 AM that restarts Ollama because sometimes the GPU processes go zombie and sit there hoarding memory like a digital squatter. We automated restarting the AI because the AI can’t be trusted to manage itself. There’s a metaphor in there somewhere.
The Payoff
Every morning at 6:30, my phone roasts my schedule. Every evening at 8:30, it previews tomorrow with the same energy. At 5 PM sharp, it tells me what bourbon to pour. If garbage day is coming and I’m about to skip town, it catches that. If I’m flying out tomorrow, it tells me to pack.
Nine sources. Five new workflows. One gateway. One twelve-word personality prompt on a mass-produced AI running on a server I bought off eBay.
Self-hosted. No cloud. No subscriptions. Just a foul-mouthed language model on commodity hardware, processing every notification in my life through a sarcasm filter before it reaches my phone.
I automated my own emotional abuse and I’ve never been happier.
This is the way.
Dave homelabs at satchnet.io. The Sass Gateway has 14 sources and 0 chill. The bourbon is poured. The model is warm.