Query and control Aqara/Lumi Studio smart home devices and manage spaces via the Aqara Open Platform API (HTTP JSON). Use when the user asks to list Aqara de...
This skill equips the agent to operate Aqara/Lumi Studio smart home devices via HTTPS requests to the Aqara Open Platform API. All operations are performed exclusively through curl commands, except GetAllDevicesWithSpaceRequest, which must be executed through bash scripts/fetch_all_devices.sh to refresh the local cache file data/devices.json.
This skill supports only:
The following environment variables are required:
AQARA_ENDPOINT_URL: The base URLAQARA_OPEN_API_TOKEN: Your Long-Lived Access Token.This section is a navigation and execution summary only. It does not add new rules or change existing constraints.
deviceId, endpointId, functionCode, and traitCode from cachedata/devices.jsonbash scripts/fetch_all_devices.shdata/devices.json existsdeviceId + endpointId + functionCode + traitCode from cachecurl for ExecuteTraitRequestcurl for GetDeviceTypeInfosRequestbash scripts/fetch_all_devices.shcurl for GetSpacesRequestspaceId from GetSpacesRequestCreateSpaceRequest or UpdateSpaceRequestspaceId from GetSpacesRequestdeviceId values from data/devices.jsonAssociateDevicesToSpaceRequestGetAllDevicesWithSpaceRequest may only be executed via bash scripts/fetch_all_devices.sh.curl.type, version, msgId, and data; version must always be "v1".type is whitelist-only: use only the exact request types listed in this document; never test guessed alternatives such as GetAllSpacesRequest, GetSpaceListRequest, or QuerySpaceListRequest.deviceId, endpointId, functionCode, traitCode, or spaceId.data/devices.json existsdeviceId, endpointId, functionCode, and traitCode from the cache filespaceId is needed, call GetSpacesRequest firstspaceId from GetSpacesRequest and deviceId values from data/devices.jsondata/devices.json, which stores the data array from GetAllDevicesWithSpaceRequestendpoints[].endpointIdGetSpacesRequest or cached space.spaceId## API Protocol### Execution Model### File Cache Model (Cache-First Data Model)## API Commands under ### Device Management### Space Management## Standard Operating Procedures (SOP)## Cache Decision Tree and ## API Call Decision Tree## Forbidden Behaviorreferences/trait-codes.mdRole: You are a strict hardware interface controller. Never infer or guess IDs or capability fields.
Any operation involving live device state, such as power, brightness, or temperature, must follow this rule:
| Power status | Valid interpretation | Response style |
|---|---|---|
Switch == "false" | Brightness / color temperature / power should be treated as 0 or "off" | "The device is currently off" |
Switch == "true" | Use the actual returned value | "Brightness is X%" |
Never produce logically inconsistent output such as "the light is off but brightness is 100%".
AQARA_OPEN_API_TOKEN: your Aqara Open API Bearer token (JWT)AQARA_ENDPOINT_URL: the API base URLReal environment value rule: AQARA_ENDPOINT_URL and AQARA_OPEN_API_TOKEN must be read from the runtime environment (via $AQARA_ENDPOINT_URL and $AQARA_OPEN_API_TOKEN). Do not guess, fabricate, or use example placeholders as real request values. If either variable is missing or empty, tell the user to configure it first.
curl -s -X POST "$AQARA_ENDPOINT_URL" \
-H "Authorization: Bearer $AQARA_OPEN_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"type":"GetAllDevicesWithSpaceRequest","version":"v1","msgId":"test-1"}'
Base URL: $AQARA_ENDPOINT_URL
All requests use a single unified POST endpoint. Routing is determined by the type field in the JSON body.
The request-body JSON may contain exactly these 4 fields. Do not add, remove, or replace fields:
{
"type": "<RequestType>",
"version": "v1",
"msgId": "<unique-id>",
"data": { ... }
}
| Field | Required | Meaning | Forbidden behavior |
|---|---|---|---|
type | Yes | API method name, such as ExecuteTraitRequest or GetSpacesRequest | Do not modify, abbreviate, or replace it with a value not listed in this document |
version | Yes | Must be the string "v1" | Do not omit it; do not use "v2", "1.0", or any other value |
msgId | Yes | Unique request identifier, such as "msg-1234567890" | None |
data | Yes | Payload for the selected type (null, object, array, or string depending on the request) | Only use structures defined in this document or references/ |
Strict request-body constraints
version: every curl request body must include "version":"v1".senderId, source, timestamp, or any field not defined in this document.data may contain made-up fields or undocumented shapes.type values: if this document says the request type is GetSpacesRequest, then type must be exactly GetSpacesRequest.type: names such as GetAllSpacesRequest, GetSpaceListRequest, QuerySpaceListRequest, ListSpacesRequest, or other self-created variants are forbidden unless they are explicitly documented in this file.Authorization: Bearer $AQARA_OPEN_API_TOKEN
Content-Type: application/json
{
"type": "<ResponseType>",
"version": "v1",
"msgId": "<matching-id>",
"code": 0,
"message": null,
"data": { ... }
}
code: 0 = success. Non-zero = error. Common error codes:
The -d value for every curl request must be a JSON object with only 4 keys: type, version, msgId, and data. Replace <TYPE> with the API method name and <DATA> with the correct payload:
curl -s -X POST "$AQARA_ENDPOINT_URL" \
-H "Authorization: Bearer $AQARA_OPEN_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"type":"<TYPE>","version":"v1","msgId":"msg-'$(date +%s)'","data":<DATA>}'
Always keep "version":"v1" in -d, and never add senderId or any other field not defined in this document.
Execution rules (must follow):
GetAllDevicesWithSpaceRequest: execute it via bash scripts/fetch_all_devices.sh. The script calls the API and writes the response data to data/devices.json. Do not call this request directly with curl.ExecuteTraitRequest, GetSpacesRequest, CreateSpaceRequest, UpdateSpaceRequest, and AssociateDevicesToSpaceRequest): execute them with bash + curl. The JSON body must contain exactly 4 keys: type, version, msgId, and data.type retries: when a request fails, do not try nearby or similar type names. Verify the documented type, payload shape, token, IDs, cache, and required preconditions, then retry the same documented request only if appropriate.Local cache file
data/devices.json — the data array from GetAllDevicesWithSpaceRequest, including complete device information: deviceId, name, deviceTypesList, state, space, endpoints, and all functions/traits/current valuesRefresh cache (create/overwrite cache file)
bash scripts/fetch_all_devices.sh
Usage rules (must follow)
data/devices.json exists and is non-empty.GetAllDevicesWithSpaceRequest again.bash scripts/fetch_all_devices.sh to refresh the cache. After refresh, re-read the cache file before continuing.bash scripts/fetch_all_devices.sh and then re-read the file.ExecuteTraitRequest) still go directly to the API via curl, but all deviceId / endpointId / functionCode / traitCode values must come from the cache file.NEVER guess, fabricate, or infer deviceId, endpointId, functionCode, or traitCode. Every value used in control calls MUST come from the cached data/devices.json file.
endpointId must be taken from the device's endpoints[].endpointId.functionCode and traitCode must be taken from endpoints[].functions[].traits[].value type must match the trait definition.When the user asks for a subset of devices (for example, all lights, devices in the bedroom, or online switches):
data/devices.json locally by deviceTypesList, name, state, or space.name / space.spatialMarking.deviceTypesList.bash scripts/fetch_all_devices.sh to refresh cache and retry.data/devices.json and run bash scripts/fetch_all_devices.sh to regenerate.GetAllDevicesWithSpaceRequestRetrieve all smart home devices in a single call, including full device info, space assignment, endpoints, functions, traits, and current values. No data field is needed (or data: null).
The agent MUST write this response to the local cache file (data/devices.json) and use the cache for all subsequent device queries, status checks, and as the basis for control commands. Use the provided script to fetch and cache:
bash scripts/fetch_all_devices.sh
Manual curl (for reference only — prefer the script):
curl -s -X POST "$AQARA_ENDPOINT_URL" \
-H "Authorization: Bearer $AQARA_OPEN_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"type":"GetAllDevicesWithSpaceRequest","version":"v1","msgId":"msg-'$(date +%s)'"}'
GetDeviceTypeInfosRequestRetrieve every device type available in the current project. Each entry contains a deviceType code and its localized display name.
curl -s -X POST "$AQARA_ENDPOINT_URL" \
-H "Authorization: Bearer $AQARA_OPEN_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"type":"GetDeviceTypeInfosRequest","version":"v1","msgId":"msg-'$(date +%s)'"}'
ExecuteTraitRequestControl one or more device functions, such as turning on/off or adjusting level. endpointId, functionCode, and traitCode must be read from the cache.
# Turn on
curl -s -X POST "$AQARA_ENDPOINT_URL" \
-H "Authorization: Bearer $AQARA_OPEN_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"type":"ExecuteTraitRequest","version":"v1","msgId":"msg-'$(date +%s)'","data":[{"deviceId":"<deviceId>","endpointId":<endpointId>,"functionCode":"<functionCode>","traitCode":"OnOff","value":true}]}'
# Turn off
curl -s -X POST "$AQARA_ENDPOINT_URL" \
-H "Authorization: Bearer $AQARA_OPEN_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"type":"ExecuteTraitRequest","version":"v1","msgId":"msg-'$(date +%s)'","data":[{"deviceId":"<deviceId>","endpointId":<endpointId>,"functionCode":"<functionCode>","traitCode":"OnOff","value":false}]}'
GetSpacesRequestRetrieve all spaces as a hierarchical tree. Each space includes its ID, name, parent space ID, spatial marking label, and nested children.
Space request type hard rule: the request type for space listing is only GetSpacesRequest. Do not try GetAllSpacesRequest, GetSpaceListRequest, QuerySpaceListRequest, or any other guessed variant.
curl -s -X POST "$AQARA_ENDPOINT_URL" \
-H "Authorization: Bearer $AQARA_OPEN_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"type":"GetSpacesRequest","version":"v1","msgId":"msg-'$(date +%s)'"}'
CreateSpaceRequestCreate a room, zone, or building. Omit parentSpaceId to create a top-level space. Run GetSpacesRequest first if the parent space ID is not known.
# Top-level space
curl -s -X POST "$AQARA_ENDPOINT_URL" \
-H "Authorization: Bearer $AQARA_OPEN_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"type":"CreateSpaceRequest","version":"v1","msgId":"msg-'$(date +%s)'","data":{"name":"Living Room","spatialMarking":"living_room"}}'
# Sub-space
curl -s -X POST "$AQARA_ENDPOINT_URL" \
-H "Authorization: Bearer $AQARA_OPEN_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"type":"CreateSpaceRequest","version":"v1","msgId":"msg-'$(date +%s)'","data":{"name":"Bedroom","parentSpaceId":"<parentSpaceId>","spatialMarking":"bedroom"}}'
UpdateSpaceRequestUpdate the name or spatial marking of an existing space. Only provided fields are updated. spaceId is required.
curl -s -X POST "$AQARA_ENDPOINT_URL" \
-H "Authorization: Bearer $AQARA_OPEN_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"type":"UpdateSpaceRequest","version":"v1","msgId":"msg-'$(date +%s)'","data":{"spaceId":"<spaceId>","name":"New Room Name"}}'
AssociateDevicesToSpaceRequestAssign one or more devices to an existing space. Response data only contains failed items; empty means all succeeded.
curl -s -X POST "$AQARA_ENDPOINT_URL" \
-H "Authorization: Bearer $AQARA_OPEN_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"type":"AssociateDevicesToSpaceRequest","version":"v1","msgId":"msg-'$(date +%s)'","data":{"spaceId":"<spaceId>","deviceIds":["<deviceId1>","<deviceId2>"]}}'
data/devices.json exists and is non-empty.bash scripts/fetch_all_devices.sh to generate the cache, then read the file.data/devices.json is missing, run bash scripts/fetch_all_devices.sh first.value.data/devices.json is missing, run bash scripts/fetch_all_devices.sh first.deviceId, endpointId, functionCode, and traitCode from the cache file.ExecuteTraitRequest curl command with only cached values.data only contains failed items; an empty array means all commands succeeded.data/devices.json.GetSpacesRequest curl command to retrieve the full space hierarchy tree.CreateSpaceRequest, UpdateSpaceRequest, or AssociateDevicesToSpaceRequest as needed.Does the user request involve devices, spaces, or types?
├── Yes → Check the local cache file `data/devices.json`
│ ├── Cache hit (file exists and is non-empty)
│ │ └── Read from the file directly and filter/aggregate locally
│ └── Cache miss / missing file
│ ├── Run `bash scripts/fetch_all_devices.sh`
│ ├── Re-read the cache file
│ └── Continue with the refreshed data
└── No → Continue with the normal flow
Does the task require device control?
├── Yes → Ensure `data/devices.json` exists (refresh first if missing)
│ ├── Read `deviceId + endpointId + functionCode + traitCode` from cache
│ └── Call `ExecuteTraitRequest` via curl
└── No → Return the cached data result
Did the user explicitly ask to refresh device data?
└── Run `bash scripts/fetch_all_devices.sh` to overwrite the cache, then re-read it
User wants devices by type?
→ data/devices.json exists? → Yes: filter file by deviceTypesList
→ No: bash scripts/fetch_all_devices.sh, then filter
User wants to list/discover all devices?
→ data/devices.json exists? → Yes: return full list from file
→ No: bash scripts/fetch_all_devices.sh, then read
User wants state of a device?
→ data/devices.json exists? → No: bash scripts/fetch_all_devices.sh
→ Read value from file: endpoints[].functions[].traits[].value
User wants to control a device?
→ data/devices.json exists? → No: bash scripts/fetch_all_devices.sh
→ Get deviceId + endpointId + functionCode + traitCode from file
→ curl ExecuteTraitRequest with correct value type
User wants devices by space/room?
→ data/devices.json exists? → Yes: filter file by space.name / spatialMarking
→ No: bash scripts/fetch_all_devices.sh, then filter
User wants to refresh device data?
→ bash scripts/fetch_all_devices.sh
User wants to see spaces?
→ curl GetSpacesRequest
User wants to create, update, or assign spaces?
→ curl GetSpacesRequest if a real spaceId is needed
→ then curl CreateSpaceRequest / UpdateSpaceRequest / AssociateDevicesToSpaceRequest
| Forbidden | Correct behavior |
|---|---|
Guessing or fabricating deviceId | Always use IDs from data/devices.json cache file. |
Guessing or creating endpointId | Always take from endpoints[].endpointId in cache file. |
Guessing functionCode or traitCode | Always take from endpoints[].functions[].traits[] in cache file. |
Running ExecuteTraitRequest without first resolving device/endpoint info | Ensure data/devices.json exists and use the cached structure. |
Using curl to call GetAllDevicesWithSpaceRequest | Only this request goes through the script: use bash scripts/fetch_all_devices.sh. |
| Calling the script or API for devices when cache file already exists and user did not ask to refresh | Read data/devices.json instead. |
| Making a separate API call to read device status/values | Device status and trait values are already in data/devices.json. |
| Inferring device type from device name | Filter cached devices by deviceTypesList. |
Guessing spaceId | Always use IDs from GetSpacesRequest response or cached device space.spaceId. |
Guessing or testing undocumented request type values | Use only the exact request names listed in Request Type Whitelist. |
| Trying alternate request names after a failure | Keep the documented type unchanged; inspect payload, token, IDs, cache, and preconditions. |
Trying guessed space-list request names such as GetAllSpacesRequest, GetSpaceListRequest, or QuerySpaceListRequest | Use only GetSpacesRequest to list spaces. |
Guessing or fabricating AQARA_ENDPOINT_URL or AQARA_OPEN_API_TOKEN | These must be read from the runtime environment. |
scripts/fetch_all_devices.sh — cache refresh script; calls GetAllDevicesWithSpaceRequest and writes data/devices.jsondata/devices.json — cache file generated by the script; contains complete device datareferences/examples.md — example curl invocationsreferences/trait-codes.md — full list of trait codes with type, unit, read/write, subscribe flagsKeep this SKILL.md lean; consult references for details.
ZIP package — ready to use