mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
docs(spotify): expand feature page with tool reference, Free/Premium matrix, troubleshooting (#15135)
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.
This commit is contained in:
parent
fe9d9a26d8
commit
9be17bb84f
1 changed files with 134 additions and 36 deletions
|
|
@ -1,13 +1,14 @@
|
||||||
# Spotify
|
# 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
|
## Prerequisites
|
||||||
|
|
||||||
- A Spotify account (Free works for most tools; **playback control requires Premium**)
|
- 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
|
- 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
|
## Setup
|
||||||
|
|
||||||
|
|
@ -17,7 +18,7 @@ Unlike most Hermes integrations, Spotify requires every user to register their o
|
||||||
hermes tools
|
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
|
### 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
|
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
|
1. Opens `https://developer.spotify.com/dashboard` in your browser
|
||||||
2. Tells you exactly what values to paste into the Spotify form
|
2. Prints the exact values to paste into Spotify's "Create app" form
|
||||||
3. Prompts you for the `Client ID` you get back
|
3. Prompts you for the Client ID you get back
|
||||||
4. Saves it to `~/.hermes/.env` and continues straight into the OAuth flow
|
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)
|
### 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 |
|
| 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`) |
|
| App description | anything (e.g. `personal Hermes integration`) |
|
||||||
| Website | leave blank |
|
| Website | leave blank |
|
||||||
| Redirect URI | `http://127.0.0.1:43827/spotify/callback` |
|
| 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
|
## Verify
|
||||||
|
|
||||||
|
|
@ -54,25 +60,101 @@ Agree to the terms, click **Save**. On the next screen click **Settings** → co
|
||||||
hermes auth status spotify
|
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
|
## 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 |
|
```
|
||||||
|------|---------|
|
> play some miles davis
|
||||||
| `spotify_playback` | play, pause, skip, seek, volume, now playing, playback state |
|
> what am I listening to
|
||||||
| `spotify_devices` | list devices, transfer playback |
|
> add this track to my Late Night Jazz playlist
|
||||||
| `spotify_queue` | inspect queue, add tracks to queue |
|
> skip to the next song
|
||||||
| `spotify_search` | search tracks, albums, artists, playlists |
|
> make a new playlist called "Focus 2026" and add the last three songs I played
|
||||||
| `spotify_playlists` | list, get, create, update, add/remove tracks |
|
> which of my saved albums are by Radiohead
|
||||||
| `spotify_albums` | get album, list album tracks |
|
> search for acoustic covers of Blackbird
|
||||||
| `spotify_saved_tracks` | list, save, remove |
|
> transfer playback to my kitchen speaker
|
||||||
| `spotify_saved_albums` | list, save, remove |
|
```
|
||||||
| `spotify_activity` | recently played, now playing |
|
|
||||||
|
|
||||||
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
|
## Sign out
|
||||||
|
|
||||||
|
|
@ -80,27 +162,35 @@ The agent picks the right tool automatically. Ask it to "play some Miles Davis,"
|
||||||
hermes auth logout spotify
|
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
|
## 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
|
## 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
|
```bash
|
||||||
hermes auth spotify --scope "user-read-playback-state user-modify-playback-state playlist-read-private"
|
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
|
## Advanced: custom client ID / redirect URI
|
||||||
|
|
||||||
|
|
@ -115,4 +205,12 @@ HERMES_SPOTIFY_CLIENT_ID=<your_id>
|
||||||
HERMES_SPOTIFY_REDIRECT_URI=http://localhost:3000/callback
|
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 |
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue