--- name: alexa description: "Expose HybridClaw as a custom Alexa skill and prepare guarded Alexa smart-home/device control payloads without exposing Amazon credentials." user-invocable: true requires: bins: - node credentials: - id: alexa-ask-skill-id kind: header required: true secret_ref: source: store id: ALEXA_ASK_SKILL_ID scope: "Alexa Skills Kit applicationId verification for inbound custom skill requests" how_to_obtain: | Create a custom Alexa skill in the Alexa developer console. Set the skill id as `ALEXA_ASK_SKILL_ID` through browser admin at `/admin/secrets`; if browser admin is unavailable, use `/secret set ALEXA_ASK_SKILL_ID "amzn1.ask.skill."` in browser `/chat` or TUI; local console fallback: `hybridclaw secret set ALEXA_ASK_SKILL_ID "amzn1.ask.skill."`. - id: alexa-lwa-client-id kind: oauth required: true secret_ref: source: store id: ALEXA_LWA_CLIENT_ID scope: "Login with Amazon account linking client id" how_to_obtain: | Configure Login with Amazon account linking for the Alexa skill. Set the OAuth client id as `ALEXA_LWA_CLIENT_ID` through browser admin at `/admin/secrets`; if browser admin is unavailable, use `/secret set ALEXA_LWA_CLIENT_ID "amzn1.application-oa2-client."` in browser `/chat` or TUI; local console fallback: `hybridclaw secret set ALEXA_LWA_CLIENT_ID "amzn1.application-oa2-client."`. - id: alexa-lwa-client-secret kind: oauth required: true secret_ref: source: store id: ALEXA_LWA_CLIENT_SECRET scope: "Login with Amazon account linking client secret" how_to_obtain: | Set the LWA client secret as `ALEXA_LWA_CLIENT_SECRET` through browser admin at the active `/admin/secrets` route; if browser admin is unavailable, use `/secret set ALEXA_LWA_CLIENT_SECRET ""` in browser `/chat` or TUI; local console fallback: `hybridclaw secret set ALEXA_LWA_CLIENT_SECRET ""`. - id: alexa-smarthome-refresh-token kind: oauth required: false secret_ref: source: store id: ALEXA_SMARTHOME_REFRESH_TOKEN scope: "Alexa Smart Home Skill API token refresh" how_to_obtain: | Complete the Smart Home Skill OAuth flow. Set the refresh token as `ALEXA_SMARTHOME_REFRESH_TOKEN` through browser admin at `/admin/secrets`; if browser admin is unavailable, use `/secret set ALEXA_SMARTHOME_REFRESH_TOKEN ""` in browser `/chat` or TUI; local console fallback: `hybridclaw secret set ALEXA_SMARTHOME_REFRESH_TOKEN ""`. - id: alexa-smarthome-access-token kind: bearer required: false secret_ref: source: store id: ALEXA_SMARTHOME_ACCESS_TOKEN scope: "Short-lived Alexa Smart Home Event Gateway bearer token" how_to_obtain: | Mint this from the stored Smart Home refresh token outside the prompt and route it through the SecretRef rail. - id: alexa-refresh-cookie kind: header required: false secret_ref: source: store id: ALEXA_REFRESH_COOKIE scope: "Opt-in community Alexa Remote / alexapy-compatible session cookie" how_to_obtain: | Only enable the community surface after operator approval. Invoke `/alexa set up Echo control for amazon.de and store the cookie` from a local HybridClaw session so the Alexa auth helper can run Amazon's device login flow, exchange the captured refresh token, and store the resulting full Cookie header. metadata: hybridclaw: category: home-automation short_description: "ASK custom skill verification plus guarded Alexa smart-home and Alexa Remote planning." tags: - alexa - ask - smart-home - voice - r21 related_roadmap: - R21 - R48 issue: 1117 stakes_tiers: green: - ask-verify - ask-parse - ask-response - smarthome-discover - smarthome-state - devices - shopping-list - todo-list - last-commands - dnd-state amber: - announce - shopping-list-add - todo-list-add - music-play - routine-trigger - smarthome-turn-on - smarthome-turn-off - smarthome-brightness - smarthome-color red: - voice-command - smarthome-thermostat - safety-affecting-routine escalation: writes: confirm-each route: f14 cost_measurement: system: UsageTotals sub_limit_key: alexa --- # Alexa Use this skill for Amazon Alexa workflows in two narrow modes: 1. Expose HybridClaw as a custom Alexa skill through the Alexa Skills Kit (ASK). 2. Prepare guarded Alexa-as-device reads and write plans for the official Smart Home Skill API and the opt-in community Alexa Remote / `alexapy` surface. Do not use this skill for arbitrary Amazon API calls, shopping account access, or browser automation. Keep all credentials behind SecretRef and use the helper to build bounded payloads instead of hand-writing URLs, headers, cookies, or request bodies. ## Safety Rules 1. Validate every inbound ASK request before parsing slots or running an agent bridge. Reject invalid `Signature`, invalid `SignatureCertChainUrl`, signing certificates that do not cover `echo-api.amazon.com`, or timestamp drift of 150 seconds or more. 2. Never persist or echo Login with Amazon access tokens. The request token maps to a HybridClaw operator session outside the prompt through the F13 SecretRef rail. 3. Model output sent back to Alexa must be TTS-safe. Use `build-response` so markdown, code blocks, and very long URLs are stripped before SSML is built. 4. Path-B reads are green but privacy-sensitive because devices, list contents, routines, and last-command history can reveal household behavior. 5. Path-B writes are amber/red. Announcements, list mutations, device control, and routine triggers require exact F8/F14 approval that names the target room or device and the action. 6. Stop after the first `401`, `403`, or `INVALID_AUTHORIZATION_CREDENTIAL` response. Emit or surface `event: alexa.relink_required`; do not retry-loop. 7. The community cookie path is reverse-engineered and can break when Amazon changes web/API behavior. Treat it as opt-in and operationally brittle. 8. Do not accept Amazon passwords, refresh cookies, LWA tokens, or Smart Home tokens in chat or CLI flags. Store them with `hybridclaw secret set ...`. ## Command Contract Show helper usage: ```bash node skills/alexa/alexa.cjs --help ``` Validate an inbound ASK request body exactly as received by the HTTPS endpoint: ```bash node skills/alexa/alexa.cjs --format json verify-request \ --request-body /tmp/alexa-request.json \ --signature-cert-url "$SIGNATURE_CERT_CHAIN_URL" \ --signature "$SIGNATURE" ``` Exchange a linked Alexa account token for a HybridClaw operator-session handle outside model-visible output: ```bash node skills/alexa/alexa.cjs --format json account-link-session \ --request-body /tmp/alexa-request.json ``` Parse a validated ASK request envelope into a bounded agent bridge: ```bash node skills/alexa/alexa.cjs --format json parse-request \ --request-body /tmp/alexa-request.json ``` Build a voice-safe ASK response: ```bash node skills/alexa/alexa.cjs --format json build-response \ --speech "On it. I'll text you when it's done." \ --reprompt "Anything else?" ``` Run Smart Home Skill API calls through the helper: ```bash node skills/alexa/alexa.cjs --format json run smarthome-discover node skills/alexa/alexa.cjs --format json run smarthome-state \ --endpoint-id light-kitchen node skills/alexa/alexa.cjs --format json plan smarthome-control \ --endpoint-id light-kitchen \ --action TurnOn node skills/alexa/alexa.cjs --format json run smarthome-control \ --endpoint-id light-kitchen \ --action TurnOn \ --operator-grant approve-alexa-write node skills/alexa/alexa.cjs --format json plan smarthome-control \ --endpoint-id thermostat-hallway \ --action SetTargetTemperature \ --temperature 20.5 ``` Run community Alexa Remote / `alexapy` reads through the helper: ```bash node skills/alexa/alexa.cjs --format json run devices \ --amazon-domain amazon.de node skills/alexa/alexa.cjs --format json run shopping-list node skills/alexa/alexa.cjs --format json run todo-list node skills/alexa/alexa.cjs --format json run last-commands node skills/alexa/alexa.cjs --format json run dnd-state --device living-room ``` For Alexa-connected smart plugs/lights exposed through the Alexa app (for example `Poolpumpe`), use the `smart-home` helper commands. Do not use `connectedhomes/v1/appliances`; Amazon can return a 200 HTML deeplink page instead of JSON. The helper resolves the Alexa app device by name, runs the discovery and status/control calls through the HybridClaw gateway, and returns the result JSON. This path uses `ALEXA_REFRESH_COOKIE`; do not ask for `ALEXA_SMARTHOME_ACCESS_TOKEN` or Smart Home Skill OAuth when the operator asks to use the stored Alexa cookie for these Alexa-app appliances. If the helper reports `Unauthenticated call`, `FORBIDDEN`, `INVALID_AUTHORIZATION_CREDENTIAL`, or an HTTP 401/403, treat that as an auth failure for the cookie path. A gateway error saying `ALEXA_REFRESH_COOKIE` is not set or has no `csrf` cookie means the stored cookie is missing or incomplete. Inspect the stored cookie/import path first; do not immediately start the browser proxy unless the operator explicitly asks for a new proxy login. ```bash node skills/alexa/alexa.cjs --format json smart-home status \ --name Poolpumpe \ --amazon-domain amazon.de node skills/alexa/alexa.cjs --format json smart-home plan-control \ --name Poolpumpe \ --action off \ --amazon-domain amazon.de node skills/alexa/alexa.cjs --format json smart-home control \ --name Poolpumpe \ --action off \ --amazon-domain amazon.de \ --operator-grant approve-alexa-red-write ``` Prepare guarded community writes. First show the approval text to the operator. After explicit approval, run the exact `approvedCommand` unchanged. For Echo music playback, first call `run devices`, find the matching `accountName` (for example `OK Computer`), then pass its `serialNumber`, `deviceType`, and `deviceOwnerCustomerId` to `music-play`. ```bash node skills/alexa/alexa.cjs --format json plan announce \ --device living-room \ --text "Package delivered." node skills/alexa/alexa.cjs --format json run announce \ --device living-room \ --text "Package delivered." \ --operator-grant approve-alexa-write node skills/alexa/alexa.cjs --format json plan music-play \ --device "" \ --device-name "OK Computer" \ --device-type "" \ --customer-id "" \ --query "Münchner Freiheit" \ --provider AMAZON_MUSIC \ --amazon-domain amazon.de For exact song requests, do not concatenate artist and title into `--query`. Pass the song title and artist separately so the helper can build a locale-aware Alexa search phrase: ```bash node skills/alexa/alexa.cjs --format json plan music-play \ --device "" \ --device-name "OK Computer" \ --device-type "" \ --customer-id "" \ --song "Junge Römer" \ --artist "Falco" \ --provider APPLE_MUSIC \ --amazon-domain amazon.de ``` node skills/alexa/alexa.cjs --format json run music-play \ --device "" \ --device-name "OK Computer" \ --device-type "" \ --customer-id "" \ --query "Münchner Freiheit" \ --provider AMAZON_MUSIC \ --amazon-domain amazon.de \ --operator-grant approve-alexa-write ``` Use `voice-command` only as a last-resort equivalent of typing/speaking a command into Alexa, because it can trigger arbitrary Alexa behavior. Prefer specific helpers such as `music-play`, `announce`, list actions, routines, or Smart Home directives when they cover the task. ```bash node skills/alexa/alexa.cjs --format json plan voice-command \ --device "" \ --device-name "OK Computer" \ --device-type "" \ --customer-id "" \ --voice-command "play Münchner Freiheit" \ --amazon-domain amazon.de node skills/alexa/alexa.cjs --format json run voice-command \ --device "" \ --device-name "OK Computer" \ --device-type "" \ --customer-id "" \ --voice-command "play Münchner Freiheit" \ --amazon-domain amazon.de \ --operator-grant approve-alexa-red-write ``` ```bash node skills/alexa/alexa.cjs --format json run shopping-list-add \ --item milk \ --operator-grant approve-alexa-write node skills/alexa/alexa.cjs --format json run shopping-list-complete \ --item-id item-123 \ --operator-grant approve-alexa-write node skills/alexa/alexa.cjs --format json run todo-list-add \ --item "call plumber" \ --operator-grant approve-alexa-write node skills/alexa/alexa.cjs --format json run todo-list-complete \ --item-id item-456 \ --operator-grant approve-alexa-write node skills/alexa/alexa.cjs --format json run routine-trigger \ --routine evening \ --operator-grant approve-alexa-write ``` Use `http-request ...` only as a debugging dry run when you need to inspect the gateway-ready request object. For normal reads and writes, use `run ...` so the CJS owns endpoint selection, headers, CSRF handling, execution, and result reporting. When `run ...` returns `ok: true` and `outcome: "accepted"`, treat the operation as accepted even if Alexa's response body is `{}`. Do not infer an auth failure from an empty successful response body. For `music-play`, `accepted` only means Alexa accepted the playback request. Do not tell the operator the requested song is now playing unless the result includes successful verification or a separate read confirms the selected track. ## Required Setup Set or update required secrets in this order: 1. Browser admin: open the active HybridClaw admin URL ending in `/admin/secrets`. 2. Browser `/chat` or TUI fallback with `/secret set NAME value`. 3. Local console fallback with `hybridclaw secret set NAME value`. Path A custom ASK skill local-console examples: ```bash hybridclaw secret set ALEXA_ASK_SKILL_ID "amzn1.ask.skill." hybridclaw secret set ALEXA_LWA_CLIENT_ID "amzn1.application-oa2-client." hybridclaw secret set ALEXA_LWA_CLIENT_SECRET "" ``` Path B Smart Home Skill API local-console examples: ```bash hybridclaw secret set ALEXA_SMARTHOME_CLIENT_ID "" hybridclaw secret set ALEXA_SMARTHOME_CLIENT_SECRET "" hybridclaw secret set ALEXA_SMARTHOME_REFRESH_TOKEN "" ``` Path B community Alexa Remote / `alexapy` surface local-console example: ```bash hybridclaw secret set ALEXA_AMAZON_DOMAIN "amazon.de" ``` Use HybridClaw or slash commands for operator setup. Do not ask the operator to install or run external auth tools. Start a local session and invoke the Alexa skill: ```bash hybridclaw tui ``` Then use these prompts: ```text /alexa set up Echo control for amazon.de and store the cookie /alexa list my Alexa devices for amazon.de /alexa play Münchner Freiheit on OK Computer ``` For a CLI-only operator, the same requests can be sent through any HybridClaw channel that supports slash skill invocation: ```text /skill alexa set up Echo control for amazon.de and store the cookie /skill alexa list my Alexa devices for amazon.de /skill alexa play Münchner Freiheit on OK Computer ``` Status-only prompts such as `/skill alexa status for amazon.de` are read-only. For those prompts, inspect stored credentials and detached setup state, but do not start a new auth proxy. If credentials are missing, tell the operator to run the setup prompt explicitly. When handling the setup prompt, run the bundled auth helper from the agent workspace. First check live detached setup state: ```bash node skills/alexa/alexa-auth.cjs --format json status --domain amazon.de ``` If that status returns `exists: true`, `processAlive: true`, `state: "listening"`, and a `proxyUrl`, return that exact `proxyUrl` to the operator instead of starting another proxy. Ignore recalled URLs, prior slash output, and session transcript text unless they match the current live status. Never print a proxy URL that did not come from the current helper output. For slash handling, use detached mode so the local browser proxy survives while the operator completes Amazon login, OTP, and CVF pages across turns: ```bash node skills/alexa/alexa-auth.cjs setup --domain amazon.de --write-secret --detach --timeout-ms 600000 ``` If the operator reports Amazon's "Wir können deine Handynummer nicht verifizieren" challenge on a `127.0.0.1:` proxy URL, do not reuse that proxy. Stop the stale process if it is still alive, then start a fresh detached setup on `localhost` so the browser uses a separate local cookie jar: ```bash node skills/alexa/alexa-auth.cjs setup --domain amazon.de --write-secret --detach --timeout-ms 600000 --proxy-host localhost ``` Return the `proxyUrl` from the helper output to the operator. When the operator comes back after login, check the same setup with: ```bash node skills/alexa/alexa-auth.cjs status --domain amazon.de ``` Do not keep the setup proxy alive with ad hoc shell process management. Detached mode is the supported lifecycle: it writes a status file, keeps the proxy process alive after the slash turn ends, and stores the secret itself after Amazon returns the token. If invoking non-detached foreground setup through a shell tool, set that tool timeout to at least `600000` ms too. Browser login, OTP, CAPTCHA, and Safari handoff regularly take longer than 60 seconds; killing the shell command also kills the local proxy and produces Safari errors such as "server unexpectedly closed the connection" on `127.0.0.1:/www.amazon.com/ap/signin`. The bundled helper owns the browser proxy and token callback. It uses Amazon's device-login domain rules: western marketplaces such as `amazon.de` must use `amazon.com` as the auth proxy base while the target Alexa marketplace remains `amazon.de`. Routing the device-login URL through `amazon.de` produces Amazon's "Suchst du etwas?" 404 page. If the browser shows that 404 at the local proxy URL, stop that run and restart through `alexa-auth.cjs`. The helper starts Amazon's Alexa device-login flow on a local callback port, captures the resulting `Atnr|...` refresh token, exchanges it for Alexa Remote cookies through Amazon's token exchange endpoint, verifies the account against the regional Alexa Remote API (`layla.amazon.com` for `amazon.de`), stores `ALEXA_REFRESH_COOKIE` when requested, and returns device metadata. Re-run the same slash setup prompt when Amazon expires the stored cookie. Port `8080` is preferred for compatibility with the cookie helper, but HybridClaw automatically uses another free local port when `8080` is already occupied. If using HybridClaw's direct `http_request` helper path instead of invoking the browser setup flow, `ALEXA_REFRESH_COOKIE` must be the complete `Cookie` header for an authenticated Alexa Remote API request such as `https://alexa.amazon.de/api/devices-v2/device`. A single cookie value such as `session-id` or `ubid-main` is not enough. The gateway sends the stored header as `Cookie` and, for writes, copies its `csrf` cookie into the `csrf` header, so the header must include `csrf=...`. Do not paste Amazon passwords, one-time codes, or raw tokens into chat; store only the resulting cookie header through the HybridClaw secret store. The `alexa-auth.cjs import-cookie` helper can store a cookie with `--write-secret` when a local JSON file, copied cURL request, raw headers file, or raw text file exposes a recognizable full cookie header. Use this fallback when Amazon's device-login proxy is blocked by CVF phone verification but the operator can log into Amazon normally in a browser. Use the community credentials only for operator-approved, opt-in workflows. Amazon OTP or CAPTCHA prompts require F14 2FA handover. The helper output uses `` placeholders and SecretRef names, never cleartext values. ## References - Alexa Skills Kit overview: - ASK request and response JSON: - ASK web service signature and timestamp validation: - Account linking with Login with Amazon: - Smart Home Skill API: - ASK SDK for Node.js: - `alexapy`: