If Home Assistant restarts, its automations stop running until it comes back. Moving a few Zigbee-only rules into zigbee2mqtt-automations can keep them out of that restart window. It is a third-party extension, rather than a built-in Zigbee2MQTT automation engine, and loads through the external extensions API.
A hallway light or door chime is a good example of a rule you might want to keep working during an HA update. Zigbee2MQTT, the coordinator and the devices still need to stay running. If the extension uses state supplied by Home Assistant, that input also stops being refreshed while HA is down.
Zigbee2MQTT has no automations feature of its own
There’s no setting to toggle and no hidden config block. The capability comes from zigbee2mqtt-automations, a project maintained by Luligu (also known for the Matterbridge Zigbee2MQTT plugin) and built on Zigbee2MQTT’s official Extensions API. Our piece on Zigbee2MQTT extensions vs external converters already covers how that extension mechanism works in general. This is the same mechanism, aimed at one specific job.
It isn’t the only community project to have attempted this — Anonym-tsk/zigbee2mqtt-extensions describes itself as a way to create simple automations directly in Zigbee2MQTT as well. This guide covers Luligu’s extension; compare compatibility and maintenance before choosing another project.
Extensions load through the same enable_external_js gate as any other Zigbee2MQTT extension. Since Zigbee2MQTT 2.11.0, that setting is disabled by default on new installations — external extensions and external converters were both switched off by default as a security hardening measure. Check the advanced section of your configuration.yaml before assuming an extension will load.
What zigbee2mqtt-automations actually does
The extension gives you a trigger/condition/action model, similar in shape to what Home Assistant automations look like, except it runs inside the Zigbee2MQTT process itself.
| Piece | Options |
|---|---|
| Triggers | Time-of-day (HH:MM:SS), sun-relative (sunrise, sunset, dawn, dusk, needs latitude/longitude and an optional elevation offset), or event-based (an entity’s state or attribute changing, with an optional minimum duration before it fires) |
| Conditions | Time-based (after, before, between, plus weekday filters) or event-based (state or attribute comparison using equal, above, or below) |
| Actions | Send a payload through Zigbee2MQTT’s internal command handling to control an entity (turn on, turn off, toggle, or a supported payload object), run a defined scene, or apply a delayed turn-off with its own configurable off-payload |
Any one trigger is enough to start evaluating an automation; every condition attached to it has to be true before the action fires. Multiple triggers and actions are supported, while conditions can be supplied as a list.
Installing it: file-based or through the frontend
There are two install paths, the same two our extensions article describes for any Zigbee2MQTT extension.
data/
configuration.yaml
automations.yaml
scenes.yaml
external_extensions/
automation.js
For a file-based install, copy the project’s compiled dist/automation.js to data/external_extensions, creating the folder if needed. Stop Zigbee2MQTT completely, then start it again. Alternatively, open Extensions in the frontend, add automation.js, replace the editor’s sample with the compiled file’s complete contents and save.
Enable advanced.enable_external_js if it is disabled, then check the log for the extension loading and any configuration validation errors. After changing automations.yaml or scenes.yaml, select automation.js in Extensions and save it to reload both files.
Where automations.yaml and scenes.yaml actually live
Create automations.yaml and scenes.yaml in Zigbee2MQTT’s data/ directory, next to configuration.yaml. The automation definitions belong in those files, not inside the main configuration.
Each automation in that file is a top-level entry keyed by its own name. Underneath it, trigger and action are required and condition is optional. Two switches sit alongside them: active, which defaults to true and lets you park an automation without deleting it, and execute_once, which defaults to false.
Here’s the shape, adapted from the example in the project’s README to the door-chime case from the top of this article:
Front door opened:
trigger:
entity: Front door sensor
attribute: contact
equal: false
condition:
entity: At home
state: ON
action:
entity: Hallway chime
logger: info
payload: turn_on
turn_off_after: 2
This example uses the README’s documented fields and has not been run on our hardware. Replace all three friendly names with entities that exist in your Zigbee2MQTT instance, and use a chime or relay that accepts state: ON/OFF. A siren requiring a warning payload needs a different action.
There are three details to check. The entity values are Zigbee2MQTT friendly names, written the way they appear in your device list, not IEEE addresses — the README’s own example names devices “Contact sensor” and “Aqara switch T1”. Second, equal: false on the contact attribute is the open state: Zigbee2MQTT reports contact: true while the magnet is closed, which is why the README calls its version of this example “Contact sensor OPENED”. Check your model’s device page and its actual open/closed reports before relying on the polarity. Third, turn_off_after is in seconds; this example sends OFF after two seconds. That turns off the target relay or chime but does not define a sound for every siren model.
The condition is the part most worth adapting. At home is just another entity checked for a state value, which is how you stop a chime firing while nobody’s in. If At home is updated by HA or another external service, its last state can become stale while that service is down. Remove the condition or replace it with a suitable local input if the chime must remain independent of HA. Conditions can also be time-based (after, before, between, and a weekday filter), and more than one condition on a single automation goes in a YAML list. Full option lists, sun-position triggers and scenes syntax are all in the README, which stays the reference for anything past this shape.
The extension’s scenes.yaml defines named lists of actions, including nested scenes. These are not the Zigbee scenes stored on devices and recalled with scene_recall. Our Zigbee2MQTT groups versus scenes guide explains that separate device-level mechanism.
The real reason to use this, and the claim that doesn’t hold up
The extension evaluates a Zigbee2MQTT state change inside the process, so that rule does not wait for Home Assistant to receive the event and run an automation. That removes HA from the rule’s execution path; it does not guarantee a particular latency improvement on your hardware.
The extension’s current action code feeds commands into Zigbee2MQTT’s internal message handling rather than publishing them through the broker. Local rules may therefore continue during a broker disconnection after startup. This is different from guaranteeing that every automation works throughout an outage.
Zigbee2MQTT needs a broker connection during startup before extensions start, as shown in its startup code. External MQTT triggers and broker-delivered inputs also need the broker, and state updates cannot reach HA while it is disconnected. Test an HA restart and a broker outage separately if either matters to you.
For a compatible remote and light, direct Zigbee binding is another option: the devices exchange supported commands without the automation software. It is useful for simple on/off or dimming control, but does not replace the extension’s conditions, schedules or sensor logic.
Triggering automations manually over MQTT
Automations don’t only run on their own defined triggers. You, or Home Assistant, or any other MQTT client, can fire one on demand by publishing “execute” to zigbee2mqtt-automations/[Name]. Scenes work the same way through zigbee2mqtt-scenes/[Name]. Our breakdown of Zigbee2MQTT’s MQTT topic structure covers the broader request/response pattern this borrows from. Home Assistant can call one of these rules while it is running, while the extension evaluates its own local triggers independently. Manual MQTT requests still require the broker.
Security: the same enable_external_js exposure as any other extension
Because this loads through enable_external_js, it inherits the same posture as any other Zigbee2MQTT extension. It’s arbitrary JavaScript running inside a process that has full internal access to Zigbee2MQTT’s state and MQTT connection. That’s precisely why the default flipped in 2.11.0.
Review the code you enable with enable_external_js and its current compatibility notes. Any code loaded this way has the same trust level as Zigbee2MQTT’s own core, not a sandboxed plugin. And if your broker isn’t locked down, that’s the bigger gap to close first — our MQTT broker security checklist covers hardening it.
Should this replace Home Assistant automations?
Keep HA automations for rules that need its integrations, UI editor or blueprints. This extension covers a smaller set of time, sun and entity-event triggers. It is most useful when all the inputs and outputs already belong to the same Zigbee2MQTT instance.
Start with one rule whose behavior you can test during an HA restart. If Zigbee2MQTT itself runs as an HA OS app, restarting Home Assistant Core is different from rebooting the host: a host reboot also stops Zigbee2MQTT and the extension.
Frequently asked questions
Does Zigbee2MQTT have built-in automations like Home Assistant?
No. Zigbee2MQTT ships no automation engine. Any automation capability inside it comes from a third-party extension loaded through the Extensions API — most commonly zigbee2mqtt-automations.
What is zigbee2mqtt-automations and who maintains it?
An open source, Apache-2.0-licensed extension for Zigbee2MQTT’s Extensions API, maintained by Luligu, who also maintains the Matterbridge Zigbee2MQTT plugin. Version 3.0.0 added scenes support in September 2025.
Do Zigbee2MQTT automations keep running if Home Assistant is down?
Yes, because they run inside the Zigbee2MQTT process itself rather than depending on HA to evaluate them. Zigbee2MQTT and the radio must remain running, and the rule must not depend on stale HA-supplied inputs. Current actions run through internal message handling; broker startup and external MQTT requests have separate dependencies, explained above.
Where do I put the automations.yaml file for Zigbee2MQTT?
In Zigbee2MQTT’s data/ directory, alongside configuration.yaml, not inside it. Scenes go in a separate scenes.yaml file in the same directory.
What does a Zigbee2MQTT automation actually look like?
A named top-level entry in automations.yaml with a required trigger and action and an optional condition. Triggers match on an entity’s attribute or state (or on a time or sun position), and actions feed a payload such as turn_on into Zigbee2MQTT’s command handling for the target entity, optionally with turn_off_after in seconds. See the worked example above, adapted from the project’s README.
Can I trigger a Zigbee2MQTT automation manually over MQTT?
Yes. Publish “execute” to zigbee2mqtt-automations/[Name] for an automation, or zigbee2mqtt-scenes/[Name] for a scene.
What this research verified
The installation paths, YAML fields and manual MQTT topics were checked against the project’s README. The source code confirms that rules listen to Zigbee2MQTT state changes and feed actions into internal command handling; Zigbee2MQTT’s startup code still requires an initial broker connection. The external-extensions documentation confirms the enable_external_js gate.
We have not installed or tested this extension on our own hardware. The worked example is an adaptation of the documented format, and the actual outage behavior depends on the installed versions, devices and rule inputs. Check the repository’s current compatibility notes before updating Zigbee2MQTT or relying on a rule during maintenance.
