Music
Play music through the device's speaker by searching YouTube. Use this when the user asks to play, sing, or listen to music.
Spoken output: Everything outside HW markers in your reply is read aloud. For a play/stop request, start with the HW markers, then give one short confirmation and end the reply. Keep song-selection reasoning, transcript interpretation, and speaker attribution in the provider's native thinking channel (omit analysis if unavailable), without a text summary before/after tools or in the final answer; do not add a preamble, a draft confirmation, or a second confirmation.
Workflow
- Specific song / artist → play directly. When
[voice-instruction] is present, use that request; a conflicting noisy [transcript] does not replace the song title. No habit or identity lookup is needed. Use a known speaker for person; otherwise omit the field silently.
- Vague request ("play music", "sing something") → check habit patterns first:
cat /root/local/users/{name}/habit/patterns.json 2>/dev/null
If music_patterns exists and current hour is within peak_hour ± 1 → use preferred_genre to pick a song, no need to ask.
Otherwise → ask: "What are you in the mood for?". The file is bootstrapped lazily by wellbeing on its first threshold nudge; do not invoke habit Flow A from here.
- Reply format:
[HW:/audio/play:{"query":"Bohemian Rhapsody Queen","person":"{name}"}][HW:/emotion:{"emotion":"excited","intensity":0.8}] Playing Bohemian Rhapsody!
{name} is the speaker identified in the injected context. If nobody is identified, drop the field entirely — [HW:/audio/play:{"query":"Bohemian Rhapsody Queen"}]. Never invent a name or reuse one from an example.
- Stop:
[HW:/audio/stop:{}] Music stopped.
API schema (/audio/play)
| Field |
Required |
Description |
query |
YES |
YouTube search string (include artist for better match) |
person |
no |
The identified speaker's label, lowercase ({name} from the injected context) — omit the field when nobody is identified. Unmatched names are logged under the shared unknown bucket, so a made-up name buys nothing. |
Do NOT use track, artist, title, song — those return 422.
Genre → Emotion (pair with every /audio/play)
| Genre keywords |
Emotion |
| jazz, blues, soul, funk, swing |
happy |
| classical, orchestra, piano, violin |
curious |
| hip hop, rap, trap, r&b, rock, metal |
excited |
| anything else |
happy |
Examples
| Input |
Output |
| "Play Bohemian Rhapsody" |
[HW:/audio/play:{"query":"Bohemian Rhapsody Queen","person":"{name}"}][HW:/emotion:{"emotion":"excited","intensity":0.8}] Playing Bohemian Rhapsody! |
| "Sing me a song" |
[HW:/emotion:{"emotion":"curious","intensity":0.6}] What kind of vibe — chill, upbeat, or something specific? |
| "Something chill" |
[HW:/audio/play:{"query":"chill acoustic playlist","person":"{name}"}][HW:/emotion:{"emotion":"happy","intensity":0.8}] Here's some chill vibes! |
| "Something chill" (no identified speaker) |
[HW:/audio/play:{"query":"chill acoustic playlist"}][HW:/emotion:{"emotion":"happy","intensity":0.8}] Here's some chill vibes! |
| "Stop the music" |
[HW:/audio/stop:{}] Music stopped. |
Delegated request with an unknown speaker and noisy transcript:
Input:
[voice-instruction] Play Eternal Flame
[transcript] Uh, my favorite song, uh, Ethan of Lamb.
Reply:
[HW:/audio/play:{"query":"Eternal Flame The Bangles"}][HW:/emotion:{"emotion":"happy","intensity":0.8}] Playing Eternal Flame by The Bangles.
How HW markers work
The Go server intercepts [HW:/audio/play:...] / [HW:/audio/stop:...] in your reply text and forwards to HAL. This is the ONLY way to play music — never use exec, mpv, vlc, yt-dlp, or curl /audio/play.
The marker is passive text, NOT a command to run. Write it directly in your reply and stop — the OS runs it for you. Do NOT try to "execute" or "invoke" it.
- ❌ WRONG — echoing/wrapping the marker in a shell tool.
echo only prints to stdout inside your sandbox; the OS never sees it, so no music plays:echo '[HW:/audio/play:{"query":"Gymnopedie No 1 Satie"}]'
- ✅ RIGHT — the marker IS your reply text (no tool call at all):
[HW:/audio/play:{"query":"Gymnopedie No 1 Satie"}][HW:/emotion:{"emotion":"curious","intensity":0.6}] Here's some Satie. 🎹
Never put [HW:...] inside echo, exec, bash, printf, or any tool argument. If you find yourself reaching for a tool to play music, stop — just emit the marker as text.
Error handling
503 → "Music playback is not available right now."
409 → music already playing; stop first, then play new song.
- No results → tell user and suggest a different query.
Rules
- Emotion marker is mandatory after every
/audio/play.
person MUST be lowercase.
- Don't recite lyrics or "sing" via TTS — call
/audio/play and let real music play.
- Volume control belongs to the Audio skill, not this one.
- If user specifies genre or mood ("play something relaxing"), pick a well-known song — no need to ask further.
1---2name: music3description: Play and stop music from YouTube through the device's speaker on user request.4---56# Music78Play music through the device's speaker by searching YouTube. Use this when the user asks to play, sing, or listen to music.910**Spoken output:** Everything outside HW markers in your reply is read aloud. For a play/stop request, start with the HW markers, then give one short confirmation and end the reply. Keep song-selection reasoning, transcript interpretation, and speaker attribution in the provider's native thinking channel (omit analysis if unavailable), without a text summary before/after tools or in the final answer; do not add a preamble, a draft confirmation, or a second confirmation.1112## Workflow13141. **Specific song / artist** → play directly. When `[voice-instruction]` is present, use that request; a conflicting noisy `[transcript]` does not replace the song title. No habit or identity lookup is needed. Use a known speaker for `person`; otherwise omit the field silently.152. **Vague request** (*"play music"*, *"sing something"*) → check habit patterns first:16 ```bash17 cat /root/local/users/{name}/habit/patterns.json 2>/dev/null18 ```19 If `music_patterns` exists and current hour is within `peak_hour ± 1` → use `preferred_genre` to pick a song, no need to ask.20 Otherwise → ask: *"What are you in the mood for?"*. The file is bootstrapped lazily by wellbeing on its first threshold nudge; do not invoke habit Flow A from here.213. Reply format:22 ```23 [HW:/audio/play:{"query":"Bohemian Rhapsody Queen","person":"{name}"}][HW:/emotion:{"emotion":"excited","intensity":0.8}] Playing Bohemian Rhapsody!24 ```25 `{name}` is the speaker identified in the injected context. If nobody is identified, drop the field entirely — `[HW:/audio/play:{"query":"Bohemian Rhapsody Queen"}]`. Never invent a name or reuse one from an example.264. Stop: `[HW:/audio/stop:{}] Music stopped.`2728## API schema (`/audio/play`)2930| Field | Required | Description |31|---|---|---|32| `query` | **YES** | YouTube search string (include artist for better match) |33| `person` | no | The identified speaker's label, lowercase (`{name}` from the injected context) — **omit the field** when nobody is identified. Unmatched names are logged under the shared `unknown` bucket, so a made-up name buys nothing. |3435Do NOT use `track`, `artist`, `title`, `song` — those return 422.3637## Genre → Emotion (pair with every `/audio/play`)3839| Genre keywords | Emotion |40|---|---|41| jazz, blues, soul, funk, swing | `happy` |42| classical, orchestra, piano, violin | `curious` |43| hip hop, rap, trap, r&b, rock, metal | `excited` |44| anything else | `happy` |4546## Examples4748| Input | Output |49|---|---|50| *"Play Bohemian Rhapsody"* | `[HW:/audio/play:{"query":"Bohemian Rhapsody Queen","person":"{name}"}][HW:/emotion:{"emotion":"excited","intensity":0.8}]` Playing Bohemian Rhapsody! |51| *"Sing me a song"* | `[HW:/emotion:{"emotion":"curious","intensity":0.6}]` What kind of vibe — chill, upbeat, or something specific? |52| *"Something chill"* | `[HW:/audio/play:{"query":"chill acoustic playlist","person":"{name}"}][HW:/emotion:{"emotion":"happy","intensity":0.8}]` Here's some chill vibes! |53| *"Something chill"* (no identified speaker) | `[HW:/audio/play:{"query":"chill acoustic playlist"}][HW:/emotion:{"emotion":"happy","intensity":0.8}]` Here's some chill vibes! |54| *"Stop the music"* | `[HW:/audio/stop:{}]` Music stopped. |5556Delegated request with an unknown speaker and noisy transcript:5758Input:59```text60[voice-instruction] Play Eternal Flame61[transcript] Uh, my favorite song, uh, Ethan of Lamb.62```6364Reply:65```text66[HW:/audio/play:{"query":"Eternal Flame The Bangles"}][HW:/emotion:{"emotion":"happy","intensity":0.8}] Playing Eternal Flame by The Bangles.67```6869## How HW markers work7071The Go server intercepts `[HW:/audio/play:...]` / `[HW:/audio/stop:...]` **in your reply text** and forwards to HAL. This is the ONLY way to play music — never use `exec`, `mpv`, `vlc`, `yt-dlp`, or `curl /audio/play`.7273**The marker is passive text, NOT a command to run.** Write it directly in your reply and stop — the OS runs it for you. Do NOT try to "execute" or "invoke" it.7475- ❌ **WRONG** — echoing/wrapping the marker in a shell tool. `echo` only prints to stdout inside your sandbox; the OS never sees it, so **no music plays**:76 ```bash77 echo '[HW:/audio/play:{"query":"Gymnopedie No 1 Satie"}]'78 ```79- ✅ **RIGHT** — the marker IS your reply text (no tool call at all):80 ```81 [HW:/audio/play:{"query":"Gymnopedie No 1 Satie"}][HW:/emotion:{"emotion":"curious","intensity":0.6}] Here's some Satie. 🎹82 ```8384Never put `[HW:...]` inside `echo`, `exec`, `bash`, `printf`, or any tool argument. If you find yourself reaching for a tool to play music, stop — just emit the marker as text.8586## Error handling8788- `503` → *"Music playback is not available right now."*89- `409` → music already playing; stop first, then play new song.90- No results → tell user and suggest a different query.9192## Rules9394- **Emotion marker is mandatory** after every `/audio/play`.95- `person` MUST be lowercase.96- Don't recite lyrics or "sing" via TTS — call `/audio/play` and let real music play.97- Volume control belongs to the **Audio** skill, not this one.98- If user specifies genre or mood (*"play something relaxing"*), pick a well-known song — no need to ask further.