Skip to content

Your First Home Assistant Automation in YAML, Line by Line

25/09/2026
Your first Home Assistant YAML automation

This article may contain affiliate links. If you buy through these links, the price is the same for you and the store pays me a small commission that helps keep Tecnoyfoto running.

← Chapter 3 · Course index

We already know how to read a YAML document’s structure and verify the states and actions Home Assistant uses. Now we will combine those skills to produce a visible result: when the virtual front door opens, Home Assistant will turn on the living-room light.

The automation is intentionally small. It has one trigger and one action, allowing us to follow the complete path from event to result without burying important ideas under twenty new options.

First, we will build it in the interface. Then we will open its YAML view and read each block. Finally, we will test it in three different ways, because running the actions is not the same as causing the configured trigger to fire.

The mental structure of an automation

An automation responds to this model:

When something happens → check conditions → run actions

Home Assistant represents it through three main sections:

triggers:
conditions:
actions:

The trigger starts the automation. Conditions decide whether it may continue at that moment. Actions describe what Home Assistant will run if the conditions pass.

The conditions are optional. If we do not need any, the section may contain an empty list:

conditions: []

For this example, the trigger and actions are essential. Without a trigger, nothing starts the automation automatically. Without actions, it could start but would not produce the result we want.

DEALS · OFFICIAL STORE

Discounts on SONOFF smart home

Wi-Fi switches, relays, sensors, LED strips and more. Deals change frequently in the official store.

Coupon: TECNOYFOTO (10% off at checkout)

View official deals Affiliate link Affiliate link · SONOFF store

Describe the behavior before opening the editor

Writing a clear sentence helps not to mix causes, checks and results:

When the entrance door switches from closed to open, turn on the living room light.

We can separate the requirement into its parts:

  • Event: the door switches from closed to open.
  • Observed entity: binary_sensor.course_front_door.
  • Initial internal state: "off".
  • Final internal state: "on".
  • Action: light.turn_on.
  • Target: light.course_living_room.

There is no condition. The automation should respond whenever that transition occurs.

Create the automation from the interface

In Home Assistant, open Settings → Automations & scenes and create a new automation. Choose Create new automation and start with an empty automation.

Give it a name that describes the result without requiring you to open it:

YAML Course - Turn On the Light When the Door Opens

You can add this description:

Turn on the virtual living-room light when the practice front door changes from closed to open.

In the triggers section, add a state trigger:

  • Entity: binary_sensor.course_front_door.
  • From: off.
  • To: on.

Don’t add any conditions.

In the actions, select the action to turn on a light and choose:

light.course_living_room

Save the automation. Home Assistant creates its internal identifier and corresponding automation entity.

Exact button labels may vary slightly with the interface language or a future update. The important pieces do not change: a state trigger, no conditions, and a light.turn_on action targeting the practice entity.

The complete YAML we just built

Open the automation menu and enter Edit in YAML. You should find a structure equivalent to this:

alias: "YAML Course - Turn On the Light When the Door Opens"
description: >-
  Turn on the virtual living-room light when the practice front door changes
  from closed to open.
triggers:
  - trigger: state
    entity_id: binary_sensor.course_front_door
    from: "off"
    to: "on"
conditions: []
actions:
  - action: light.turn_on
    target:
      entity_id: light.course_living_room
mode: single

The interface may order some fields differently or place the description on one line. That does not change the behavior.

alias and description: understand the automation before opening it

alias: "YAML Course - Turn On the Light When the Door Opens"
description: >-
  Turn on the virtual living-room light when the practice front door changes
  from closed to open.

alias is the name shown in the interface. It should describe what the automation does and, when useful, the relevant context. “Door automation” says much less than “Turn On the Light When the Door Opens.”

description records details that do not fit comfortably in the name. Here, we used a folded text block to split a long sentence across two source lines.

triggers: what starts the automation

triggers:
  - trigger: state
    entity_id: binary_sensor.course_front_door
    from: "off"
    to: "on"

triggers contains a list. It has one item, started by the dash before trigger.

The state value tells Home Assistant to observe a state change. entity_id identifies the entity to watch. from and to define the exact transition: the entity must leave "off" and enter "on".

For our door sensor, "off" means closed and "on" means open. We use the internal states verified in the previous chapter, not the human-friendly words a card may display.

Why we specify from and to

We could write:

triggers:
  - trigger: state
    entity_id: binary_sensor.course_front_door
    to: "on"

This version starts when the entity enters "on" from any previous state, including unknown or unavailable. In some automations, that may be exactly what you want.

Adding from: "off" expresses a more specific transition: a door known to be closed has opened. We want that precision in this first exercise because it makes the observed change easier to reason about.

You also shouldn’t remove both from and to without understanding the effect:

triggers:
  - trigger: state
    entity_id: binary_sensor.course_front_door

The trigger can now respond to any change in the state object, including some attribute changes. It no longer means specifically that the door opened.

conditions: []: an empty list also communicates a decision

conditions: []

The brackets represent an empty list. This automation has no conditions: after the trigger fires, the automation proceeds directly to the actions.

We could skip the key in a manual setting, but the editor usually keeps all three sections to show the entire structure. There’s nothing to edit in that list.

actions: the result we ask for

actions:
  - action: light.turn_on
    target:
      entity_id: light.course_living_room

actions is another list. Its first item calls light.turn_on. Inside target, entity_id identifies the light that should receive the command.

We already tested this call in Tools → Actions. Placing it in an automation does not change its meaning; it changes when the call runs. Previously, we clicked a button. Now, the automation will call it after the trigger.

mode: single: what happens if it starts again

mode: single

The mode controls what happens if the automation is triggered again while a previous run is still active.

single allows only one active run and rejects a new trigger until that run finishes. Our action completes almost immediately, so this detail is unlikely to make a visible difference. In Chapter 6, we will add waits and see why the mode then becomes important.

Where is id?

An automation created from the interface has a unique identifier stored in automations.yaml. Depending on the YAML view shown by the editor, the id field may not appear in the editable fragment.

A complete entry of automations.yaml usually has this form:

- id: "course_turn_on_light_when_door_opens"
  alias: "YAML Course - Turn On the Light When the Door Opens"
  description: "Turn on the virtual living-room light when the door opens."
  triggers:
    - trigger: state
      entity_id: binary_sensor.course_front_door
      from: "off"
      to: "on"
  conditions: []
  actions:
    - action: light.turn_on
      target:
        entity_id: light.course_living_room
  mode: single

The outer dash exists because automations.yaml is a list of automations. id allows Home Assistant to identify this automation in a stable way. It is also necessary to keep traces of automation manually written in YAML.

The id is neither the automation’s entity_id nor its visible alias. It must be unique among all automations. If you use the editor, let Home Assistant manage it.

Testing an action is not the same as testing the trigger

Home Assistant offers several ways to perform tests. Each one answers a different question.

Run one action

You can run an individual action directly from its menu in the editor. This verifies that the action call and target work; it does not test the trigger or conditions.

In our case it responds to:

Can Home Assistant run light.turn_on with light.course_living_room as its target?

Run all automation actions

The option Run actions runs through the sequence of actions, but omits triggers and conditions. If the light goes on like this, we only know that the end part works.

This is a useful test, but it can lead to the wrong conclusion: “The automation works manually, so the trigger works.” We have not tested the trigger at all.

Trigger the real event

To test the complete path:

  1. Turn off light.course_living_room.
  2. Check that input_boolean.course_front_door_open is disabled.
  3. Activate input_boolean.course_front_door_open.
  4. Verify that binary_sensor.course_front_door changes from off to on.
  5. Check that the light changes to on.

We have now caused the configured transition and observed its result.

To repeat the test, close the virtual door first. Turning on a control that is already on does not create a new off-to-on transition.

Read the first trace

After causing the trigger to fire, open the automation and inspect its traces. Home Assistant shows the run path step by step.

In this automation you should see:

State trigger fired
        ↓
No conditions to check
        ↓
light.turn_on action executed

Select the trigger step. The trace records the change that started the automation, including the previous and new states. Then select the action and review the target it used.

Traces are not only for failures. Studying one now, while the behavior is simple, will make traces easier to interpret once we add conditions and multiple branches.

Home Assistant stores a limited number of recent traces. Manually written YAML automations need an id for their traces to be retained.

First diagnosis: the action works, but the door does not initiate it

Suppose Run actions turns on the light, but opening the virtual door does nothing. We have already isolated part of the problem:

  • The action and its target are probably correct.
  • We need to review the trigger, whether the automation is enabled, and the door’s actual transition.

Check:

  1. Confirm that the automation is enabled.
  2. Confirm that the trigger’s entity_id matches exactly.
  3. Make sure the door starts at off.
  4. Verify that it actually changes to on.
  5. Check for a new trace after opening the door.

If there is no trace, the automation did not start. Changing indentation in the action will not help. Focus the diagnosis on the part we have not yet proven.

Exercise: turn off the light when the door closes

Create a second automation. The requirement is:

When the door changes from open to closed, turn off the living-room light.

Do not copy the solution immediately. Start with the automation that already works and decide which parts must change.

You must obtain:

  • A different alias.
  • The same trigger entity.
  • Reverse transition: from "on" to "off".
  • The light.turn_off action.
  • Same target.

Test both automations by toggling the door control. Opening the door should turn on the light; closing it should turn the light off.

See the explained solution

In the editor’s YAML view, the second automation can be written as follows:

alias: "YAML Course - Turn off light when closing the door"
description: >-
  Turn off the virtual living-room light when the practice door changes
  from open to closed.
triggers:
  - trigger: state
    entity_id: binary_sensor.course_front_door
    from: "on"
    to: "off"
conditions: []
actions:
  - action: light.turn_off
    target:
      entity_id: light.course_living_room
mode: single

The structure does not change. We modify the transition and operation because the new requirement describes the opposite path.

Keeping two automations is clear at this stage: each has one trigger and one result. In the next chapter, we will express multiple decisions and see when trigger IDs and choose make it sensible to combine related behaviors.

Deliberate error: pasting a list item into the individual editor

This block belongs to automations.yaml:

- id: "course_close_door_turn_off_light"
  alias: "YAML Course - Turn off light when closing the door"
  triggers:
    - trigger: state
      entity_id: binary_sensor.course_front_door
      from: "on"
      to: "off"
  conditions: []
  actions:
    - action: light.turn_off
      target:
        entity_id: light.course_living_room
  mode: single

If you paste this entire block into an individual automation’s YAML editor, you provide a list item where the editor expects one automation map. Do not “fix” the indentation at random. Remove the outer dash and understand that id belongs to the storage-file context.

The correct question before copying is always:

Does this fragment represent one automation, an item in automations.yaml, or the entire automation: section?

What should you take from this chapter?

An automation starts when one of its triggers fires, checks its conditions, and runs its actions. Our first automation has no conditions, but it keeps the section as an empty list.

The state trigger does not simply describe a value: it can describe a concrete transition by means of from and to. The action retains the same meaning as we already tested in Tools → Actions; now it is the automation engine that decides when to call it.

We also separated three tests: running one action, running the action sequence, and causing the real trigger to fire. Only the third exercises the complete behavior. The trace shows the path Home Assistant followed.

In the next chapter, we will extend the automation. Opening the door will no longer be enough: it must also be night, and someone must be home. We will then use choose to express different outcomes without hiding the logic inside a template.