Automations · Home Assistant

Scripts and Scenes.

Reading time
~17 min · 3,426 words
FAQ
0 questions
Status
Draft 1 · under review
Section
All Home Assistant pages

A script in Home Assistant is a named, reusable sequence of actions that other automations can call. A scene is a captured snapshot of entity states that can be restored on demand. Both reduce duplication in a Home Assistant configuration: a script encapsulates logic that many automations share, so a change made once affects everywhere the script is called; a scene captures a set of target states — "day mode for Greenhouse Zone 1" — that can be applied by any automation or by the grower directly. For agricultural operations, scripts carry the common procedures (fertigation cycles, startup and shutdown sequences, alert formatting, cooling escalations) and scenes carry the operational modes (day, night, emergency cooling, winter mode, propagation setpoints). This page covers the distinctions between scripts, scenes, and automations, the patterns that fit each tool, how to pass data into scripts as parameters, how scenes interact with automations, and the failure modes that affect both.

Before building scripts and scenes.

Prerequisites from earlier pages:

Automation basics in hand. [Automation Fundamentals](/home-assistant/automations/fundamentals) covers the trigger-condition-action model that scripts and scenes plug into. Scripts are the actions that automations call; scenes are the state targets that automations apply.

Areas and naming conventions established. Per [Organizing Home Assistant for a Farm](/home-assistant/agriculture/organizing). Scripts and scenes are entities themselves — `script.fertigationcycle`, `scene.greenhousezone1day_mode` — and a clear naming convention matters as the count grows.

A sense of what gets repeated. Scripts and scenes exist to eliminate duplication. An operation that has not yet built enough automations to notice the duplication does not need either of these tools. By the tenth automation, the repetition starts showing up; by the twentieth, scripts and scenes become obvious.

What a script is.

A script is a named sequence of actions, stored as its own entity. Any automation, any service call, any dashboard button, or any other script can invoke it. The actions inside a script are the same kinds available in an automation — service calls, delays, waits, choose blocks, parallel sections, repeats — but a script has no trigger. It runs when something calls it.

The shape of a script. A script has an alias (the human name), an ID (the stable identifier), an optional description, optional fields (parameters the caller provides), and a sequence of actions. That is the whole structure.

Scripts are services. Every script registers itself as a service in Home Assistant — `script.fertigationcyclezone_1` is callable from any other automation, from a dashboard button, from the REST API, from voice assistants, from anywhere services are callable. This uniform interface is what makes scripts powerful: the same shared logic is accessible from every corner of the system.

Scripts can take parameters. A well-designed script accepts parameters through its `fields` definition. A "send alert" script that takes the message, the priority, and the target device as parameters works for every kind of alert the operation generates, instead of requiring a dedicated script per alert type.

Scripts have modes, like automations. Each script specifies a mode — single, restart, queued, parallel — that controls what happens when the script is called again while a previous run is executing. The same considerations from [Automation Fundamentals](/home-assistant/automations/fundamentals) apply. Most shared-logic scripts work well in `mode: parallel` because each caller should get its own run without interfering with others.

Scripts produce a response variable. Modern Home Assistant scripts can return a value to their caller, using the `stop` action with `response_variable`. An automation that calls a script can receive data back — the result of a calculation, a status code, a formatted message. This turns scripts into more than just one-way action sequences.

What a scene is.

A scene is a named set of entity states. When the scene is activated, Home Assistant sets each of the listed entities to its captured state.

The shape of a scene. A scene has an alias, an ID, optional icon, and an `entities` block listing each entity and its desired state. "Scene `greenhousezone1daymode`: temperature setpoint 75°F, humidity setpoint 65%, ventilation stage 2, supplemental lighting auto, irrigation auto." Activating the scene sets all of those at once.

Scenes are declarative, not procedural. A scene describes what should be, not how to get there. When activated, Home Assistant sets each entity to its target state directly. There is no sequence, no delays, no conditional logic — a scene is a picture of a desired configuration that gets applied. For logic that needs sequence or branching, a script is the right tool; for restoring a configuration, a scene is.

Scenes can be captured live. The `scene.create` service can snapshot current entity states into a temporary scene. This is useful for "save current state before making a change, then restore after" patterns — a maintenance mode that captures the live state, runs whatever is needed, then restores everything back to where it was.

Scenes work across domains. A single scene can set states on switches, lights, climate entities, covers, fans, input helpers, and more. An "emergency cool" scene opens vents, runs fans at full, closes curtains against sun, sets the climate setpoint, and turns supplemental lights off — one activation, coordinated change across many systems.

Scripts versus scenes versus automations.

Each of the three tools has a different shape and a different best fit.

Automations have triggers. They run when something specific happens — a sensor crosses a threshold, a time of day arrives, a template goes true. An automation is what watches for events and responds to them.

Scripts have no triggers. They run when called. A script is reusable procedural logic — a sequence of actions that many automations (or the grower directly) might want to run.

Scenes have no logic. They are state targets. A scene is what should be, expressed as entity states; applying it makes those states real.

The decision matrix. When something should happen in response to an event — automation. When the same sequence of actions needs to run from many different places — script. When a set of entity states needs to be applied as a unit — scene.

How they combine. An automation watches for a condition (its trigger), and as its action, activates a scene (setting multiple target states), or calls a script (running a shared sequence of actions). The three tools fit together. Most substantial agricultural deployments use all three.

An example of the combination. Consider a greenhouse cooling escalation. The automation watches temperature crossing 85°F. The script it calls runs the cooling escalation sequence — opens vents, waits two minutes, checks temperature, starts fans if still too warm, waits two minutes, checks again, opens roof vents if still too warm. The scene it can fall back to — emergency cooling — is a pre-defined "everything on maximum" configuration for the worst case. Automation listens, script decides, scene configures.

Calling scripts.

Scripts can be invoked from several places.

From automations. The typical pattern. An automation's action calls the script by service name: `script.fertigationcyclezone1`, or the equivalent `script.turnon` targeting the script entity. Parameters flow through the `data` or `variables` fields on the service call.

From other scripts. A script can call another script. Useful for factoring a complex operation into smaller pieces — a "morning startup" script can call "open vents," "start irrigation check," and "send morning status" scripts in sequence.

From the UI. Scripts can be exposed on dashboards as buttons. A dashboard button labeled "Run Fertigation Cycle Now" calls the script when tapped. Useful for operations where the grower wants manual-run capability alongside the automations that run things on schedule.

From voice assistants. Scripts exposed to a voice assistant can be invoked by name. "Run the cooling sequence" is a useful voice command in an operation that benefits from hands-free control in the greenhouse.

From the REST API or MQTT. External systems can invoke scripts through Home Assistant's REST API or through MQTT commands. This opens scripts to integration with scheduling systems, field devices, or other platforms.

Script fields (parameters).

A script with `fields` defined is a parameterized service — callers pass values in, and the script uses them.

Why parameters matter. A "send alert" script with no parameters is a single fixed alert. A "send alert" script that takes `message`, `priority`, and `target` as parameters is a general-purpose notification routine that every automation can call with its own specifics. One script, many uses.

Field types. Home Assistant supports typed fields through selectors — text, number, entity picker, device picker, boolean, time, target selector. Selectors make the script callable from the UI with proper input controls and let the UI validate inputs.

Defaults. Fields can have default values. A script parameter that is usually the same (priority defaulting to "normal," target defaulting to the main phone) but can be overridden for specific cases has a default. Callers override only when they need something different.

Required versus optional. Fields can be marked required. A missing required field produces an error at call time rather than silently running with a nothing value.

Using field values in the script. Inside the script, field values are available as Jinja2 template variables. A field named `message` becomes `{{ message }}` in the actions. Service calls pass the values into notification services, conditional checks use them, loops iterate over them.

Agricultural script patterns.

Scripts that come up repeatedly in agricultural deployments.

The fertigation cycle. Accepts parameters for zone, nutrient recipe, duration, and flush duration. Opens the appropriate valves, runs the injection, flushes, closes the valves. Called from scheduled automations for routine fertigation, from manual-start automations for one-off runs, and from the UI when the grower wants to trigger a cycle directly.

The cooling escalation. Accepts parameters for zone and target temperature. Steps through the cooling measures in order — open vents, wait, check; start fans, wait, check; open roof vents, wait, check — and exits when the target is reached or the measures are exhausted. Called by the "high temperature" automation for each zone. One script handles the logic for all zones.

The alert formatter. Accepts parameters for zone, metric, value, severity, and target device. Builds a formatted message from the parameters, routes it to the appropriate notification service with the appropriate priority, and logs the event. Called by every alert automation, so alert formatting is consistent across the operation.

The startup sequence. No parameters. Runs at Home Assistant startup or when called manually. Checks each zone's sensors are reporting, verifies critical automations are enabled, sends a morning status summary to the grower. The startup script is the place to put "things the system should verify after a restart."

The graceful shutdown. No parameters. Runs before planned maintenance. Puts each zone into a safe state (closes vents that were open, turns off supplemental that was running, sets irrigation to manual mode), sends a confirmation the system is in safe state, then logs the shutdown. Useful when the grower plans to take the Home Assistant host offline for updates or hardware work.

The zone status report. Accepts a zone parameter. Builds a multi-line status summary for that zone — current temperature, humidity, VPD, DLI, soil moisture, last irrigation, current automation state — and returns it as a response variable or sends it through a notification. Useful for both scheduled daily summaries and on-demand "how is Zone 3?" queries.

The safe-valve-close. Accepts a valve parameter. Commands the valve closed, waits, verifies closure through flow or pressure or state feedback, retries if needed, and alerts if the valve does not confirm closed after the configured number of retries. Called by any automation that needs to close a valve safely rather than just commanding the close and hoping.

Agricultural scene patterns.

Scenes that show up repeatedly.

Day mode. Temperature setpoints for daytime, humidity targets for daytime, ventilation stage for normal operation, irrigation schedule active, supplemental lighting on DLI control. The collection of states that represent "the zone is in normal production mode during daylight."

Night mode. Lower temperature setpoints (many crops benefit from a night drop), higher humidity tolerance, supplemental lighting off (for photoperiod-sensitive crops during dark period), ventilation minimal. The nighttime counterpart to day mode.

Emergency cool. All fans on, all vents open, roof vents open, curtains retracted, supplemental lights off, climate setpoint lowered. The worst-case response applied as a single activation. An automation triggered by a runaway temperature alarm applies this scene and alerts the grower.

Winter mode. Ventilation minimized, heating setpoints active, supplemental lighting schedules longer to compensate for shorter days, irrigation reduced to the winter pattern. The seasonal configuration applied at the start of the cold season.

Summer mode. Ventilation maximum, heating off, shade curtains in the daytime, supplemental lighting limited to early and late day, irrigation more frequent. Seasonal summer configuration.

Propagation mode. Tight temperature control, high humidity, gentle ventilation, close monitoring alerts active. Applied when a zone shifts to propagation duty.

Flowering mode. Strict photoperiod control, specific temperature differential between day and night, reduced irrigation for specific varieties. Applied when a zone shifts to flowering.

Maintenance mode. Automations paused, setpoints held, alerts suspended for the zone being worked on. Applied before a grower goes into a zone to work, so that the act of opening doors or moving equipment does not trigger a flurry of alerts.

Scene activation patterns.

Several patterns for how scenes are used.

Apply a static scene. The most common pattern. `scene.turn_on` with the scene entity ID activates the scene and sets all its entities to their captured states. A timed automation applies day mode at 06:00 and night mode at 20:00.

Snapshot-and-restore. `scene.create` captures current state into a temporary scene at the start of an operation; a later `scene.turn_on` restores it. Useful for maintenance — capture current state, switch to maintenance mode, do the work, restore original state.

Transition through scenes. An automation can apply a sequence of scenes with delays between them. "Ramp into day mode" might apply morning-transition at 06:00, day-mode at 06:30, full-production at 07:00. Each scene is a stable target; the delays give the controlled equipment time to reach each stage.

Scene as fallback. A complex script that exhausts its options can apply a known-safe scene as its final action. If cooling escalation runs through its full sequence without reaching the target temperature, apply the emergency-cool scene and alert the grower. The scene is the safety floor.

Scene with override. A scene sets defaults, then the automation makes per-case adjustments. Apply "flowering mode" scene for the general target, then override the photoperiod setpoint based on the current crop's specific schedule. Scenes-as-baselines-with-overrides is a common pattern in operations with many crops in different cycles.

Testing scripts and scenes.

Scripts and scenes are as testable as automations, and testing matters as much.

Manual execution. Scripts can be run from the UI, from Developer Tools → Services, or from the script's own detail page. Scenes activate the same way. Manual execution is the first test — does this do what I expect?

Parameterized script testing. A script with fields can be tested with different inputs through the UI editor, which builds a form from the field definitions. Useful for verifying that the script handles different parameter values correctly, including edge cases.

Trace viewer. Scripts produce traces like automations do. Each run's trace shows the actions that ran, the responses from service calls, and any errors. Traces are the primary debugging tool.

Test scenes by applying them. Apply a scene and observe what changes. For scenes with many entities, the UI's scene editor shows each entity's current state versus the scene's target state, which makes it easy to spot mismatches.

Test sequencing. Scripts that call other scripts, or automations that chain scripts and scenes, benefit from end-to-end testing after any change. A change to a leaf script can ripple through many callers; running the full sequence once catches breaks that unit-level tests miss.

Common failure modes.

Specific scripts-and-scenes problems from real operations.

The script that got stuck waiting for a condition that never happened. A `waitfortrigger` inside the script had no timeout; a valve that failed to confirm its state caused the script to hang indefinitely. Every call after that queued up (or was ignored, depending on mode), and the automation that relied on the script stopped working. Fix: always set timeouts on waits; use modes carefully; add a watchdog that alerts on long-running script instances.

The scene that did not include a critical entity. "Emergency cool" opened the vents and turned on fans but did not turn off supplemental lighting. The lights kept dumping heat in. Fix: review emergency scenes for completeness; include all entities that affect the target condition; document what each scene covers.

The script that worked for one zone and failed for another. The script hardcoded `switch.greenhousezone1_fan` instead of accepting a zone parameter. When called for Zone 2, it controlled Zone 1's fan. Fix: parameterize scripts; any value that varies by caller should be a field, not a constant.

The scene that captured unavailable entities. A `scene.create` snapshot was taken while a sensor was briefly unavailable. When the scene was restored, the entity snapshot was "unavailable," which Home Assistant applied as an attempt to set the entity to unavailable — producing confusing errors. Fix: verify entities are available before snapshotting; handle unavailable entities explicitly in scene definitions.

The script that called another script that no longer existed. A script was renamed; callers that referenced the old name silently failed to do anything on the rename step. Fix: search for references before renaming; use descriptive IDs that are unlikely to be renamed frequently; or treat script IDs as stable interfaces that evolve rarely.

The scene whose entity states drifted. A "day mode" scene was defined once; over time new entities were added to the zone (a new fan, a new sensor) that the scene did not include. Applying day mode left the new entities in whatever state they were in, which was usually wrong. Fix: review scenes when entities are added; treat scenes as configuration that needs maintenance, not static one-time definitions.

The script that ran concurrently when it should not have. A fertigation script in `mode: parallel` got called twice in quick succession; both runs tried to open the same valve at the same time, producing confused behavior. Fix: choose the script's mode to match what it controls — `queued` if calls must run one at a time, `restart` if the most recent call should take priority, `single` if only one should run at all.

The scene activation that fought an automation. A grower manually activated "winter mode" during a warm spell in winter. The automation that had been setting day-mode setpoints kept re-applying them; the result was oscillation. Fix: automations and manual scene activations should not fight — use input helpers or flags to suppress competing automations during manual overrides, and make the override clear in the UI.

What not to do.

Patterns to avoid.

Don't put scripts inline in every automation. If five automations each have the same three-step action sequence, factor those steps into a script. The automations become shorter, the logic is in one place, and future changes happen once.

Don't use scripts for what automations should do. A script with no callers, invoked by a single time-based or state-based rule, should probably just be an automation. Scripts earn their place by being reusable.

Don't use scenes for what automations should do. A scene changes entity states directly; an automation runs logic. "When moisture drops, start irrigation" is an automation; "apply these target states" is a scene. A scene that tries to embed logic is working against the tool.

Don't forget that scripts are services. Every script is callable from anywhere. A critical script should have appropriate safeguards — conditions inside it that verify the operation is appropriate, logging so its calls are traceable, and clear documentation of what it does and when it should be called.

Don't overload one script with too many responsibilities. A script that does fertigation, alerting, logging, and shutdown is harder to debug than four focused scripts. Smaller scripts are easier to test and easier to reuse.

Don't skip parameter validation. A script that accepts a zone parameter and assumes the zone exists will fail confusingly when called with a typo. A quick check at the start of the script (condition: the zone's sensors are available) produces a clear error rather than a cascade of service-call failures.

Don't let scenes become invisible. A scene with 40 entities in it, applied by many automations, is doing a lot. Document what each scene represents and what entities it covers. The `description` field on scenes is not there for decoration.

Don't freeze scripts and scenes in version 1. Both are configuration. They need review as the operation evolves. A script written for the first greenhouse may need updating when the operation expands to four greenhouses. Scheduled review — quarterly or semi-annually — catches drift before it causes problems.