The core limitation
Automating with Google Home & HomeKit
Patterns for making Home Assistant behave well when lights, switches and media are controlled from Google Home or HomeKit — platforms that can only turn things on and off, not run your scripts.
The core limitation
Google Home and HomeKit talk to HA through the Google Assistant / HomeKit integrations. They can:
- turn an entity on/off, and (for lights) set brightness / colour
- run exposed scripts and scenes
- query state
They cannot run automations, and they won’t run a script you forgot to expose. So any “polish” behaviour — dimming after dark, turning a light off later, logging the event — has to live in an automation that reacts to the state change the assistant causes, not in the assistant itself.
The general recipe:
- Expose only the entities and scripts each platform should control (exposure is off by default — list them explicitly).
- Write automations with
light.turned_on/switch.turned_ontriggers targeting those entities. The trigger fires identically whether the change came from the HA dashboard, a voice command, or a HomeKit switch on the wall — so one automation serves all sources. - Add time-of-day / state conditions to shape the behaviour.
Example: Light:On:Dim
The best illustration of the pattern. Bedside lamps exposed to the assistants are sometimes switched on at full brightness late at night (a voice command or a HomeKit switch). This automation re-dims them to a safe level:
- id: '202607080107'
description: ''
triggers:
- trigger: light.turned_on
target:
entity_id:
- light.light_bedside_1
- light.light_bedside_2
- light.light_masterbedroom_1
options:
behavior: each
conditions:
- condition: state
entity_id: input_boolean.active
state: ['on']
- condition: time
after: '21:00'
before: '07:30:00'
- condition: template
value_template: >-
{{ is_state_attr(trigger.entity_id, 'brightness', none) == false and
state_attr(trigger.entity_id, 'brightness') | int(0) > 15 }}
actions:
- sequence:
- action: light.turn_on
target:
entity_id: "{{ trigger.entity_id }}"
data:
brightness_pct: 20
alias: Light:On:Dim
mode: parallel
max: 10
Design points worth copying:
light.turned_on+behavior: each— fires once per light, so a voice command or scene that hits several lights at once works without any of the runs blocking each other (hencemode: parallel).- Brightness guard (
> 15) — leaves alone lights that were switched on at (or near) zero brightness, e.g. lights ramping up on their own. This is what keeps the automation from fighting devices that manage their own dimming. - The visible ramp — re-setting the light to 20 % brightness ramps it down rather than snapping, so it looks as if the light came on at the right level.
- Time-of-day condition — the same light at 8 am is left alone; only the 21:00–07:30 window gets the treatment.
input_boolean.activecondition — required when running a cluster so the standby doesn’t also act (see High Availability).
This is the key idea: react to state, not to the source. Because the trigger is on the light itself, the automation works for HomeKit, Google Home, the dashboard, and any future platform, with zero per-platform code.
Exposing entities deliberately
Both integrations default to no exposure — you list each entity you want voice-controlled, and you can attach friendly names/areas. Tips:
- Expose scripts for multi-entity actions (“Party Lights”, “Enough Christmas”, “Lights Out”) rather than making users say one word per light. Google Assistant script names are what the user actually says.
- Keep a separate exposure list per platform: HomeKit for things people reach for on their phones / watch at the bedside (bedside lamps, bedroom lights, alarm panel, computers), Google Home for the rest. The same entity doesn’t need to be in both.
- If you run a cluster, only the active instance should be connected to the assistants — see the gotchas in High Availability.
- Watch for entity-ID typos in the exposure lists: a misspelled entity is silently not exposed, so “the light is missing from HomeKit” often means a typo, not a broken integration.
Gotchas
- Assistant changes bypass your scripts. If a user says “turn on the
bedside light”, the Google Assistant integration calls
light.turn_ondirectly — any script with dimming logic does not run. State-trigger automations (likeLight:On:Dim) are how you recover the behaviour. - State reporting. The Google Assistant integration’s
report_statesetting controls whether HA pushes entity state changes to Google. Leave it on, otherwise voice queries (“is the light on?”) can answer with stale state. - PIN / secure devices. Voice commands from secure devices (e.g. a Nest Hub) require the configured PIN; keep it in secrets, and remember a PIN change silently breaks voice control until everyone re-enters it.
- HomeKit accessory setup. The HomeKit integration exposes HA as a single HomeKit accessory with a room layout; expose the alarm control panel too — “Armed” / “Disarmed” from the Home app is a nice touch.
Related
Source Disclaimer
- AI Generated
- Human Generated
- AI Edited
- Human Edited