Mastering Home Assistant's Scripts and Sequences for Advanced Automation Routines

NGC 224
DIY Smart Home Creator
Home Assistant excels at making your smart home intelligent, but beyond simple "if X then Y" automations lies a powerful feature: Scripts. While automations react to triggers, scripts define reusable sequences of actions, enabling you to orchestrate complex routines, introduce delays, implement conditional logic, and build highly sophisticated smart home behaviors that would be cumbersome, if not impossible, with standalone automations.
Understanding the Role of Scripts
Think of automations as the "events" and scripts as the "functions" or "subroutines" in programming. An automation detects a trigger (e.g., motion detected, time of day) and then calls a script (or a series of actions). The script itself contains the detailed, ordered steps that need to be executed. This separation of concerns offers significant benefits:
- Reusability: Define a complex routine once and call it from multiple automations, dashboards, or even other scripts.
- Modularity: Break down large automation flows into smaller, manageable, and testable script components.
- Complex Logic: Implement intricate sequences with delays, conditional branches, loops, and dynamic variables.
- Manual Execution: Run a script manually from the Home Assistant UI, providing quick control over predefined routines.
Key Scripting Features and Syntax
Scripts are defined under the script:
domain in your Home Assistant configuration, typically in configuration.yaml
or an included YAML file (e.g., !include scripts.yaml
or !include_dir_list scripts/
). Each script is given a unique ID.
Basic Structure:
# scripts.yaml
my_first_script:
alias: "My First Script"
sequence:
- service: light.turn_on
target:
entity_id: light.living_room_lights
- delay: "00:00:05" # Wait 5 seconds
- service: notify.mobile_app
data:
message: "Lights are on!"
The core of any script is its sequence
block, which is a list of actions executed sequentially. Home Assistant offers a rich set of actions:
service:
Call any Home Assistant service (e.g.,light.turn_on
,media_player.play_media
).delay:
Pause script execution for a specified duration (e.g.,"00:01:30"
for 1 minute 30 seconds, orseconds: 10
).wait_template:
Halt execution until a Jinja2 template evaluates totrue
. Essential for waiting for device states.- wait_template: "{{ is_state('light.living_room_lights', 'on') }}" timeout: "00:00:10" # Optional: Timeout after 10 seconds continue_on_timeout: true # Optional: Continue even if timeout occurs
wait_for_trigger:
Pause until a specific event or trigger occurs.- wait_for_trigger: - platform: state entity_id: binary_sensor.front_door to: 'off' timeout: "00:05:00"
condition:
Introduce conditional logic. If the condition isn't met, the remaining actions in the sequence are skipped.- condition: state entity_id: binary_sensor.motion_sensor_hallway state: 'on' - service: light.turn_on target: entity_id: light.hallway_light
choose:
Implement if/elif/else branching logic, allowing different sequences based on various conditions.- choose: - conditions: "{{ is_state('sun.sun', 'below_horizon') }}" sequence: - service: light.turn_on target: entity_id: light.porch_light - conditions: "{{ is_state('sun.sun', 'above_horizon') }}" sequence: - service: light.turn_off target: entity_id: light.porch_light default: # Optional: Actions if no conditions match - service: notify.persistent_notification data: message: "Sun state unclear."
repeat:
Loop through a sequence of actions a specific number of times, until a condition is met, or while a condition is true.- repeat: count: 3 # Repeat 3 times sequence: - service: media_player.volume_up target: entity_id: media_player.living_room_tv - delay: "00:00:01"
variables:
Define temporary variables within a script's execution, useful for passing dynamic data.my_dynamic_script: sequence: - variables: target_light: "{{ light_entity_id_from_automation }}" # Passed from caller - service: light.turn_on target: entity_id: "{{ target_light }}"
Managing Script Execution Modes
An often-overlooked but crucial aspect of scripts is their mode
. This defines how Home Assistant handles multiple simultaneous calls to the same script:
single
(default): Only one instance of the script can run at a time. New calls are ignored if one is already running.restart
: If the script is called while already running, the current instance is stopped, and a new one starts.parallel
: Multiple instances of the script can run concurrently. Useful for independent actions.queued
: New calls are added to a queue and executed one after another once the previous instance finishes.
Choosing the correct mode is vital for preventing unexpected behavior, especially with time-sensitive or state-dependent routines.
Best Practices for Reliable Scripting
- Modularity: Break down complex routines into smaller, single-purpose scripts. This enhances readability, testing, and reusability.
- Use
wait_template
withtimeout
: Never assume a device will instantly respond. Always add a timeout towait_template
orwait_for_trigger
actions to prevent scripts from hanging indefinitely. - Leverage Variables: Design scripts to accept variables (passed from the automation that calls them). This makes your scripts highly reusable and adaptable to different contexts or devices. For example, a "turn on light with color" script could take
entity_id
andcolor
as variables. - Error Handling with
choose
anddefault
: Use thedefault
block in achoose
action to handle scenarios where none of your explicit conditions are met, preventing unintended omissions. - Comment Your Code: Add comments (
#
) generously to explain the purpose of complex steps or logic, especially when collaborating or revisiting scripts later. - Thorough Testing: Use the Home Assistant UI to manually trigger scripts and observe their behavior. Leverage the "Traces" feature (available for automations and scripts) to visually debug their execution flow step-by-step.
- Understand
mode
: Carefully consider the implications ofsingle
,restart
,parallel
, andqueued
for each script based on its purpose. For routines that should never run concurrently or need to finish before another starts,single
orqueued
might be appropriate. For independent actions,parallel
.
Example: An Advanced "Good Night" Routine
Let's build a robust "Good Night" script, triggered by a button press or time of day:
# In scripts.yaml
good_night_routine:
alias: "Execute Good Night Routine"
mode: single # Only one instance should run at a time
sequence:
- service: input_boolean.turn_on
target:
entity_id: input_boolean.good_night_active # Indicate routine is running
# 1. Turn off all main lights (using a light group)
- service: light.turn_off
target:
entity_id: light.all_interior_lights
# 2. Check if doors are closed before arming alarm
- choose:
- conditions:
- condition: state
entity_id: binary_sensor.front_door_contact
state: 'off'
- condition: state
entity_id: binary_sensor.back_door_contact
state: 'off'
sequence:
- service: alarm_control_panel.alarm_arm_home
target:
entity_id: alarm_control_panel.home_alarm
- service: notify.mobile_app
data:
message: "Alarm armed. All doors closed."
default:
- service: notify.mobile_app
data:
message: "Warning: Doors are open! Alarm not armed."
title: "Home Assistant Alert"
- stop: "Doors open, cannot arm alarm." # Stop script execution
- delay: "00:00:02" # Short delay after alarm arming attempt
# 3. Set thermostat to night mode
- service: climate.set_preset_mode
target:
entity_id: climate.thermostat
data:
preset_mode: "sleep"
# 4. Power off media devices, waiting for them to turn off
- service: media_player.turn_off
target:
entity_id:
- media_player.living_room_tv
- media_player.soundbar
- wait_template: >
{{ is_state('media_player.living_room_tv', 'off') and
is_state('media_player.soundbar', 'off') }}
timeout: "00:00:20"
continue_on_timeout: true # Continue even if devices don't report off
# 5. Lock all smart locks
- service: lock.lock
target:
entity_id:
- lock.front_door_lock
- lock.back_door_lock
# 6. Final confirmation notification
- service: notify.mobile_app
data:
message: "Good Night! Your home is secured."
- service: input_boolean.turn_off
target:
entity_id: input_boolean.good_night_active # Routine finished
Conclusion
Home Assistant's scripting capabilities are a cornerstone for building truly sophisticated and reliable smart home ecosystems. By understanding and effectively utilizing sequences, delays, conditions, loops, and execution modes, you can move beyond basic automations to create dynamic, robust, and incredibly intelligent routines that precisely meet your home's needs. Dive in, experiment, and transform your smart home from reactive to proactive with the power of scripts!

NGC 224
Author bio: DIY Smart Home Creator