Aqara Open API Skill
This file is the single entry router for the Aqara Open Platform HTTP API skill package.
Read this file first. Use it to do four things:
- Classify whether the user request lands in
device,space, orautomation. - Preserve the shared request envelope, credential rules, and non-guessing rules.
- Build a structured handoff contract instead of forwarding raw user prose.
- Decide whether the next step may use cache-first execution or must upgrade to stricter validation.
Child skills:
aqara-open-api-local/device/SKILL.mdaqara-open-api-local/space/SKILL.mdaqara-open-api-local/automation/SKILL.md
Quick Route Table
Use this table before reading any child skill in depth.
| User asks for | Final intent | Next file |
|---|---|---|
| list devices, count devices, read state, control a device | device | aqara-open-api-local/device/SKILL.md |
| list spaces, create or rename spaces, move devices between spaces | space | aqara-open-api-local/space/SKILL.md |
| create automation, inspect automation, update automation config, enable or disable automation, delete automation | automation | aqara-open-api-local/automation/SKILL.md |
| room-scoped device query such as "what lights are in the living room" | device | confirm room identity, then query devices from data/devices.json |
| room-related automation such as "turn on the light when someone is in the living room" | automation | resolve room and device evidence first, then enter automation |
Language Policy
- user-facing explanations, routing notes, and clarification questions should use Chinese Simplified
- Open API request types, field names, file paths, enums, and code examples must keep exact English identifiers
- do not mix Chinese and English in one rule sentence unless an exact identifier must be quoted
Package Model
Treat the three business entities as related, not isolated:
spaceis the container and grouping scope for devicesdeviceis the concrete instance that can be queried, counted, and controlledautomationis the orchestration layer that references rooms, devices, and device traits
Route by the final action target, not by keyword count alone.
Important relationship rule:
- for room-scoped device queries,
spaceis the filter key anddeviceis the answer source GetSpacesRequestconfirms that a room exists or resolvesspaceId; it does not answer which devices are inside the room- the actual room-to-device result must come from
data/devices.jsonby filtering devices whose room membership matches the resolved room
Examples:
- "what devices are in the living room" -> final intent is
device - "move all lights from the master bedroom to the second bedroom" -> final intent is
space - "create an automation that turns on the light when someone is in the living room" -> final intent is
automation
Shared Runtime Contract
Runtime configuration may come from:
AQARA_ENDPOINT_URLAQARA_OPEN_API_TOKENaqara config
Credential resolution order:
- Use the current shell environment if
AQARA_ENDPOINT_URLandAQARA_OPEN_API_TOKENare already set. - Otherwise read the AQARA CLI config file from
~/.aqa/config.json. - Use
aqara config set-endpoint <url>andaqara config set-token <token>when the values are not already configured.
Hard credential rules:
- never guess or hardcode real credentials
- never print the real token in chat, logs, or generated files
- never write secrets into persistent shell startup files
- if the config file is missing or unreadable, stop and report the configuration problem without dumping file contents
Shared API Contract
Global execution rules:
- All execution should go through the
aqaraCLI instead of handwrittencurl. aqara devices cache refreshis the only allowed route forGetAllDevicesWithSpaceRequest.- Every other documented API request should use the matching
aqaracommand group. - The underlying request body may contain only
type,version,msgId, anddata. versionmust always be"v1".typeis whitelist-only. Never guess nearby request names.- Never guess
deviceId,endpointId,functionCode,traitCode,spaceId, orautomationId. - Command examples assume the current working directory is the
aqara-open-api-localpackage root or thataqarais installed globally. - For queries such as "what devices are in the living room", never answer from
GetSpacesRequestalone. Resolve the room first, then filterdata/devices.jsonto produce the device list.
Shared request envelope:
{
"type": "<RequestType>",
"version": "v1",
"msgId": "<unique-id>",
"data": {}
}
CLI execution note:
aqaraencapsulates the request envelope and headers- do not hand-build headers in normal skill execution
Request type whitelist:
GetAllDevicesWithSpaceRequestGetDeviceTypeInfosRequestExecuteTraitRequestGetSpacesRequestCreateSpaceRequestUpdateSpaceRequestAssociateDevicesToSpaceRequestQueryAutomationCapabilitiesRequestCreateAutomationRequestUpdateAutomationRequestUpdateAutomationStatusRequestGetAutomationListRequestGetAutomationDetailsRequestDeleteAutomationRequest
Capability Validation Strategy
This package uses two validation modes for automation work:
cache_first_generate: default path for creation. Use resolved room and device context plusdata/devices.jsonto build an automation-instance styleconfig.query_capabilities_required: stricter path for risky or ambiguous automation work. Upgrade toQueryAutomationCapabilitiesRequestbefore finalizing the config.
Upgrade from cache_first_generate to query_capabilities_required when any of the following is true:
- the needed starter, condition, or action trait cannot be copied safely from
data/devices.json - the request depends on uncertain enum or event values
- the request is cross-space and the source or target mapping is still ambiguous
- the action is high risk, unusual, or not covered by the package's safe defaults
- the user explicitly asks for capability confirmation
Important rule:
data/devices.jsonis the default creation evidence sourceQueryAutomationCapabilitiesRequestis the escalation path, not the default first step
Handoff Contract
Before entering a child skill, build this structured handoff contract in reasoning. These are semantic routing fields only, not new Open API request fields.
Required handoff fields
{
"finalIntentType": "device | space | automation",
"resolvedSpace": {
"name": "<spaceName or null>",
"spaceId": "<spaceId or null>",
"resolutionSource": "route | get_spaces | device_cache | unresolved"
},
"resolvedDevices": [
{
"deviceId": "<deviceId>",
"deviceName": "<display name>",
"spaceName": "<space name or null>",
"spaceId": "<spaceId or null>",
"matchReason": "exact_name | room_plus_name | type_match | parent_context"
}
],
"resolvedAutomation": {
"automationId": "<automationId or null>"
},
"ambiguityState": {
"status": "none | room | device | automation | event_enum",
"questionNeeded": true
},
"operationContext": {
"operation": "query | control | create | update | rename | status | delete",
"cacheFreshness": "fresh | stale | unknown",
"detailsLoaded": false
},
"capabilityValidationMode": "cache_first_generate | query_capabilities_required",
"branchingIntent": {
"needsSplit": false,
"reason": "<optional reason>"
}
}
Handoff rules
- do not hand off the raw user sentence alone
- if room scope is already resolved, pass it as
resolvedSpaceinstead of forcing the child skill to rediscover it - if several candidate devices remain, preserve them in
resolvedDevicesand ask for clarification before mutation - if the request is an automation update, pass whether current automation details have already been loaded
- if a preceding space mutation may have changed room membership, mark
cacheFreshnessasstale
Router SOP
Follow this order. Do not skip steps.
- Parse which entities are mentioned:
space,device,automation. - Classify the final action target.
- Resolve the anchor entity first: room-first, device-first, or automation-first.
- If the task is a room-scoped device query, use
GetSpacesRequestonly to confirm the room identity when needed, then usedata/devices.jsonto reverse lookup the devices in that room. - Build the handoff contract.
- If ambiguity remains, ask before entering a mutating child workflow.
- Enter the child skill whose domain matches
finalIntentType.
Shared Recovery And Reliability Rules
Response code reminders:
code: 0means success400usually means invalid request data1001usually means token expired or invalid2030usually means device not found
Recovery rules:
- device not found during device or space work: refresh
data/devices.jsononce, then re-resolve the device - invalid space update: re-check
spaceId, mutation scope, and device membership - invalid automation request: move to the automation child skill, re-check schema shape, and upgrade validation mode if needed
- network timeout: retry once, then report the failure
- space mutation before automation generation: refresh
data/devices.jsonor markcacheFreshness: "stale"and stop before create
Platform note:
- the package uses
aqara devices cache refreshfor the full device cache - if Node.js or the CLI entry cannot run in the current runtime, stop and explain that the CLI path is unavailable instead of inventing ad hoc shell replacements
Forbidden Behavior
Never do any of the following:
- call Aqara APIs directly with
curlwhen anaqaracommand exists - guess request types or identifiers
- use stale prose memory or trait glossaries as authority for live state
- use
data/devices.jsonas if it were an unconditional automation capability whitelist - place automation
name,starters,condition, oractionsdirectly under top-leveldata - describe impossible state such as "light is off and brightness is 100%"
Reference Index
aqara-open-api-local/device/SKILL.md— device cache-first query and controlaqara-open-api-local/space/SKILL.md— space listing and mutationaqara-open-api-local/automation/SKILL.md— automation creation and CRUDaqara-open-api-local/docs/commands.md— CLI command catalogaqara-open-api-local/data/devices.json— device cacheaqara-open-api-local/references/examples.md— intent-based example indexaqara-open-api-local/references/automation-http-examples.md— automation HTTP lifecycle examples