Create or Update Scene
ha_config_set_sceneCreate or update a Home Assistant scene configuration. Supports full replacement or surgical edits via Python transformation for adding, updating, or removing entities.
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.
WHEN TO USE:
python_transform: surgical edits to an existing scene (add/remove/update a single entity entry). Requiresconfig_hashfrom ha_config_get_scene() for optimistic locking.config: creating a new scene, or wholesale replacement.
WHEN NOT TO USE:
To activate a scene at runtime, use ha_call_service(domain="scene", service="turn_on", target=...) — this tool only manages scene configuration, not the runtime turn-on/off side.
To list or look up existing scenes, use ha_search(domain_filter="scene").
SCENE SHAPE: entities is a dict keyed by entity_id (e.g.,
{'light.kitchen': {'state': 'on', 'brightness': 200}}), NOT a
list. 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.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| wait | No | Wait for scene to be queryable before returning. Default: True. 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. | |
| 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. Requires config_hash for validation. 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 🎯 PATTERNS: - Filter cards: cards = [c for c in cards if keep(c)] - Skip in a loop: prefer `continue` over an empty `pass` branch (clearer) - Conditionally include: build a new list and `.append(x)` only the cards you want, instead of iterating the original and using if/pass branches to drop entries - Modify in place when possible (single pass, fewer surprises) over reconstructing the entire list |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||