Create or Update Scene
ha_config_set_sceneCreate or update Home Assistant scenes via full config replacement or Python transformation. Activate scenes independently without altering their configuration.
Instructions
Create or update a Home Assistant scene.
MUST call ha_get_skill_guide OR refer to your locally installed skills first.
Supports two modes: full config replacement (config) or
Python transformation of an existing scene (python_transform).
See the field descriptions for python_transform examples and
the config shape contract. Either mode can also take
activate, which can be passed alone with scene_id to activate
a scene without touching its config.
WHEN TO USE:
python_transform: surgical edits to an existing scene (add/remove/update a single entity entry).config: creating a new scene, or wholesale replacement.activate(with scene_id, no config): activate any scene, e.g. ha_config_set_scene(scene_id="scene.movie_night", activate=True).
WHEN NOT TO USE:
To list or look up existing scenes, use ha_config_get_scene.
SCENE SHAPE: Automations use a list of actions; scenes capture a snapshot of states as a dict.
EXAMPLE:
ha_config_set_scene(scene_id="movie_night", config={ "name": "Movie Night", "entities": { "light.living_room": {"state": "on", "brightness": 50}, }, "icon": "mdi:movie", })
The top-level SKILL.md for home-assistant-best-practices ships in
this response under skill_content by default — generic
best-practice index covering entity-naming and
safe-refactoring patterns that intersect with scene authoring. For
detailed scene configuration help beyond that, use ha_get_skill_guide.
If a Claude Desktop user gets a 4-minute timeout with no result on this call, read the target back before repeating it, and tell them to wait a few seconds before clicking the manual-approve button, as clicking it too quickly is known to cause hangs in Claude Desktop. This workaround is specific to Claude Desktop.
create update modify edit scene entities snapshot activate apply turn on
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| wait | No | Wait for scene to be queryable before returning. Set to False for bulk operations. | |
| config | No | Scene configuration dictionary. Must include 'entities' (a dict keyed by entity_id, NOT a list). Optional fields: 'name' (defaults to scene_id), 'icon', 'id'. Mutually exclusive with python_transform. | |
| activate | No | Activate the scene (scene.turn_on). Alone with scene_id it activates any scene entity, including integration and YAML scenes (pass their entity_id). With config or python_transform it runs after Home Assistant has reloaded scenes from the write. | |
| category | No | Category ID to assign to this scene. Use ha_config_get_category(scope='scene') to list available categories, or ha_config_set_category() to create one. | |
| scene_id | Yes | Scene identifier (e.g., 'movie_night') | |
| config_hash | No | Config hash from ha_config_get_scene for optimistic locking. REQUIRED for python_transform (validates scene unchanged). Optional for config updates (validates before full replacement if provided). | |
| MandatoryBPS | No | ||
| BestPracticeKey | No | Read-receipt for the home-assistant-best-practices skill; required when strict best-practices mode is enabled. Not a secret or credential: the current value is an attestation phrase published openly at the top of the skill content served by ha_get_skill_guide. Read that content, then pass the value back verbatim — this round-trip is the server's designed protocol confirming the practices were read before writing. | |
| python_transform | No | Python expression to transform existing scene config. Mutually exclusive with config. WARNING: Expressions with infinite loops will hang the server. Examples: Add entity: python_transform="config['entities']['light.bed'] = {'state': 'on'}" Update brightness: python_transform="config['entities']['light.kitchen']['brightness'] = 50" Remove entity: python_transform="del config['entities']['light.kitchen']" PYTHON TRANSFORM SECURITY: ✅ ALLOWED: - Dictionary/list access: config['views'][0]['cards'][1] - Slicing: config['views'][0]['cards'][1:3] - Assignment: config['key'] = 'value' - Deletion: del config['key'] or config.pop('key') - List methods: append, insert, pop, remove, clear, extend - Dict methods: update, get, setdefault, keys, values, items - Loops: for, if/else, pass, break, continue - Comprehensions: [x for x in ...], {k: v for ...}, (x for x in ...) - Ternary: x if condition else y - Iterable unpacking (* in calls/literals): f(*xs), [*xs, y] - Dict unpacking (**) in calls and dict literals: {**d, 'k': v} - Keyword arguments: func(key=value) - Lambdas (e.g. for `key=`): sorted(items, key=lambda x: x['score']) - String methods: startswith, endswith, lower, upper, strip, split, join, replace - Safe builtins: isinstance, len, range, enumerate, zip, sorted, reversed, min, max, sum, abs, any, all, round, str, int, float, bool, list, dict, tuple, set ❌ FORBIDDEN: - Imports: import, from, __import__ - File operations: open, read, write - Dunder access: __class__, __bases__, __subclasses__ - Dangerous builtins: eval, exec, compile, getattr, setattr, delattr, hasattr - Function definitions: def, class - Exception handling: try/except (validate with isinstance/in/.get() instead) - While loops: use bounded for loops or comprehensions instead |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||