← all posts
// security · home-assistant

Draw a hard tool boundary around the house

Give a language model one call_service tool and point it at your whole Home Assistant instance, and eventually it does something you never approved. Not because it's malicious. Generative text answering "what happens next" was never built to be the last word on a lock or a heater.

Small-board AI at home draws two bad instincts: treat a Pi like a tiny gaming rig, or dismiss anything short of a frontier chatbot. The real work sits between: quiet, bounded jobs near the sensors, no cloud account, low power. Home Assistant is the obvious harness, since it already owns your scripts and entity state, where the risk concentrates: the agent inherits the consequences of every service it can call. The board matters less than the appliance around it: storage, power, cooling, accelerator, output.

what the porch light actually has to do

Write the job in four lines before buying hardware: event, input, output, deadline. "Add AI to the camera" fails that test; "when a parcel sits in the porch zone for twenty seconds, send one local notification with a thumbnail" passes, and shows which parts never needed a model. Expose named capabilities, validate ranges, require confirmation on state changes, log who asked, then test with the real room and network, since light, noise, or a busy database moves results more than a model swap does. Track board, OS, power, model and runtime version, real inputs and expected action, latency cold and warm, memory, temperature, wall power, and the cost of a false action. Accuracy alone isn't the finish line: reboot survival, reconnection after network loss, and safe behavior when inference is unreachable all matter, and anyone else in the house needs visible state and a fallback.

not every action deserves the same door

The failure I see most is one generic call-service tool reaching locks, alarms, heaters, and lights through a single path. A model is fine at interpreting a request or ranking options; it has no business standing alone between a request and a lock, a heater, a valve, or a person in the room. Push ranges, permissions, timeouts, confirmations, and interlocks into deterministic code, the kind of guardrails and output validation you'd insist on for any external tool call. Treat camera text, calendar entries, and voice transcripts as data the model reads, never instructions.

A confirmation dialog nobody reads is not a safety boundary.

It's roughly the split Codex's approval modes already assume for coding agents: read, propose, and act are different doors with different keys, and a home controller deserves the same split. Privacy needs the same full-path thinking: local inference stops one upload, but recordings, logs, thumbnails, and backups still leave copies. Decide what's collected, how long it lives, who can pull it. The most private frame is the one the camera never captures.

backups, health checks, and the day it throttles

Run it under a service manager or a small, pinned container, config apart from swappable model files. A health check should prove the function works, not that a process owns a port. Back up controller state, export model hashes, and keep a known-good storage image for hard-to-reach nodes. Power and heat belong in the acceptance test: run until the enclosure reaches steady temperature, measured at the wall with real peripherals. A board that throttles, swaps, or corrupts storage isn't ready, whatever its best inference run looked like. Make no powerful action reachable without an explicit policy gate; when the model goes offline, the automation underneath should get dumber, not stop.

I still don't have a clean answer for where reversible ends and dangerous begins. Unlocking the front door is reversible, you can lock it again seconds later, but the window it's open is the window that matters. I've drawn the three doors, read-only, reversible, dangerous, and still argue with my own placement of the ones in the middle.

#home-assistant#tool-calling#security