---
name: home_assistant_routines
description: Build whole-home Home Assistant routines an agent can trust: automations and scripts with safety confirmations before risky actions, presence-aware logic, and failure fallbacks that keep the house sane when devices flake. Use when creating or reviewing HA automations and scripts, gating a risky action behind human approval, making behavior depend on who is home, or hardening a routine against flaky devices and missed responses.
---

# Home Assistant Routines

## Purpose

Thin per-device automations pile up into a mess that misfires at 2 AM. A routine is a whole-home job designed end to end: what starts it, what must be true, what it asks before acting, what it does when nobody answers, and what it does when a device fails.

This skill turns a plain request ("arm the house when everyone leaves") into a routine that:

- Asks for human confirmation before anything risky or hard to undo.
- Reacts to who is home, not just to sensor noise.
- Keeps working when a device flakes, a phone is on silent, or HA restarts mid-run.

It covers automations (triggered, with conditions) and scripts (started on demand, no triggers). Both use the same actions and building blocks: `choose`, `if`/`then`, `wait_for_trigger`, `wait_template`, `repeat`, `delay`, `parallel`. Verified against the official HA docs and the companion app docs; links in `references/sources.md`.

## Workflow

Follow these steps in order. Do not skip the safety steps.

### 1. Write the job in one sentence

One verb, one outcome, one trigger moment. "When everyone leaves, ask whether to arm the alarm, then arm it or leave it." If you cannot state it in one sentence, the routine is two routines.

### 2. Map it to triggers, conditions, actions

- **Triggers**: the moments the job starts. Prefer state changes of a `person` or zone over raw device trackers.
- **Conditions** ("And if"): what must be true at start time. Presence, time windows, security states.
- **Actions** ("Then do"): the steps, top to bottom. Keep the sequence short; move branches into `choose`.

### 3. Pick automation, script, or blueprint

- **Automation** when the house starts it on its own (presence change, time, sensor event).
- **Script** when a human, dashboard button, voice assistant, or another automation starts it (good night, leaving, movie mode).
- **Blueprint** when the same routine repeats with different devices or people. Build it once, parameterize the inputs.

### 4. Add the confirmation layer

Any step that is risky, hard to undo, or security-relevant gets a human gate first. The proven pattern is the confirmable notification script (details and full YAML in `references/confirmations.md`):

1. Build unique action IDs from the run context: `action_arm: "{{ 'ARM_' ~ context.id }}"`. Never reuse a fixed ID across runs; stale taps from an old notification would fire the wrong run.
2. Send a mobile notification with `actions:` (Confirm / Dismiss buttons).
3. `wait_for_trigger` on `platform: event`, `event_type: mobile_app_notification_action`, matching your unique action IDs. Set a `timeout`. Never wait forever; a phone on silent is a normal state.
4. `choose` on `wait.trigger.event.data.action` to run the confirmed step, the dismissed step, or the timeout fallback.
5. Pick the automation mode deliberately: `single` blocks re-runs while waiting; `restart` kills the old wait when re-triggered; `parallel` and `queued` let runs stack. The timeout keeps any mode from wedging.

### 5. Add the presence layer

Gate behavior on `person.*` entities and zone states (`home`, `away`, `not_home`), not on single device trackers. Details in `references/presence.md`:

- Use "everyone away" conditions from person entities for arm/lock routines, with a `for:` delay (a few minutes) so a tracker blip at the driveway does not arm the house while someone is still in the garage.
- Use per-person states for personalized routines (welcome-home lighting per person, per-room scenes).
- Never treat a single device tracker's `away` as proof someone left; trackers lie, groups of them lie less.

### 6. Add the failure fallback layer

Assume every step can fail. Details and patterns in `references/fallbacks.md`:

- `continue_on_error: true` on steps allowed to fail (a notification to a dead service, one light in a group). By default a failed step stops the whole run and marks it failed; use this to keep the rest alive. It does not hide the error; traces and logs still record it.
- Timeouts on every `wait_for_trigger` and `wait_template`, with a fallback branch for the timeout case. A routine with no timeout is a routine that wedges.
- `repeat` with `until` for critical alerts that must not be missed once (water leak, smoke, freezer). Retry with backoff, and cap it with a final fallback (call a second device, log a persistent notification).
- A `default` branch on every `choose` that needs one. Silence is not a plan.
- Verify the target exists before acting when the device is optional: check `is_state` or availability first, or the step fails at 3 AM and wakes nobody.

### 7. Verify with traces, then ship

- Run the routine and open the automation trace. Walk every branch: confirmed, dismissed, timed out, device failed. If you cannot trigger a branch in testing, you do not know what it does.
- Ship the YAML and a one-paragraph summary: what it does, what it asks, what happens on timeout and on failure. Anything staged must not look live; keep drafts out of production until verified.

## Output Contract

Every routine this skill produces ships with:

1. The automation and/or script YAML, valid and commented at each decision point.
2. A confirmation plan: which steps gate, what the buttons say, what the timeout is, what the timeout does.
3. A presence plan: which person entities and zones it reads, and the `for:` delays against tracker noise.
4. A failure plan: which steps carry `continue_on_error`, where waits time out, what the fallbacks are.
5. A test note: which branches were walked in traces, and which could not be triggered.

## Operating Rules

1. No security-relevant actuation without a confirmation gate: locks, alarms, garage doors, cameras, anything that changes who can get in. No exceptions for convenience.
2. Never wait forever. Every `wait_for_trigger` and `wait_template` gets a `timeout` and a fallback branch.
3. Never reuse a notification action ID across runs. Bind IDs to `context.id`.
4. Never branch on one device tracker's state. Use person entities and zones; add `for:` delays against flapping.
5. `continue_on_error` is for steps the routine can survive losing, never for the safety-critical step itself. If the lock command fails, the routine must fail loudly, not shrug and continue.
6. Every factual claim about HA behavior in your output must trace to the official docs or a tested trace. If you cannot verify it, cut it or mark it as untested.
7. Keep drafts staged. A routine goes live only after its branches are walked in traces. Staged is never live.
