Quick answer

Each automation has triggers, optional conditions and actions. A sun trigger takes offset -00:30:00 to fire before sunset. Motion lights can wait for five continuous minutes without motion. A dishwasher alert first records sustained running power in a helper, then waits for power below 5 watts for two minutes. Two-person away mode checks that both people are away.

Contents

By LK Wood IV · 2026-06-16 · ~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

The visual editor supports complex action sequences too. Its YAML view edits the same UI-managed automation. For hand-maintained files, the YAML documentation distinguishes automations.yaml from labeled blocks in configuration.yaml. The full examples below go in configuration.yaml; merge their list entries into one automation block or give each block a distinct label. In the UI YAML editor, paste one automation without the enclosing automation: key and list marker.

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_kelvin: 2500  # warm

The offset field accepts positive or negative durations. -00:30:00 means 30 minutes before the event.

Use color_temp_kelvin for temperature-capable lights. Home Assistant removed the old mired argument in 2026.3. The examples convert mireds with kelvin = 1000000 / mireds, rounded to a whole kelvin; choose a value within your light’s supported range.

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_kelvin: 2000  # 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

Use a smart plug rated for the dishwasher’s load that reports watts. This example records a running cycle in an input boolean helper before allowing a completion alert:

input_boolean:
  dishwasher_running:
    name: Dishwasher running
    # No initial value: restore the previous state after a restart.

automation dishwasher:
  - id: dishwasher_record_running
    alias: "Dishwasher - Record Running Cycle"
    trigger:
      - platform: numeric_state
        entity_id: sensor.dishwasher_power
        above: 10    # watts; tune from a complete cycle's power history
        for: "00:01:00"
    action:
      - service: input_boolean.turn_on
        target:
          entity_id: input_boolean.dishwasher_running

  - id: dishwasher_notify_done
    alias: "Dishwasher - Done Notification"
    trigger:
      - platform: template
        value_template: >-
          {{ is_state('input_boolean.dishwasher_running', 'on') and
             is_number(states('sensor.dishwasher_power')) and
             states('sensor.dishwasher_power') | float(0) < 5 }}
        for: "00:02:00"
    action:
      - service: input_boolean.turn_off
        target:
          entity_id: input_boolean.dishwasher_running
      - service: notify.mobile_app_phone
        data:
          title: "Dishwasher Done"
          message: "Cycle complete."

An idle reading cannot notify while the helper is off. Unknown or unavailable readings also cannot complete a cycle. The helper survives a normal restart; the two-minute trigger timer starts over after a restart or automation reload. The 10 W, one-minute start and 5 W, two-minute finish values are examples. Inspect a full wash and drying cycle and lengthen the finish interval beyond any mid-cycle pause. Clear the helper manually after a canceled cycle. Verify an idle period, a short dip and a completed cycle in Traces before relying on the alert.

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_kelvin: 4000  # 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_kelvin: 2000  # warm, evening
        default:
          - service: light.turn_on
            target:
              entity_id: light.living_room
            data:
              brightness_pct: 10
              color_temp_kelvin: 1667  # very warm; check your light's minimum

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_kelvin: 5000  # 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

After adapting entity IDs, run Developer Tools → YAML → Check configuration before reloading manual YAML. Test each light action with a supported kelvin value and check the automation trace. These examples were reviewed against current documentation on 2026-10-12; a YAML parse alone does not verify your installed integrations, devices or notification service.

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.

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. If you’d rather trigger these by voice than by dashboard, the local LLM voice guide covers HA 2026.8’s llama.cpp integration — including which models actually target the right entities.

Sources

Frequently asked questions

Should I use the Home Assistant automation UI or YAML?
The visual editor supports conditions, branches and loops, and lets you switch to Edit in YAML. UI-managed automations are saved in automations.yaml. Manual YAML can live in configuration.yaml or separate included files; it does not automatically become editable in the UI. Use the visual editor for building and discovering actions, and YAML for copying examples or version control. Some advanced options are YAML-only.
What is the difference between an automation and a script in Home Assistant?
Automations run automatically when a trigger fires (without you doing anything). Scripts are manual action sequences you call explicitly — from a button press, a service call, or from within an automation. Scripts are reusable: if three automations all need to ’turn on the good morning lighting scene and set the thermostat to 70’, put that in a script and call it from each automation rather than repeating the action list. Scripts don’t have triggers.
How do I debug an automation that isn’t firing?
Settings → Automations → open the automation → trace. The automation trace shows every recent run attempt, whether the trigger fired, which conditions passed or failed, and which actions ran. If the automation didn’t fire at all, the trigger didn’t activate — check the entity state, the trigger value_template, or the time specification. If it fired but did nothing visible, check the condition section — a condition that evaluates false silently stops the automation.
What is a template in Home Assistant?
Templates are Jinja2 expressions inside Home Assistant YAML that evaluate dynamically at runtime. They let you calculate values, compare states, and make conditional decisions inside automations. For example: {{ 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).
How do I trigger an automation when someone arrives home?
The most reliable approach is zone-based presence detection with the official companion app (iOS or Android). The app reports when a device enters or leaves a defined Home Assistant zone (like ‘Home’). In the automation: trigger type ‘Zone’, entity = person.your_name, zone = zone.home, event = enter. Companion apps handle battery-efficient geofencing. Alternative: Bluetooth proxy detection (device comes in range of a Bluetooth proxy), or router-based tracking (device connects to the home WiFi network).

Sources and corrections

Last updated
Methodology
See our methodology for research and review standards.
Corrections
Spotted an error or a stale number? Email contact@techfuelhq.com. Confirmed corrections are recorded here with the date and change.

About the author

Written by Lowell K. Wood IV, who builds and runs TechFuelHQ from St. Louis, Missouri.