control
Control connected devices and services, retrieve results, and capture camera snapshots.
Discover the device with endpoint_query or the room with group_query. Copy its full id, message and optional routeId; use the documented payload for the declared message. Send a matching payload ({} for a command without fields). Preserve the account that returned the IDs and clarify ambiguous targets before writes.
Most controls return status accepted: dispatch succeeded, but the physical outcome is unconfirmed. For result-returning commands, such as search, library pages and get-snapshot, set waitForResult=true. A correlated result returns status responded; snapshots also return image pixels and timeOfSample. Outbound declarations include events, so they do not guarantee that every command responds. For playback, volume and power, omit waitForResult and verify fresh state using endpoint_query or group_query with declared expand capabilities and forceDeviceAttributeQuery=true.
Live music queue recipe for "set up a playlist and play it on my Sonos": build an active playback queue unless the customer also asks to save a reusable library playlist. This recipe is available to tools-only clients without resources/read or bundled skills.
Discover the Spotify library and the requested speaker or native group. On the library's declared media-search/search-media message, use payload {"query":"","type":"track"} and waitForResult=true. Copy playable canonical track IDs from the returned tracks; do not invent IDs or pass a search phrase to playback.
Select the target route declaring media-queue, preferring the native Sonos route when available. Check its supportedMediaResources and maxItemsPerPlay. Send one play-queue message with payload {"mediaIds":["",""]} and the copied routeId. This starts a new ordered selection. play-queue has no queueVersion field; requiresQueueVersion applies only to add-to-queue. Do not emulate a queue with repeated single-track play-media commands.
Send get-queue with payload {} and waitForResult=true on the same target and route. queue-contents returns currentMediaId, upcoming mediaIds, complete and an optional queueVersion. complete=false is a limited window, not proof that other songs are absent. Read FRESH media-player observations with endpoint_query/group_query, expand=["media-player"] and forceDeviceAttributeQuery=true before claiming playback.
To add music without restarting, search for another track and send add-to-queue once with {"mediaId":""}. If requiresQueueVersion=true, first read get-queue and include its exact queueVersion in that append payload. Spotify Connect does not accept queueVersion; omit it there. Read the queue again after each append. A conflict or uncertain write requires inspection, never an automatic retry or replacement selection. No saved-playlist command is needed for this live-queue workflow.
A failed search does not establish that the speaker stopped or the whole connection is unavailable. Preserve current playback, report the failed operation, and use fresh device observations for playback claims. Do not substitute remembered song names or invented IDs for returned playable tracks. The search payload type is lowercase "track", not the uppercase capability configuration label "TRACK".
Room lighting scenes: use group_query with expand:["scene"] and forceDeviceAttributeQuery:true, select the requested native provider group/route, and inspect its declared messages. To recall an available scene, send scene/activate with {"sceneId":""} on that group and route. To save a new scene, first set the requested member lighting states, then send its declared scene/create-scene with {"name":""} and waitForResult=true. This snapshots the group's current light settings; it does not activate the scene. Use the returned scene-created.sceneId for activate, and fresh-query available-scenes before repeating an uncertain create. After recall, verify each affected light's fresh power/brightness and supported color state; dispatch acceptance or a scene label alone does not prove every light changed. Never create or recall a scene on another room or provider route as a fallback.
Use only capabilities and commands declared by the selected device or service. Examples of device classes and providers, subject to the connected integration's support:
Lights, switches and plugs: on/off and brightness (Philips Hue, Tuya, TP-Link).
Phones, tablets, laptops, wallets and trackers: locate or ring (Apple Find My, Tile).
Thermostats and temperature sensors: heat/cool settings; read ambient temperature with endpoint_query (Nest, Tuya, ecobee).
Cameras: request a declared get-snapshot command and inspect the returned pixels (Ring, Nest and other cameras). A snapshot is distinct from live video.
Connectivity and battery: check declared observations with endpoint_query for phones, watches, locks and other devices.
Smart locks and PINs: use declared lock and PIN commands (August, Yale, Ring, Seam).
Home appliances: supported controls and running-state observations (Samsung, LG, Xiaomi).
Robot vacuums: clean rooms and return to dock (Roomba, Roborock, Dreame). Send clean-room to the robot listing the room in controllableGroups with {"groupIds": []}. Bounded remote driving requires fresh visual feedback; cleaning is not navigation.
Speakers and announcements: supported speech and audio playback (Sonos, Alexa, Nest cameras).
TVs, remotes and media libraries: playback, volume, search and declared playlist operations (Spotify, Fire TV, YouTube, Chrome, TCL, Samsung, LG).
Files and photos: declared browse, download, upload, rename, move and delete commands (iCloud Photos, iCloud Drive, Google Drive, Outlook). download-file returns a URI; catalog presence alone does not establish upload support.
Litter robots and pet appliances: declared cleaning, waste and dispensing observations or controls.
Water sensors and sprinklers: declared water detection, watering state and controls.
Calendars and reminders: declared list, create, complete, reschedule and delete operations (iCloud Calendar and Reminders). Connected reminders are distinct from assistant-created scheduled tasks.
Read the relevant bundled skill reference or portos://guides/index for unfamiliar workflows. File/reminder deletion and PIN changes modify account data. Inspect partial or uncertain writes before another action. result_timeout means unknown outcome: read state before considering a retry. MESSAGE_UNSUPPORTED or MESSAGE_AMBIGUOUS means nothing was sent; correct the message from discovery. An unreachable device rejected the command. Never automatically retry a state-changing command or claim success from conflicting observations.
Use endpoint_manage/group_manage to change names, types, membership or merges.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Full Port OS endpoint ID (…/endpoints/…) from endpoint_query or group ID (…/endpoint-groups/…) from group_query. | |
| message | Yes | Full message ID copied from the target's messages: <capability-interface-namespace>/messages/<message-name>, with an @<version> suffix only when the listed ID has one. | |
| payload | Yes | JSON object matching the message payload schema. Use {} for messages without fields. | |
| routeId | No | Optional provider route ID copied from the target routes. Reuse it for pause, resume and volume after playing through that provider. It must belong to id and advertise the requested message. Without it, the route declaring the most interfaces is used, then the highest route ID. | |
| waitForResult | No | Wait for one correlated, schema-validated result for commands that retrieve results, such as camera snapshots, media search or library pages, when outboundMessages are declared. Playback and volume commands do not return correlated results. For power and other response-less controls omit it, then read fresh state with endpoint_query. | |
| correlationToken | No | Optional caller-provided correlation token. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||