Enhancing Home Assistant with custom automation
I tend to write these after breaking something a few times, which is usually the fastest way to find the rough edges. Home Assistant gets much easier to live with once the automations are repeatable, readable and not doing pointless work every second.
Start with the difference between scenes, automations and blueprints. A scene sets device states, for example lights on at 30 per cent and the thermostat to a setpoint. An automation reacts to triggers and runs actions, for example motion detected then turn on a grouped light. A blueprint is a reusable automation template you can share or import. Use the GUI for quick experiments. Switch to YAML when you want repeatable configs and version control. Put YAML files under config/automations.yaml or split them into config/automations/ if you prefer a directory. Save blueprints under config/blueprints/automation/<author>/name.yaml. For triggers, use device_trigger where you can rather than state polling. Device triggers from Z-Wave JS, Zigbee integrations or MQTT are a lot lighter than template checks running every second. For a simple evening lights automation, a compact example looks like this:
alias: Evening lights on arrival
description: Turn on hall and lounge when I arrive after sunset
trigger:
- platform: zone
entity_id: person.jamie
zone: zone.home
event: enter
condition:
- condition: sun
after: sunset
action:
- service: scene.turn_on
target:
entity_id:
- scene.hall_evening
- scene.lounge_dim
mode: single
For reusability, turn that into a blueprint. Create config/blueprints/automation/lab53/arrival_lights.yaml and use inputs so you can pick the person, zone and scenes without editing YAML each time. A usable blueprint snippet:
blueprint:
name: Arrival lights with sunset
description: Turn scenes on when a person enters a zone after sunset
domain: automation
input:
person:
name: Person entity
selector:
entity:
domain: person
zone:
name: Zone
selector:
entity:
domain: zone
scenes:
name: Scenes to activate
selector:
target:
entity:
domain: scene
trigger:
- platform: zone
entity_id: !input person
zone: !input zone
event: enter
condition:
- condition: sun
after: sunset
action:
- service: scene.turn_on
target: !input scenes
mode: single
Save it, reload blueprints from Configuration, then create automations from that blueprint. That cuts down on copy and paste mistakes. When I build blueprints I test with a synthetic trigger first. Use Developer Tools → Services and call the automation.trigger service. Watch the trace in the automation UI to see each step and the values passed to the blueprint inputs.
Device integration is where a lot of these projects bog down. Pick a radio stack early. I use Z-Wave JS for Z-Wave, Zigbee2MQTT for many Zigbee sticks, and ESPHome for DIY sensors. MQTT is useful for bespoke hardware. Use unique entity_id names when you add devices; change names in the integration UI rather than editing core.entity_registry unless you know what you are doing. Make use of helpers: input_booleans, input_selects and input_numbers let you turn awkward flows into simple conditions passed to blueprints. For devices with local APIs, prefer local integrations. They are quicker and keep automations running if the cloud is down. If a device keeps flapping, switch its state handling to a binary_sensor or add a small condition with a for: value so it does not retrigger constantly.
Performance starts to matter once you have more than a handful of automations. Keep template sensors minimal and move repeated calculations into one template sensor instead of copying the same template into multiple automations. Use device triggers and binary_sensors as cheap, event-driven sources. Set automation mode with intent: single prevents overlaps, queued runs them one after another, parallel allows concurrency if the actions are independent. I set long-running automations to mode: queued with max: 2 so they do not pile up. When calling heavy services such as cloud TTS, push them into a script and mark the script as background. That keeps the automation quick to return and avoids blocking other logic.
When automations misbehave, use the trace and logger. Turn on debug for an integration in Configuration → Logs or by adding a logger entry in configuration.yaml like this:
logger:
default: info
logs:
homeassistant.core: debug
homeassistant.components.mqtt: debug
Use the automation trace to inspect variables, conditions and timing. Check Developer Tools → States to confirm entity IDs have not changed after a device reconfigure. If a blueprint fails for multiple people, try the same inputs on a local test person or entity. Keep all configurations in Git. Tag working releases before major changes so you can roll back with a single git checkout. Back up the config directory regularly, and keep secrets.yaml somewhere encrypted if you need to.
My takeaways are fairly boring, which usually means they work. Put inputs on any blueprint value that changes between rooms. Use device triggers and binary_sensors to keep CPU use down. Test each automation with the trace tool and keep configs in Git so a bad change is easy to undo.



