Home Assistant Automations: A Practical Guide (2026)
By LK Wood IV · 2026-05-31 · ~15 min read · St. Louis County, MO
Home Assistant automations follow a consistent structure: something happens (trigger), check if conditions are met (conditions), then do things (actions). Once you understand that structure, you can write almost any automation. This guide is examples-first — real working YAML for the automations that actually matter.
If you haven’t set up Home Assistant yet, the Home Assistant on Proxmox guide covers the install. For Zigbee/Z-Wave devices, the integration guide covers pairing.
The automation structure
automation:
- alias: "My Automation Name"
trigger:
- platform: <trigger_type>
# trigger-specific fields
condition:
- condition: <condition_type>
# condition-specific fields
action:
- service: <domain.service>
target:
entity_id: <entity_id>
data:
# service-specific data
Trigger: what initiates the automation (state change, time, zone entry, webhook, etc.) Condition: optional guards — the automation only proceeds if all conditions pass Action: what happens when the trigger fires and conditions pass
Lighting automations
Turn on lights at sunset
automation:
- alias: "Living Room — Lights On at Sunset"
trigger:
- platform: sun
event: sunset
offset: "-00:30:00" # 30 minutes before actual sunset
action:
- service: light.turn_on
target:
entity_id: light.living_room
data:
brightness_pct: 60
color_temp: 400 # warm color temperature (mireds)
The offset field accepts positive or negative durations. -00:30:00 means 30 minutes before the event.
Adaptive lighting: dim at night
automation:
- alias: "Bedroom — Dim Lights After 10 PM"
trigger:
- platform: time
at: "22:00:00"
condition:
- condition: state
entity_id: light.bedroom
state: "on"
action:
- service: light.turn_on
target:
entity_id: light.bedroom
data:
brightness_pct: 20
color_temp: 500 # very warm
transition: 10 # 10-second transition
The condition here prevents the automation from triggering the bedroom lights if they’re already off — you don’t want the lights turning on at 10 PM just to dim them.
Motion-triggered lights with timeout
automation:
- alias: "Hallway — Motion Light"
trigger:
- platform: state
entity_id: binary_sensor.hallway_motion
to: "on"
action:
- service: light.turn_on
target:
entity_id: light.hallway
- delay: "00:05:00" # wait 5 minutes
- condition: state # only turn off if still no motion
entity_id: binary_sensor.hallway_motion
state: "off"
- service: light.turn_off
target:
entity_id: light.hallway
For more reliable motion timeout behavior, use the wait_for_trigger action instead of delay:
action:
- service: light.turn_on
target:
entity_id: light.hallway
- wait_for_trigger:
- platform: state
entity_id: binary_sensor.hallway_motion
to: "off"
for: "00:05:00"
- service: light.turn_off
target:
entity_id: light.hallway
wait_for_trigger pauses the action sequence until the trigger fires, then continues. If the motion sensor never clears, the action sequence waits indefinitely (use timeout: to cap it).
Presence-based automations
Welcome home scene
automation:
- alias: "Welcome Home — Set Living Room Scene"
trigger:
- platform: zone
entity_id: person.lk
zone: zone.home
event: enter
condition:
- condition: sun
after: sunset
before: sunrise
action:
- service: scene.turn_on
target:
entity_id: scene.living_room_evening
- service: climate.set_temperature
target:
entity_id: climate.main_thermostat
data:
temperature: 70
The sun condition ensures the welcome home lighting only triggers after dark. Arriving home at noon doesn’t need the lights on.
Everyone left — eco mode
automation:
- alias: "All Away — Energy Saving Mode"
trigger:
- platform: state
entity_id:
- person.lk
- person.partner # list multiple people
to: "not_home"
condition:
- condition: state
entity_id: person.lk
state: "not_home"
- condition: state
entity_id: person.partner
state: "not_home"
action:
- service: climate.set_temperature
target:
entity_id: climate.main_thermostat
data:
temperature: 65 # setback temperature
- service: light.turn_off
target:
area_id: living_room
- service: notify.mobile_app_phone
data:
message: "Away mode activated."
The trigger fires when any person changes to not_home. The conditions verify that ALL tracked people are away before applying eco mode — so the trigger fires but conditions gate it until the last person leaves.
Notification automations
Dishwasher done
This works with a smart plug that measures wattage (Zigbee or Z-Wave smart outlet):
automation:
- alias: "Dishwasher — Done Notification"
trigger:
- platform: numeric_state
entity_id: sensor.dishwasher_power
below: 5 # watts — below this = cycle complete
for: "00:02:00"
condition:
- condition: numeric_state
entity_id: sensor.dishwasher_power
above: 0.1 # was actually running (not just idle/off)
action:
- service: notify.mobile_app_phone
data:
title: "Dishwasher Done"
message: "Cycle complete."
The for: "00:02:00" on the trigger prevents false positives from mid-cycle power dips — the wattage has to stay below 5W for two minutes before triggering.
Low battery alert
automation:
- alias: "Low Battery — All Devices"
trigger:
- platform: numeric_state
entity_id:
- sensor.front_door_lock_battery
- sensor.bedroom_motion_battery
- sensor.thermostat_battery
- sensor.smoke_detector_battery
below: 20
action:
- service: notify.mobile_app_phone
data:
title: "Low Battery"
message: "{{ trigger.to_state.name }} is at {{ trigger.to_state.state }}%"
The template {{ trigger.to_state.name }} and {{ trigger.to_state.state }} pull the entity’s display name and current value from the trigger context — so one automation handles multiple devices and tells you specifically which one is low.
Template-based automations
Door left open warning
automation:
- alias: "Front Door — Left Open Alert"
trigger:
- platform: state
entity_id: binary_sensor.front_door
to: "on"
for: "00:10:00" # open for 10 minutes
condition:
- condition: template
value_template: "{{ states('person.lk') == 'home' }}"
action:
- service: notify.mobile_app_phone
data:
message: "Front door has been open for 10 minutes."
- service: tts.speak
target:
entity_id: media_player.kitchen_speaker
data:
message: "The front door is still open."
The template condition checks that someone is home before sending the alert — no point in notifying if no one is there to close it.
Thermostat override protection
automation:
- alias: "Thermostat — Override Detection"
trigger:
- platform: state
entity_id: climate.main_thermostat
attribute: temperature
condition:
- condition: template
value_template: >
{{ trigger.to_state.attributes.temperature | float > 78 and
now().hour >= 1 and now().hour < 6 }}
action:
- service: climate.set_temperature
target:
entity_id: climate.main_thermostat
data:
temperature: 70
- service: notify.mobile_app_phone
data:
message: "Thermostat was set above 78°F at night — reset to 70°F."
Choose blocks: conditional action branching
When you need the automation to do different things based on a condition, use choose:
automation:
- alias: "Motion — Lighting by Time of Day"
trigger:
- platform: state
entity_id: binary_sensor.living_room_motion
to: "on"
action:
- choose:
- conditions:
- condition: time
after: "06:00:00"
before: "20:00:00"
sequence:
- service: light.turn_on
target:
entity_id: light.living_room
data:
brightness_pct: 90
color_temp: 250 # cooler, daytime
- conditions:
- condition: time
after: "20:00:00"
before: "23:00:00"
sequence:
- service: light.turn_on
target:
entity_id: light.living_room
data:
brightness_pct: 40
color_temp: 500 # warm, evening
default:
- service: light.turn_on
target:
entity_id: light.living_room
data:
brightness_pct: 10
color_temp: 600 # very warm, late night
Scripts: reusable action sequences
Put repeated action sequences in scripts:
# configuration.yaml
script:
good_morning:
alias: "Good Morning Routine"
sequence:
- service: light.turn_on
target:
area_id: bedroom
data:
brightness_pct: 30
color_temp: 200 # cool/bright
transition: 120 # 2-minute sunrise
- service: climate.set_temperature
target:
entity_id: climate.main_thermostat
data:
temperature: 70
- delay: "00:02:00"
- service: light.turn_on
target:
entity_id: light.kitchen
data:
brightness_pct: 80
Call this script from any automation or button press:
action:
- service: script.good_morning
Debugging automations
Trace view: Settings → Automations → open automation → Traces. Shows every firing with the trigger value, each condition result (pass/fail with values), and each action outcome.
Template testing: Developer Tools → Template. Paste any Jinja2 expression and see it evaluate against current state in real time. Use this to test conditions before putting them in an automation.
Entity history: Developer Tools → States. See the current value and last-changed time for any entity. Useful when an automation isn’t triggering — check if the entity state is actually what you think it is.
Logbook: Settings → Logbook. Shows state changes and automation fires in chronological order. Filter by entity to see exactly when something changed.
Best practices
Use for: on state triggers to avoid automations firing on momentary state changes (a sensor flickering, a button double-press).
Avoid complex logic in a single automation — break it into an automation that calls a script, with multiple scripts for different conditions. Simpler automations are easier to debug.
Version control your config — store your configuration.yaml and automation files in a Gitea repository. The Docker Compose starter stack includes Gitea for exactly this.
Use areas and labels — Home Assistant’s area grouping lets you target all lights in a room without listing entity IDs. area_id: living_room in a target covers everything in that area, including devices added later.
This guide extends the setup work from the Home Assistant on Proxmox guide and the Zigbee/Z-Wave integration guide. The automations here assume your devices are already paired and showing correct state in HA.
Frequently asked questions
Should I use the Home Assistant automation UI or YAML?
What is the difference between an automation and a script in Home Assistant?
How do I debug an automation that isn't firing?
What is a template in Home Assistant?
{{ states('sensor.temperature') | float > 75 }} evaluates to true or false based on the current temperature sensor reading. Templates are used in condition value_templates, in action data (to compute a brightness value from a sensor), and in trigger value_templates (to trigger on computed conditions).