Process intents

Once you have created a smart home Action and provided fulfillment, your fulfillment must process the smart home intents and return responses. You can use any programming language as long as you adhere to the request and response formats. Your fulfillment should minimize latency between the Assistant and your cloud API.

These sections describe the request and response formats for communication between the Assistant and your smart home Action's fulfillment:

With any smart home intent, you can also return error responses:

For the full list of supported device types and traits along with sample requests and responses, see:

action.devices.SYNC

This intent is triggered at user setup or when a user reconnects through the Action (to reconnect or disconnect) when necessary to resync devices in batch (for example, when new traits are added).

When this intent is triggered the Assistant sends a request to your fulfillment, which should respond with the following:

  • Required. Return all devices. Devices that are temporarily unavailable should be included, otherwise an offline device will no longer be recognized.
  • Required. Return the attributes of each device.
Request
{
    "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
    "inputs": [{
      "intent": "action.devices.SYNC"
    }]
}
Node.jsResponse
const {smarthome} = require('actions-on-google');
const app = smarthome();
// ...
app.onSync((body, headers) => {
  // TODO Get devices for user
  return {
    requestId: body.requestId,
    payload: {
      agentUserId: "1836.15267389",
      devices: [{
        id: "123",
        type: "action.devices.types.OUTLET",
        traits: [
          "action.devices.traits.OnOff"
        ],
        name: {
          defaultNames: ["My Outlet 1234"],
          name: "Night light",
          nicknames: ["wall plug"]
        },
        willReportState: false,
        roomHint: "kitchen",
        deviceInfo: {
          manufacturer: "lights-out-inc",
          model: "hs1234",
          hwVersion: "3.2",
          swVersion: "11.4"
        },
        otherDeviceIds: [{
          deviceId: "local-device-id"
        }],
        customData: {
          fooValue: 74,
          barValue: true,
          bazValue: "foo"
        }
      }, {
        id: "456",
        type: "action.devices.types.LIGHT",
        traits: [
          "action.devices.traits.OnOff",
          "action.devices.traits.Brightness",
          "action.devices.traits.ColorTemperature",
          "action.devices.traits.ColorSpectrum"
        ],
        name: {
          defaultNames: ["lights out inc. bulb A19 color hyperglow"],
          name: "lamp1",
          nicknames: ["reading lamp"]
        },
        willReportState: false,
        roomHint: "office",
        attributes: {
          temperatureMinK: 2000,
          temperatureMaxK: 6500
        },
        deviceInfo: {
          manufacturer: "lights out inc.",
          model: "hg11",
          hwVersion: "1.2",
          swVersion: "5.4"
        },
        customData: {
          fooValue: 12,
          barValue: false,
          bazValue: "bar"
        }
      }]
    }
  };
});
JSONResponse
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "agentUserId": "1836.15267389",
    "devices": [
      {
        "id": "123",
        "type": "action.devices.types.OUTLET",
        "traits": [
          "action.devices.traits.OnOff"
        ],
        "name": {
          "defaultNames": [
            "My Outlet 1234"
          ],
          "name": "Night light",
          "nicknames": [
            "wall plug"
          ]
        },
        "willReportState": false,
        "roomHint": "kitchen",
        "deviceInfo": {
          "manufacturer": "lights-out-inc",
          "model": "hs1234",
          "hwVersion": "3.2",
          "swVersion": "11.4"
        },
        "customData": {
          "fooValue": 74,
          "barValue": true,
          "bazValue": "foo"
        }
      },
      {
        "id": "456",
        "type": "action.devices.types.LIGHT",
        "traits": [
          "action.devices.traits.OnOff",
          "action.devices.traits.Brightness",
          "action.devices.traits.ColorTemperature",
          "action.devices.traits.ColorSpectrum"
        ],
        "name": {
          "defaultNames": [
            "lights out inc. bulb A19 color hyperglow"
          ],
          "name": "lamp1",
          "nicknames": [
            "reading lamp"
          ]
        },
        "willReportState": false,
        "roomHint": "office",
        "attributes": {
          "temperatureMinK": 2000,
          "temperatureMaxK": 6500
        },
        "deviceInfo": {
          "manufacturer": "lights out inc.",
          "model": "hg11",
          "hwVersion": "1.2",
          "swVersion": "5.4"
        },
        "customData": {
          "fooValue": 12,
          "barValue": false,
          "bazValue": "bar"
        }
      }
    ]
  }
}

Request format

  • requestId: String. Required. Id of request for ease of tracing
  • inputs:
    • intent: String. Required. action.devices.SYNC
    • (No payload)

Response format

  • payload:
    • errorCode: String. Optional. For systematic errors on SYNC.
    • debugString: String. Optional. Detailed error which will never be presented to users but may be logged or used during development.
    • agentUserId: String (up to 256 bytes). Required. Reflects the unique (and immutable) user ID on the agent's platform. The string is opaque to Google, so if there's an immutable form vs a mutable form on the agent side, use the immutable form (e.g. an account number rather than email).
    • devices: Array<Object>. Array of devices. Zero or more devices are returned (zero devices meaning the user has no devices, or has disconnected them all). Each device has the following properties:
      • id: String. Required. The ID of the device in the partner's cloud. This must be unique for the user and for the partner, as in cases of sharing we may use this to dedupe multiple views of the same device. It should be immutable for the device; if it changes, the Assistant will treat it as a new device.
      • type: String. Required. The hardware type of device (for example, action.devices.types.LIGHT). See the full list of device types.
      • traits: Array<String>. Required. List of traits this device supports (for example, action.devices.traits.OnOff). This defines the commands, attributes, and states that the device has. See the full list of device traits.
      • name: Object. Required. Names of this device.
        • defaultNames: Array<String>. Optional. List of names provided by the partner rather than the user, often manufacturer names, SKUs, etc.
        • name: String. Required. Primary name of the device, generally provided by the user. This is also the name the Assistant will prefer to describe the device in responses.
        • nicknames: Array<String>. Optional. Additional names provided by the user for the device.
      • willReportState: Boolean. Required. Indicates whether this device will have its states updated by the Real Time Feed. (TRUE to use the Real Time Feed for reporting state, and FALSE to use the polling model.)
      • roomHint: String. Optional. Provides the current room of the device in the user's home to simplify setup.
      • deviceInfo: Object. Optional. Contains fields describing the device for use in one-off logic if needed (e.g. 'broken firmware version X of light Y requires adjusting color', or 'security flaw requires notifying all users of firmware Z').
        • manufacturer: String. Especially useful when the partner is a hub for other devices. Google may provide a standard list of manufacturers here so that e.g. TP-Link and Smartthings both describe 'osram' the same way.
        • model: String. The model or SKU identifier of the particular device.
        • hwVersion: String. Specific version number attached to the hardware if available.
        • swVersion: String. Specific version number attached to the software/firmware, if available.
      • attributes: Object. Optional, aligned with per-trait attributes as in Attributes below. Right-hand values are string | int | boolean | number.
      • customData: Object. Optional; this is a special object defined by the partner which will be attached to future QUERY and EXECUTE requests. Partners can use this object to store additional information about the device to improve performance or routing within their cloud, such as the global region of the device. Data in this object has a few constraints:
        • No Personally Identifiable Information.
        • Data should change rarely, akin to other attributes -- so this should not contain real-time state.
        • The total object is limited to 512 bytes per device.

action.devices.QUERY

This intent queries for the current states of devices. It is used for queries where truly real-time accuracy is required (for example, the status of a door lock). Only states are returned when action.devices.QUERY is triggered. To update the properties or traits or other persistent elements of the device, action.devices.SYNC is used.

Request
{
    "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
    "inputs": [{
      "intent": "action.devices.QUERY",
      "payload": {
        "devices": [{
          "id": "123",
          "customData": {
            "fooValue": 74,
            "barValue": true,
            "bazValue": "foo"
          }
        }, {
          "id": "456",
          "customData": {
            "fooValue": 12,
            "barValue": false,
            "bazValue": "bar"
          }
        }]
      }
    }]
}
Node.jsResponse
const {smarthome} = require('actions-on-google');
const app = smarthome();
// ...
app.onQuery((body, headers) => {
  // TODO Get device state
  return {
    requestId: body.requestId,
    payload: {
      devices: {
        123: {
          on: true,
          online: true
        },
        456: {
          on: true,
          online: true,
          brightness: 80,
          color: {
            name: "cerulean",
            spectrumRGB: 31655
          }
        }
      }
    }
  };
});
JSONResponse
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "devices": {
      "123": {
        "on": true,
        "online": true
      },
      "456": {
        "on": true,
        "online": true,
        "brightness": 80,
        "color": {
          "name": "cerulean",
          "spectrumRGB": 31655
        }
      }
    }
  }
}

Request format

  • requestId: String. Required. Id of request for ease of tracing
  • inputs:
    • intent: String. Required. action.devices.QUERY
    • payload: Object. Required
      • devices: Array<Object>. Required.
        • id: Required. Partner ID to query, as per the id provided in SYNC.
        • customData: Optional. If the opaque customData object is provided in SYNC, it's sent here.

Response format

  • payload:
    • errorCode: String. Optional. An error code for the entire transaction -- for auth failures and partner system unavailability. For individual device errors use the errorCode within the device object.
    • debugString: String. Optional. Detailed error which will never be presented to users but may be logged or used during development.
    • devices: Object. Map of devices. Each property has the following name and value:
      • id: Object. Required. Maps partner device ID to object of state properties, as defined in States section below.
        • online: Boolean. Required. Indicates if the device is online (that is, reachable) or not.
      • errorCode: String. Optional. Expanding ERROR state if needed from the preset error codes, which will map to the errors presented to users.
      • debugString: String. Optional. Detailed error which will never be presented to users but may be logged or used during development.

action.devices.EXECUTE

This intent is triggered to provide commands to execute on smart home devices. The new state should be provided in the response if available. One triggered intent can target multiple devices, with multiple commands. For example, a triggered intent may set both brightness and color on a set of lights or may set multiple lights each to a different color.

Request
{
    "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
    "inputs": [{
      "intent": "action.devices.EXECUTE",
      "payload": {
        "commands": [{
          "devices": [{
            "id": "123",
            "customData": {
              "fooValue": 74,
              "barValue": true,
              "bazValue": "sheepdip"
            }
          }, {
            "id": "456",
            "customData": {
              "fooValue": 36,
              "barValue": false,
              "bazValue": "moarsheep"
            }
          }],
          "execution": [{
            "command": "action.devices.commands.OnOff",
            "params": {
              "on": true
            }
          }]
        }]
      }
    }]
}
Node.jsResponse
const {smarthome} = require('actions-on-google');
const app = smarthome();
// ...
app.onExecute((body, headers) => {
  // TODO Send command to device
  return {
    requestId: body.requestId,
    payload: {
      commands: [{
        ids: ["123"],
        status: "SUCCESS",
        states: {
          on: true,
          online: true
        }
      }, {
        ids: ["456"],
        status: "ERROR",
        errorCode: "deviceTurnedOff"
      }]
    }
  };
});
JSONResponse
{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "commands": [
      {
        "ids": [
          "123"
        ],
        "status": "SUCCESS",
        "states": {
          "on": true,
          "online": true
        }
      },
      {
        "ids": [
          "456"
        ],
        "status": "ERROR",
        "errorCode": "deviceTurnedOff"
      }
    ]
  }
}

Request format

  • requestId: String. Required. Id of request for ease of tracing
  • inputs
    • intent: String. Required. action.devices.EXECUTE
    • payload:
      • commands: Array<Object>. Required. Each object contains one or more devices to target with the attached commands.
        • devices: Array<Object>code>. Required.
          • id: Required. Partner ID to query, as per the id provided in SYNC.
          • customData: Optional. If the opaque customData object is provided in SYNC, it's sent here.
        • execution: Array<Object>. Required. The ordered list of execution commands for the attached ids.
          • command: String. Required. The command (see below) to execute, with (usually) accompanying parameters.
          • params: Map<string, Object> Optional, but aligned with the parameters for each command (below).
            • <name>: String. Required. The name of the param.
            • <value>: String | Number | Boolean

Response format

  • payload:
    • errorCode: String. Optional. An error code for the entire transaction -- for auth failures and partner system unavailability. For individual device errors use the errorCode within the device object.
    • debugString: String. Optional. Detailed error which will never be presented to users but may be logged or used during development.
    • commands: Array<Object>. Required. Each object contains one or more devices with response details. N.B. These may not be grouped the same way as in the request. For example, the request might turn 7 lights on, with 3 lights succeeding and 4 failing, thus with two groups in the response.
      • ids: Array<String>. Required. Partner device IDs of the response
      • status: String. Required. Current status types:
        • SUCCESS - confirmed that the command(s) has/have succeeded.
        • PENDING - commands are enqueued but expected to succeed.
        • OFFLINE - target devices(s) in offline state or unreachable.
        • ERROR - unable to perform the commands.
      • errorCode: String. Optional. Expanding ERROR state if needed from the preset error codes, which will map to the errors presented to users.
      • debugString: String. Optional. Detailed error which will never be presented to users but may be logged or used during development.
      • states: Object. Optional, but aligned with per-trait states as in Attributes below. These are the states after execution, if available.
        • online: Boolean. Optional. Indicates if the device is online (that is, reachable) or not.
        • name:value String. Required. Name of the state followed by its value, which can be a String, Number, or Boolean.

action.devices.DISCONNECT

This intent is triggered to inform you when a user has unlinked the app account from the Google Assistant. After receiving a DISCONNECT intent, you should not report state for this user's devices.

Request
{
    "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
    "inputs": [{
      "intent": "action.devices.DISCONNECT",
    }]
}
Node.jsResponse
const {smarthome} = require('actions-on-google');
const app = smarthome();
// ...
app.onDisconnect((body, headers) => {
  // TODO Disconnect user account from Google Assistant
  // You can return an empty body
  return {};
});
JSONResponse
{}

Request format

  • requestId: String. Required. Id of request for ease of tracing
  • inputs
    • intent: String. Required. action.devices.DISCONNECT

Response format

  • 200 Ok with an empty JSON body is all that is needed.

Error responses

These are some error codes that can be returned with your responses.

Example of an error response:

{
  "requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
  "payload": {
    "errorCode": "notSupported"
  }
}
  • authExpired: Credentials have expired.
  • authFailure: General failure to authenticate.
  • deviceOffline: The target is unreachable.
  • timeout: Internal timeout.
  • deviceTurnedOff: The device is known to be turned hard off (if distinguishable from unreachable).
  • deviceNotFound: The device doesn't exist on the partner's side. This normally indicates a failure in data synchronization or a race condition.
  • valueOutOfRange: The range in parameters is out of bounds.
  • notSupported: The command or its parameters are unsupported (this should generally not happen, as traits and business logic should prevent it).
  • protocolError: Failure in processing the request.
  • unknownError: Everything else, although anything that throws this should be replaced with a real error code.

See the full list of errors and exceptions.