원클릭으로
원클릭으로
Capture actionable user requests as persistent tasks, update task status as work progresses, and keep a shared task store in sync. Use when a user asks an agent to do work, check progress, block a task, complete a task, or manage the Kanban board.
Maintain a shared workspace TODO list with blocked tasks.
| name | soundclaw |
| description | Control Spotify playback, search music, and return shareable music links. |
| metadata | {"openclaw":{"skillKey":"soundclaw"}} |
Use this skill when the user wants an agent to search for music, play a song or playlist, control Spotify playback, or send back a shareable Spotify link on the same channel the request came from.
{
"activation": {
"anyPhrases": [
"spotify",
"play a song",
"play this song",
"play music",
"play a playlist",
"find a song",
"queue this song",
"music link"
]
},
"movement": {
"target": "jukebox",
"skipIfAlreadyThere": true
}
}
When this skill is activated, the agent should walk to the office jukebox before handling the request.
This section is for developers implementing the backend skill handler in OpenClaw. The Claw3D UI handles authentication via Spotify PKCE OAuth in the browser. The gateway skill handles agent-driven requests via the
soundclaw.*RPC namespace.
The user authenticates directly in the browser (PKCE, no secret required).
The access token is stored in browser localStorage under the key soundclaw_token.
For agent-driven playback (e.g. "play Jazz for me"), the gateway skill should either:
// Search for tracks. Returns a list of { name, artist, album, uri, spotifyUrl }.
soundclaw.search({ query: string }): SpotifySearchResult[]
// Get a shareable Spotify link for a query (for Telegram/chat replies).
soundclaw.getLink({ query: string }): { url: string; title: string }
// Report current playback state (reads from Spotify API).
soundclaw.playerStatus(): PlayerStatus | null
// Request playback of a URI (requires user to be authenticated in browser).
soundclaw.play({ uri: string }): { ok: boolean; message?: string }
// Pause / resume / skip.
soundclaw.pause(): void
soundclaw.resume(): void
soundclaw.next(): void
soundclaw.previous(): void
movement.target: "jukebox")soundclaw.search to find the best matchsoundclaw.getLink and reply with the linksoundclaw.play to start playback