From 9be17bb84f3dc5c88462dd74dcac8b8fb2fca509 Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Fri, 24 Apr 2026 05:38:02 -0700 Subject: [PATCH] docs(spotify): expand feature page with tool reference, Free/Premium matrix, troubleshooting (#15135) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The initial Spotify docs page shipped in #15130 was a setup guide. This expands it into a full feature reference: - Per-tool parameter table for all 9 tools, extracted from the real schemas in tools/spotify_tool.py (actions, required/optional args, premium gating). - Free vs Premium feature matrix — which actions work on which tier, so Free users don't assume Spotify tools are useless to them. - Active-device prerequisite called out at the top; this is the #1 cause of '403 no active device' reports for every Spotify integration. - SSH / headless section explaining that browser auto-open is skipped when SSH_CLIENT/SSH_TTY is set, and how to tunnel the callback port. - Token lifecycle: refresh on 401, persistence across restarts, how to revoke server-side via spotify.com/account/apps. - Example prompt list so users know what to ask the agent. - Troubleshooting expanded: no-active-device, Premium-required, 204 now_playing, INVALID_CLIENT, 429, 401 refresh-revoked, wizard not opening browser. - 'Where things live' table mapping auth.json / .env / Spotify app. Verified with 'node scripts/prebuild.mjs && npx docusaurus build' — page compiles, no new warnings. --- website/docs/user-guide/features/spotify.md | 170 +++++++++++++++----- 1 file changed, 134 insertions(+), 36 deletions(-) diff --git a/website/docs/user-guide/features/spotify.md b/website/docs/user-guide/features/spotify.md index ecadc7245b..298bd06428 100644 --- a/website/docs/user-guide/features/spotify.md +++ b/website/docs/user-guide/features/spotify.md @@ -1,13 +1,14 @@ # Spotify -Hermes can control Spotify directly — playback, queue, search, playlists, saved tracks/albums, and listening history — using Spotify's official Web API with PKCE OAuth. +Hermes can control Spotify directly — playback, queue, search, playlists, saved tracks/albums, and listening history — using Spotify's official Web API with PKCE OAuth. Tokens are stored in `~/.hermes/auth.json` and refreshed automatically on 401; you only log in once per machine. -Unlike most Hermes integrations, Spotify requires every user to register their own lightweight developer app. Spotify does not let third parties ship a public OAuth app that anyone can use. The whole thing takes about two minutes. +Unlike Hermes' built-in OAuth integrations (Google, GitHub Copilot, Codex), Spotify requires every user to register their own lightweight developer app. Spotify does not let third parties ship a public OAuth app that anyone can use. It takes about two minutes and `hermes auth spotify` walks you through it. ## Prerequisites -- A Spotify account (Free works for most tools; **playback control requires Premium**) -- Hermes Agent installed and running +- A Spotify account. **Free** works for search, playlist, library, and activity tools. **Premium** is required for playback control (play, pause, skip, seek, volume, queue add, transfer). +- Hermes Agent installed and running. +- For playback tools: an **active Spotify Connect device** — the Spotify app must be open on at least one device (phone, desktop, web player, speaker) so the Web API has something to control. If nothing is active you'll get a `403 Forbidden` with a "no active device" message; open Spotify on any device and retry. ## Setup @@ -17,7 +18,7 @@ Unlike most Hermes integrations, Spotify requires every user to register their o hermes tools ``` -Scroll to `🎵 Spotify`, press space to toggle it on, then `s` to save. +Scroll to `🎵 Spotify`, press space to toggle it on, then `s` to save. The 9 Spotify tools only appear in the agent's toolset after this — they're off by default so users who don't want them don't ship extra tool schemas on every API call. ### 2. Run the login wizard @@ -25,18 +26,19 @@ Scroll to `🎵 Spotify`, press space to toggle it on, then `s` to save. hermes auth spotify ``` -If you don't have a Spotify app yet, Hermes walks you through creating one: +If no `HERMES_SPOTIFY_CLIENT_ID` is set, Hermes walks you through the app registration inline: -1. Opens the Spotify developer dashboard in your browser -2. Tells you exactly what values to paste into the Spotify form -3. Prompts you for the `Client ID` you get back -4. Saves it to `~/.hermes/.env` and continues straight into the OAuth flow +1. Opens `https://developer.spotify.com/dashboard` in your browser +2. Prints the exact values to paste into Spotify's "Create app" form +3. Prompts you for the Client ID you get back +4. Saves it to `~/.hermes/.env` so future runs skip this step +5. Continues straight into the OAuth consent flow -After the Spotify consent page, tokens are saved under `providers.spotify` in `~/.hermes/auth.json` and the integration is live. +After you approve, tokens are written under `providers.spotify` in `~/.hermes/auth.json`. The active inference provider is NOT changed — Spotify auth is independent of your LLM provider. ### Creating the Spotify app (what the wizard asks for) -When you land on the dashboard, click **Create app** and fill in: +When the dashboard opens, click **Create app** and fill in: | Field | Value | |-------|-------| @@ -44,9 +46,13 @@ When you land on the dashboard, click **Create app** and fill in: | App description | anything (e.g. `personal Hermes integration`) | | Website | leave blank | | Redirect URI | `http://127.0.0.1:43827/spotify/callback` | -| Which API/SDKs? | **Web API** | +| Which API/SDKs? | check **Web API** | -Agree to the terms, click **Save**. On the next screen click **Settings** → copy the **Client ID**. That's the only value Hermes needs (no client secret — PKCE doesn't use one). +Agree to the terms and click **Save**. On the next page click **Settings** → copy the **Client ID** and paste it into the Hermes prompt. That's the only value Hermes needs — PKCE doesn't use a client secret. + +### Running over SSH / in a headless environment + +If `SSH_CLIENT` or `SSH_TTY` is set, Hermes skips the automatic browser open during both the wizard and the OAuth step. Copy the dashboard URL and the authorization URL Hermes prints, open them in a browser on your local machine, and proceed normally — the local HTTP listener still runs on the remote host on port 43827. If you need to reach it through an SSH tunnel, forward that port: `ssh -L 43827:127.0.0.1:43827 remote`. ## Verify @@ -54,25 +60,101 @@ Agree to the terms, click **Save**. On the next screen click **Settings** → co hermes auth status spotify ``` -Shows whether tokens are present and when the access token expires. Hermes automatically refreshes on 401. +Shows whether tokens are present and when the access token expires. Refresh is automatic: when any Spotify API call returns 401, the client exchanges the refresh token and retries once. Refresh tokens persist across Hermes restarts, so you only re-auth if you revoke the app in your Spotify account settings or run `hermes auth logout spotify`. ## Using it -Once logged in, the agent has access to 9 Spotify tools: +Once logged in, the agent has access to 9 Spotify tools. You talk to the agent naturally — it picks the right tool and action. -| Tool | Actions | -|------|---------| -| `spotify_playback` | play, pause, skip, seek, volume, now playing, playback state | -| `spotify_devices` | list devices, transfer playback | -| `spotify_queue` | inspect queue, add tracks to queue | -| `spotify_search` | search tracks, albums, artists, playlists | -| `spotify_playlists` | list, get, create, update, add/remove tracks | -| `spotify_albums` | get album, list album tracks | -| `spotify_saved_tracks` | list, save, remove | -| `spotify_saved_albums` | list, save, remove | -| `spotify_activity` | recently played, now playing | +``` +> play some miles davis +> what am I listening to +> add this track to my Late Night Jazz playlist +> skip to the next song +> make a new playlist called "Focus 2026" and add the last three songs I played +> which of my saved albums are by Radiohead +> search for acoustic covers of Blackbird +> transfer playback to my kitchen speaker +``` -The agent picks the right tool automatically. Ask it to "play some Miles Davis," "what am I listening to," "add the current track to my starred playlist," etc. +### Tool reference + +All playback-mutating actions accept an optional `device_id` to target a specific device. If omitted, Spotify uses the currently active device. + +#### `spotify_playback` +Control and inspect playback. + +| Action | Purpose | Premium? | +|--------|---------|----------| +| `get_state` | Full playback state (track, device, progress, shuffle/repeat) | No | +| `get_currently_playing` | Just the current track | No | +| `play` | Start/resume playback. Optional: `context_uri`, `uris`, `offset`, `position_ms` | Yes | +| `pause` | Pause playback | Yes | +| `next` / `previous` | Skip track | Yes | +| `seek` | Jump to `position_ms` | Yes | +| `set_repeat` | `state` = `track` / `context` / `off` | Yes | +| `set_shuffle` | `state` = `true` / `false` | Yes | +| `set_volume` | `volume_percent` = 0-100 | Yes | + +#### `spotify_devices` +| Action | Purpose | +|--------|---------| +| `list` | Every Spotify Connect device visible to your account | +| `transfer` | Move playback to `device_id`. Optional `play: true` starts playback on transfer | + +#### `spotify_queue` +| Action | Purpose | Premium? | +|--------|---------|----------| +| `get` | Currently queued tracks | No | +| `add` | Append `uri` to the queue | Yes | + +#### `spotify_search` +Search the catalog. `query` is required. Optional: `types` (array of `track` / `album` / `artist` / `playlist` / `show` / `episode`), `limit`, `offset`, `market`. + +#### `spotify_playlists` +| Action | Purpose | Required args | +|--------|---------|---------------| +| `list` | User's playlists | — | +| `get` | One playlist + tracks | `playlist_id` | +| `create` | New playlist | `name` (+ optional `description`, `public`, `collaborative`) | +| `add_items` | Add tracks | `playlist_id`, `uris` (optional `position`) | +| `remove_items` | Remove tracks | `playlist_id`, `uris` (+ optional `snapshot_id`) | +| `update_details` | Rename / edit | `playlist_id` + any of `name`, `description`, `public`, `collaborative` | + +#### `spotify_albums` +| Action | Purpose | Required args | +|--------|---------|---------------| +| `get` | Album metadata | `album_id` | +| `tracks` | Album track list | `album_id` | + +#### `spotify_saved_tracks` / `spotify_saved_albums` +| Action | Purpose | +|--------|---------| +| `list` | Paginated library listing | +| `save` | Add `ids` / `uris` to library | +| `remove` | Remove `ids` / `uris` from library | + +#### `spotify_activity` +| Action | Purpose | Premium? | +|--------|---------|----------| +| `now_playing` | Currently playing (returns empty on 204 — see below) | No | +| `recently_played` | Last played tracks. Optional `limit`, `before`, `after` (Unix ms) | No | + +### Feature matrix: Free vs Premium + +Read-only tools work on Free accounts. Anything that mutates playback or the queue requires Premium. + +| Works on Free | Premium required | +|---------------|------------------| +| `spotify_search` (all) | `spotify_playback` — play, pause, next, previous, seek, set_repeat, set_shuffle, set_volume | +| `spotify_playback` — get_state, get_currently_playing | `spotify_queue` — add | +| `spotify_devices` — list | `spotify_devices` — transfer | +| `spotify_queue` — get | | +| `spotify_playlists` (all) | | +| `spotify_albums` (all) | | +| `spotify_saved_tracks` (all) | | +| `spotify_saved_albums` (all) | | +| `spotify_activity` (all) | | ## Sign out @@ -80,27 +162,35 @@ The agent picks the right tool automatically. Ask it to "play some Miles Davis," hermes auth logout spotify ``` -Removes tokens from `~/.hermes/auth.json`. To also clear the app config, delete `HERMES_SPOTIFY_CLIENT_ID` (and optionally `HERMES_SPOTIFY_REDIRECT_URI`) from `~/.hermes/.env`. +Removes tokens from `~/.hermes/auth.json`. To also clear the app config, delete `HERMES_SPOTIFY_CLIENT_ID` (and `HERMES_SPOTIFY_REDIRECT_URI` if you set it) from `~/.hermes/.env`, or run the wizard again. + +To revoke the app on Spotify's side, visit [Apps connected to your account](https://www.spotify.com/account/apps/) and click **REMOVE ACCESS**. ## Troubleshooting -**`403 Forbidden` on playback endpoints** — Spotify requires Premium for `play`, `pause`, `skip`, and volume control. Search, playlists, and library reads work on Free. +**`403 Forbidden — Player command failed: No active device found`** — You need Spotify running on at least one device. Open the Spotify app on your phone, desktop, or web player, start any track for a second to register it, and retry. `spotify_devices list` shows what's currently visible. -**`204 No Content` on `now_playing`** — nothing is currently playing; expected behavior, not an error. +**`403 Forbidden — Premium required`** — You're on a Free account trying to use a playback-mutating action. See the feature matrix above. -**`INVALID_CLIENT: Invalid redirect URI`** — the redirect URI registered in your Spotify app doesn't match what Hermes is using. Default is `http://127.0.0.1:43827/spotify/callback`. If you picked something else, set `HERMES_SPOTIFY_REDIRECT_URI` in `~/.hermes/.env` to match. +**`204 No Content` on `now_playing`** — nothing is currently playing on any device. This is Spotify's normal response, not an error; Hermes surfaces it as an explanatory empty result. -**`429 Too Many Requests`** — Spotify rate limit. Hermes surfaces this as a friendly error; wait a minute and retry. +**`INVALID_CLIENT: Invalid redirect URI`** — the redirect URI in your Spotify app settings doesn't match what Hermes is using. The default is `http://127.0.0.1:43827/spotify/callback`. Either add that to your app's allowed redirect URIs, or set `HERMES_SPOTIFY_REDIRECT_URI` in `~/.hermes/.env` to whatever you registered. + +**`429 Too Many Requests`** — Spotify's rate limit. Hermes returns a friendly error; wait a minute and retry. If this persists, you're probably running a tight loop in a script — Spotify's quota resets roughly every 30 seconds. + +**`401 Unauthorized` keeps coming back** — Your refresh token was revoked (usually because you removed the app from your account, or the app was deleted). Run `hermes auth spotify` again. + +**Wizard doesn't open the browser** — If you're over SSH or in a container without a display, Hermes detects it and skips the auto-open. Copy the dashboard URL it prints and open it manually. ## Advanced: custom scopes -By default Hermes requests the scopes needed for every shipped tool. To override: +By default Hermes requests the scopes needed for every shipped tool. Override if you want to restrict access: ```bash hermes auth spotify --scope "user-read-playback-state user-modify-playback-state playlist-read-private" ``` -See Spotify's [scope reference](https://developer.spotify.com/documentation/web-api/concepts/scopes) for available values. +Scope reference: [Spotify Web API scopes](https://developer.spotify.com/documentation/web-api/concepts/scopes). If you request fewer scopes than a tool needs, that tool's calls will fail with 403. ## Advanced: custom client ID / redirect URI @@ -115,4 +205,12 @@ HERMES_SPOTIFY_CLIENT_ID= HERMES_SPOTIFY_REDIRECT_URI=http://localhost:3000/callback ``` -The redirect URI must be allow-listed in your Spotify app's settings. +The redirect URI must be allow-listed in your Spotify app's settings. The default works for almost everyone — only change it if port 43827 is taken. + +## Where things live + +| File | Contents | +|------|----------| +| `~/.hermes/auth.json` → `providers.spotify` | access token, refresh token, expiry, scope, redirect URI | +| `~/.hermes/.env` | `HERMES_SPOTIFY_CLIENT_ID`, optional `HERMES_SPOTIFY_REDIRECT_URI` | +| Spotify app | owned by you at [developer.spotify.com/dashboard](https://developer.spotify.com/dashboard); contains the Client ID and the redirect URI allow-list |