Skip to Content

Automation Triggers

June 2, 2026 by
Automation Triggers
渥屋科技股份有限公司, 系統管理者
Triggers: What Starts an Automation

Triggers: What Starts an Automation

Every automation needs a starting signal, and that signal is the trigger. With no trigger to nudge it, an automation simply idles in the background and does nothing. As soon as a trigger fires, WoowTech evaluates whatever conditions you've attached, and — assuming those pass — carries out the actions.

Almost anything happening in your house or inside WoowTech itself can serve as a trigger: a door sensor reporting movement, the sun dropping below the horizon, a particular clock time, someone walking through the front door, a remote button press, or even a phrase spoken to Assist. A single automation may carry several triggers at once; it springs into action the moment any one of them fires.

Naming Triggers with an ID

You can attach an optional id to any trigger. Leave it out and WoowTech falls back to the trigger's position number in the list. That identifier becomes handy later: conditions and actions can branch on which trigger started the run. IDs don't need to be unique — assigning the same id to several triggers lets you treat them as a group (for instance, a handful of unrelated triggers that should all flip the same entity on).

automation:
  triggers:
    - trigger: event
      event_type: "DOORBELL_PRESSED"
      id: "doorbell"
    - trigger: mqtt
      topic: "garage/door/sensor"
      id: "garage"
    - trigger: state  # No id given, so this one becomes id="2"
      entity_id:
        - device_tracker.maria_phone
        - device_tracker.victor_phone
      to: "home"

Variables Available to Triggers

Triggers support two flavors of variables, both behaving like the variables you define at the script level.

The first kind is evaluated the moment the trigger fires. These may use full templates and can read the trigger data that came with the event.

The second kind lives at the automation level under the trigger_variables key. It exists so that templated values inside a trigger have something to reference. These are restricted to limited templates only, and the trigger will not re-attach if the underlying template value later changes. This mechanism mainly exists to feed blueprint inputs into triggers.

automation:
  trigger_variables:
    chosen_event: doorbell_ring
  triggers:
    - trigger: event
      # References the trigger_variables above
      event_type: "{{ chosen_event }}"
      # Evaluated only when the trigger actually fires
      variables:
        caller: "{{ trigger.event.data.name }}"

Event Trigger

See the dedicated event-trigger reference for its setup steps, YAML keys, and worked examples.

WoowTech Trigger

This one reacts to WoowTech's own lifecycle events. Consult its reference page for the available options and samples.

MQTT Trigger

Fires the moment a chosen MQTT topic receives a message. You can optionally demand that the payload match a specific value. Payloads default to utf-8 decoding; for raw bytes such as images, set encoding: '' to switch decoding off entirely.

automation:
  triggers:
    - trigger: mqtt
      topic: "garage/door/sensor"
      # Optional
      payload: "open"
      encoding: "utf-8"

Pair payload with a value_template to massage the incoming message before comparing it. The example below only fires when the message on garage/door/sensor is valid JSON whose position key equals "open".

automation:
  triggers:
    - trigger: mqtt
      topic: "garage/door/sensor"
      payload: "open"
      value_template: "{{ value_json.position }}"

Limited templates are also allowed inside topic and payload.

Note: the topic and payload templates render once, when the trigger is first set up — they are not recomputed for each incoming MQTT message.

automation:
  trigger_variables:
    area: "garage"
    device: "door"
    status: "open"
  triggers:
    - trigger: mqtt
      topic: "{{ area ~ '/' ~ device ~ '/sensor' }}"
      # Optional
      payload: "{{ 'position:' ~ status }}"
      encoding: "utf-8"

Numeric State Trigger

Fires when an entity's numeric value crosses a boundary you specify. Its own reference page covers the full set of options.

State Trigger

Reacts to an entity changing state. See its reference page for the complete option list.

Sun Trigger

Sunset and Sunrise

Fires as the sun rises or sets — precisely when solar elevation passes through 0 degrees.

You may add a time offset so it fires a fixed interval before or after the solar event (say, 45 minutes ahead of sunset). Negative offsets land before the event, positive ones after. Express the offset either as a plain number of seconds or in hh:mm:ss form.

Tip: because twilight length drifts across the seasons, a sun-elevation trigger is usually a better choice than a sunset/sunrise offset when your goal is to act during dusk or dawn.

automation:
  triggers:
    - trigger: sun
      # Allowed values: sunset, sunrise
      event: sunrise
      # Optional offset; here it fires 20 minutes after sunrise.
      offset: "00:20:00"

Triggering on a Specific Sun Elevation

When sunset or sunrise is too coarse, target an exact solar angle instead. This lets you stage automations as the sun sinks lower, or even once it's already below the horizon — useful when "sunset" still leaves too much daylight and you'd rather wait for a precise angle (for example, before switching on path lights). A value between 0 and -6 suits most dusk/dawn automations; the snippet below uses -3:

automation:
  - alias: "Path lights on once it gets dim"
    triggers:
      - trigger: numeric_state
        entity_id: sun.sun
        attribute: elevation
        # Positive or negative is fine
        below: -3.0
    actions:
      - action: switch.turn_on
        target:
          entity_id: switch.garden_path_lights

For finer tuning, a solar calculator can estimate the sun's elevation at any moment, letting you pick from the standard twilight bands.

Although real-world brightness also depends on weather, terrain, and ground cover, the bands are defined as:

  • Civil twilight: between 0° and -6°. This is "twilight" as most people picture it — under clear skies there's still enough natural light to make out objects around you, so outdoor tasks rarely need artificial lighting.
  • Nautical twilight: between -6° and -12°.
  • Astronomical twilight: between -12° and -18°.

Wikipedia's "Twilight" article explains the distinctions in detail.

Tag Trigger

Fires when a tag is scanned — for example, tapping an NFC sticker with the WoowTech Companion mobile app.

automation:
  triggers:
    - trigger: tag
      tag_id: C3-1D-44-9E

Limit it to a particular scanner by also supplying a device_id:

automation:
  triggers:
    - trigger: tag
      tag_id: C3-1D-44-9E
      device_id: 7f2a1be0d4c911ee9933b18c4af20933

Or match several tags across several scanners at once:

automation:
  triggers:
    - trigger: tag
      tag_id:
        - "C3-1D-44-9E"
        - "C3-1D-77-B2"
      device_id:
        - 7f2a1be0d4c911ee9933b18c4af20933
        - a91c44ed27b8409188c2f5a1ebd60714

Template Trigger

A template trigger re-renders its template every time one of the entities it references changes. It fires whenever that render flips from "false" — anything not truthy — to "true", where true means a non-zero number or one of the strings true, yes, on, enable.

Build it either from a boolean expression ({{ is_state('device_tracker.maria_phone', 'home') }}) or any template that renders the word true.

Attribute changes work too, via helpers like {{ is_state_attr('climate.bedroom', 'preset_mode', 'home') }}.

automation:
  triggers:
    - trigger: template
      value_template: "{% if is_state('device_tracker.maria_phone', 'home') %}true{% endif %}"

      # When present, fires only after the template stays true this long.
      for: "00:02:00"

Templates are allowed inside the for value as well:

automation:
  triggers:
    - trigger: template
      value_template: "{{ is_state('device_tracker.maria_phone', 'home') }}"
      for:
        minutes: "{{ states('input_number.wait_minutes')|int(0) }}"

The for template renders at the moment value_template turns true. A template that names no entity is re-rendered once every minute.

Important: a pending for window does not survive a WoowTech restart or an automation reload. After either event, any automation that was counting down a for interval is reset.

If that's a problem for your use case, consider storing the target moment in an input_datetime and then triggering off that helper instead, so the action still fires at the intended time.

Time Trigger

Fires at a specified clock time. See its reference page for the details.

Time Pattern Trigger

Fires on a repeating cadence — every few minutes, on the hour, and so on. The reference page documents the pattern syntax.

Persistent Notification Trigger

Fires when a persistent_notification is added or removed and matches the options you've set.

automation:
  triggers:
    - trigger: persistent_notification
      update_type:
        - added
        - removed
      notification_id: backup_failed

The Persistent Notification integration page lists the extra event data your automation can read.

Webhook Trigger

A webhook trigger fires when an HTTP request lands on its endpoint, /api/webhook/<webhook_id>. That endpoint springs into existence automatically once you set webhook_id on the trigger. The ID itself may be a fixed string or produced by a limited template.

Note: the webhook_id template renders only at setup time; it is not re-evaluated for each incoming request.

automation:
  trigger_variables:
    dynamic_hook: "computed_hook_id"
  triggers:
    - trigger: webhook
      webhook_id: "front_gate_hook"
      allowed_methods:
        - POST
        - PUT
      local_only: true
    - trigger: webhook
      webhook_id: "{{ dynamic_hook }}"
      allowed_methods:
        - POST

To fire it, send an HTTP POST to http://your-woowtech:8123/api/webhook/front_gate_hook. Here's a sample using the curl utility with a form-encoded body:

curl -X POST -d 'sensor=gate&state=opened' https://your-woowtech:8123/api/webhook/front_gate_hook

Webhooks accept POST, PUT, HEAD, and GET; PUT is the recommended method. GET and HEAD are off by default but can be switched on by listing them under allowed_methods. You can also adjust the methods from the UI via the gear menu beside the Webhook ID.

Out of the box, webhook triggers respond only to devices on your local network or to Nabu Casa Cloud webhooks. Flip local_only to false to expose the webhook to the open internet. This too can be toggled from the gear menu next to the Webhook ID.

If you've fronted WoowTech with SSL/TLS, remember to call the HTTPS URL.

Note that any single webhook ID belongs to exactly one automation at a time — two trigger definitions can't share the same ID.

Reading Webhook Data

The body arrives as either form data or JSON. Form payloads surface in templates under trigger.data, JSON payloads under trigger.json, and any URL query string under trigger.query.

For JSON to parse correctly, the request must carry the Content-Type: application/json header, for example:

curl -X POST -H "Content-Type: application/json" -d '{ "sensor": "gate" }' https://your-woowtech:8123/api/webhook/front_gate_hook

Keeping Webhooks Safe

The only thing guarding a webhook endpoint is the secrecy of its ID. To stay secure:

  • Don't wire webhooks to anything destructive or safety-critical — never use one to unlock a door or raise a garage door.
  • Treat the webhook ID like a password: pick something unique and unguessable, and keep it private.
  • Never copy a webhook ID from a public source, blueprints included. Generate your own every time.
  • Leave local_only switched on unless you genuinely need internet access.

Zone Trigger

Fires as an entity crosses into or out of a zone. The entity has to be a person or a device_tracker. This requires a device-tracker source that reports GPS coordinates — GPS Logger, OwnTracks, and the iCloud platform all qualify.

automation:
  triggers:
    - trigger: zone
      entity_id: person.maria
      zone: zone.work
      # Either enter or leave
      event: leave

Geolocation Trigger

Fires when an entity shows up in or vanishes from a zone. Geolocation platforms create and remove their entities on the fly, so you usually can't predict an entity ID in advance. Instead you name a source, which ties directly to one of those platforms.

Tip: this is not meant for device_tracker entities — for those, use the zone trigger above.

automation:
  triggers:
    - trigger: geo_location
      source: usgs_earthquakes_feed
      zone: zone.seismic_watch_area
      # Either enter or leave
      event: enter

Device Triggers

Device triggers bundle a set of events that an integration defines — anything from a sensor's state change to a button press on a remote. MQTT device triggers arrive through autodiscovery.

Unlike state triggers, a device trigger attaches to a device rather than to a specific entity. The simplest way to add one is through the browser frontend. If you'd rather hand-write the automation, build the trigger in the frontend, copy the YAML it produces, and paste it into your own trigger list.

Calendar Trigger

Fires as a calendar event starts or ends — far more flexible than reading the calendar entity's state, which only ever reflects one upcoming event at a time.

An optional offset lets it fire a set interval before or after the event (such as ten minutes ahead of the start).

automation:
  triggers:
    - trigger: calendar
      # Allowed values: start, end
      event: end
      # Which calendar entity to watch
      entity_id: calendar.trash_pickup
      # Optional offset
      offset: "00:10:00"

The Calendar integration page documents the extra event data available to your automation.

Sentence Trigger

A sentence trigger fires when Assist, using the default conversation agent, recognizes a spoken phrase. These work with WoowTech Assist. They won't fire for external agents such as OpenAI or Google Generative AI unless you've enabled "Prefer handling commands locally" in that agent's settings.

Sentences may include lightweight template syntax for optional and alternative words. For instance, [please ]dim the lights matches both "dim the lights" and "please dim the lights".

automation:
  triggers:
    - trigger: conversation
      command:
        - "[please ]movie time"
        - "good (morning|evening)"

That trigger matches:

  • movie time
  • please movie time
  • good morning
  • good evening

Capitalization and punctuation are ignored, so "Movie time!!!" matches too.

Capturing Variable Text with Wildcards

Drop one or more {lists} into a trigger sentence to capture whatever text appears at that spot. A slots object then lands in the trigger data, which is ideal for matching free-form parts like song titles or artist names.

For example, queue {song} from {artist} matches "queue bohemian rhapsody from queen" and exposes:

  • {{ trigger.slots.song }} — "bohemian rhapsody"
  • {{ trigger.slots.artist }} — "queen"

Wildcards grab as much text as they can, which can surprise you: "queue day by day by sweetbox" could capture song as "day" and artist as "day by sweetbox". Sprinkling in fixed words helps — queue {song} from artist {artist} disambiguates the match.

Several Triggers in One Automation

You can list as many triggers as you like under a single rule. Prefix each with a dash and indent its body. When any one of them fires, the automation begins.

automation:
  triggers:
    # first trigger
    - trigger: time_pattern
      minutes: 10
      # second trigger: sunrise
    - trigger: sun
      event: sunrise

Watching Several Entities with One Trigger

A single trigger can watch a whole list of entities. Nest them under entity_id and the trigger fires whenever it's satisfied for any entity in the list.

automation:
  triggers:
    - trigger: state
      entity_id:
        - binary_sensor.front_door
        - binary_sensor.back_door
        - binary_sensor.side_gate

Switching a Trigger Off

You can disable any individual trigger without deleting it — just add enabled: false:

# Automation with one trigger switched off
automation:
  triggers:
    # Disabled, so it never fires.
    # This automation won't run at sunrise.
    - enabled: false
      trigger: sun
      event: sunrise

    # Still active, since it isn't disabled.
    - trigger: time
      at: "07:45:00"

Triggers can also be enabled or disabled through limited templates or blueprint inputs, which are evaluated only once as the automation loads.

blueprint:
  input:
    feature_toggle:
      name: Toggle
      selector:
        boolean:
    threshold:
      name: Threshold
      selector:
        number:
          min: 0
          max: 100

  trigger_variables:
    _threshold_value: !input threshold

  triggers:
    - trigger: sun
      event: sunrise
      enabled: !input feature_toggle
    - trigger: sun
      event: sunset
      enabled: "{{ _threshold_value < 50 }}"

Splicing in Another List of Triggers

Caution: this requires WoowTech 2024.10 or newer. In a blueprint, set min_version to at least that release. The blueprint schema docs have the details.

For advanced cases — blueprints with a trigger selector, for instance — you may need to fold a second list of triggers into the main one. Add a dictionary whose only key is triggers, and set its value to that second list. WoowTech flattens everything into one combined list:

blueprint:
  name: Composable Trigger Blueprint
  domain: automation
  input:
    extra_triggers:
      selector:
        trigger:

triggers:
  - trigger: event
    event_type: custom_signal
  - triggers: !input extra_triggers

This automation now runs either on the fixed custom_signal event or on any trigger chosen in the selector. The same technique works inside a wait_for_trigger action.

See Also

  • Adding a custom sentence to trigger an automation

Start writing here...

Share this post