Files
spotify-voice-assistant/current-functions.txt
T
bhethermanandClaude Sonnet 5 2ed1ca1e99 Fix cold-start play_media failure and swap reversed room IDs
The Spotify integration only exposes the media_player.play_media
service once it has an active playback context, which doesn't exist
yet on a cold start; the fixed 2s delay after select_source wasn't
long enough in that case even though it always worked once something
had already played. Poll supported_features for the PLAY_MEDIA bit
(up to 8s) before calling play_media instead of guessing a fixed delay.

Also swap the Living Room/Bedroom source_list ID mapping in both the
prompt (for display) and the functions (for select_source) -- it was
backwards.

Adds a test-harness regression case exercising the opaque Spotify
Connect device IDs the source_list actually reports.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-05 13:40:40 -04:00

241 lines
9.6 KiB
Plaintext

- spec:
name: execute_services
description: Use this function to execute service of devices in Home Assistant.
parameters:
type: object
properties:
list:
type: array
items:
type: object
properties:
domain:
type: string
description: The domain of the service
service:
type: string
description: The service to be called
service_data:
type: object
description: The service data object to indicate what to control.
properties:
entity_id:
type: string
description: The entity_id retrieved from available devices. It
must start with domain, followed by dot character.
required:
- entity_id
required:
- domain
- service
- service_data
function:
type: native
name: execute_service
# Spotify Music Control Functions
- spec:
name: search_spotify
description: >-
Search Spotify for an artist, album, track, or playlist and return the Spotify URI.
Use this before playing music to get the URI. Use this whenever the user asks to play
or queue a specific song, artist, album, or playlist — even if the name contains a
number (e.g. "Back on 74", "1979", "Blink 182"). A number that is part of a
song/artist/album name is NOT a volume level; only use control_playback's volume_set
if the user explicitly says "volume" or "percent".
parameters:
type: object
properties:
query:
type: string
description: Artist, album, track, or playlist name to search for (e.g., "Coldplay", "Parachutes", "Yellow", "Today's Top Hits")
type:
type: string
enum: [artist, album, track, playlist]
description: Type of content to search for. Playlist searches check your personal playlists first, then fall back to public Spotify playlists.
required:
- query
- type
function:
type: script
sequence:
- service: spotify_voice_assistant.search
response_variable: _function_result
data:
query: "{{ query }}"
type: "{{ type }}"
- spec:
name: play_music
description: Play music immediately on a Spotify Connect device using a Spotify URI, replacing current playback. You must first call search_spotify to get the URI. Use this when user says "play".
parameters:
type: object
properties:
spotify_uri:
type: string
description: Spotify URI from search_spotify (e.g., "spotify:artist:4gzpq5DPGxSnKTe4SA8HAU")
type:
type: string
enum: [artist, album, track, playlist]
description: The exact "type" value returned by search_spotify for this URI. Required — passing the wrong value causes playback to silently fail.
room:
type: string
description: Spotify Connect source/device name to play on, matching an entry in media_player.spotify_bhetherman's source_list exactly (e.g., "Living Room")
required:
- spotify_uri
- type
- room
function:
type: script
sequence:
- service: media_player.select_source
target:
entity_id: media_player.spotify_bhetherman
data:
source: "{{ room | replace('Living Room', 'd0166d6f83796b0f9059b0adf0f6cb0d81fa6376') | replace('Bedroom', 'a334c8ba989367b52303eaa9dbc424cdd83012b5') }}"
- repeat:
while:
- condition: template
value_template: >-
{{ repeat.index <= 8 and
(state_attr('media_player.spotify_bhetherman', 'supported_features') | int(0)
| bitwise_and(512)) != 512 }}
sequence:
- delay: "00:00:01"
- service: media_player.play_media
target:
entity_id: media_player.spotify_bhetherman
data:
media_content_id: "{{ spotify_uri }}"
media_content_type: "{{ type }}"
enqueue: replace
- spec:
name: queue_music
description: >-
Queue or play music using a Spotify URI from search_spotify. Use this whenever the
user says "queue" or "add to queue" — always use this function for queue requests,
regardless of whether the content is a track, album, artist, or playlist; the
correct behavior for each type is handled automatically. (Individual tracks are
added to the queue without interrupting playback; since Spotify cannot queue a whole
album/artist/playlist, those start playing immediately instead.)
parameters:
type: object
properties:
spotify_uri:
type: string
description: Spotify URI from search_spotify (e.g., "spotify:track:4gzpq5DPGxSnKTe4SA8HAU")
type:
type: string
enum: [artist, album, track, playlist]
description: The exact "type" value returned by search_spotify for this URI.
room:
type: string
description: Spotify Connect source/device name to queue on, matching an entry in media_player.spotify_bhetherman's source_list exactly (e.g., "Living Room")
required:
- spotify_uri
- type
- room
function:
type: script
sequence:
- service: media_player.select_source
target:
entity_id: media_player.spotify_bhetherman
data:
source: "{{ room | replace('Living Room', 'd0166d6f83796b0f9059b0adf0f6cb0d81fa6376') | replace('Bedroom', 'a334c8ba989367b52303eaa9dbc424cdd83012b5') }}"
- repeat:
while:
- condition: template
value_template: >-
{{ repeat.index <= 8 and
(state_attr('media_player.spotify_bhetherman', 'supported_features') | int(0)
| bitwise_and(512)) != 512 }}
sequence:
- delay: "00:00:01"
- service: media_player.play_media
target:
entity_id: media_player.spotify_bhetherman
data:
media_content_id: "{{ spotify_uri }}"
media_content_type: "{{ type }}"
enqueue: "{{ 'add' if type == 'track' else 'replace' }}"
- spec:
name: control_playback
description: >-
Control playback of music that is ALREADY PLAYING (pause, resume, stop, next track,
previous track, set volume, shuffle) on the currently active Spotify Connect session.
Only use volume_set when the user explicitly says the word "volume" or "percent"
(e.g. "turn the volume up", "set volume to 50", "50 percent volume").
Do NOT use this function to play a requested song, artist, or album — a number in a
song/artist/album name (e.g. "Back on 74", "Blink 182", "Sunset 2005") is part of the
title, never a volume level. Use search_spotify + play_music for any request to play
or start specific music, even if it contains a number.
parameters:
type: object
properties:
action:
type: string
enum: [pause, play, stop, next_track, previous_track, volume_set, shuffle_on, shuffle_off]
description: Playback control action
volume_level:
type: number
description: Volume level (0-100) for volume_set action only. Only set this when the user said the word "volume" or "percent".
required:
- action
function:
type: script
sequence:
- choose:
- conditions: "{{ action == 'pause' }}"
sequence:
- service: media_player.media_pause
target:
entity_id: media_player.spotify_bhetherman
- conditions: "{{ action == 'play' }}"
sequence:
- service: media_player.media_play
target:
entity_id: media_player.spotify_bhetherman
- conditions: "{{ action == 'stop' }}"
sequence:
# media_player.spotify_bhetherman does not support the media_stop
# service (STOP is not in its supported_features); Spotify Connect has
# no separate stop concept, so route "stop" through pause instead.
- service: media_player.media_pause
target:
entity_id: media_player.spotify_bhetherman
- conditions: "{{ action == 'next_track' }}"
sequence:
- service: media_player.media_next_track
target:
entity_id: media_player.spotify_bhetherman
- conditions: "{{ action == 'previous_track' }}"
sequence:
- service: media_player.media_previous_track
target:
entity_id: media_player.spotify_bhetherman
- conditions: "{{ action == 'volume_set' }}"
sequence:
- service: media_player.volume_set
target:
entity_id: media_player.spotify_bhetherman
data:
volume_level: "{{ volume_level / 100 }}"
- conditions: "{{ action == 'shuffle_on' }}"
sequence:
- service: media_player.shuffle_set
target:
entity_id: media_player.spotify_bhetherman
data:
shuffle: true
- conditions: "{{ action == 'shuffle_off' }}"
sequence:
- service: media_player.shuffle_set
target:
entity_id: media_player.spotify_bhetherman
data:
shuffle: false