The Automation DSL can be used to create automations that are more complex than those discussed in[DSL guide - basic automations on Android](https://developers.home.google.com/apis/android/automation/dsl/basic).

## Sequential with multiple actions

![Sequential with multiple actions](https://developers.home.google.com/static/apis/images/apis-automation-dsl-sequential-multiple.svg)

An automation can do more than one thing. For example, in place of the single`action`node, you could have multiple`action`nodes, which run in sequential order:  

    automation {
      sequential {
        starter<_>(...)
        condition {...}
        action {...}
        action {...}
        action {...}
        }
    }

## Sequential with multiple parallel actions

![Sequential with multiple parallel actions](https://developers.home.google.com/static/apis/images/apis-automation-dsl-sequential-multiple-parallel.svg)

If you place multiple`action`nodes in a`parallel`node, the actions execute concurrently.  

    automation {
      sequential {
        starter<_>(...)
        condition {...}
        parallel {
          action {...}
          action {...}
          action {...}
        }
      }
    }

If there are`action`nodes in the`sequential`node that come after the`parallel`node, they wait to execute until all the nodes within the`parallel`node have finished executing.
| **Key Point:** If you need several actions to occur in an automation, it may be preferable to place them in a`parallel`node. This is because running actions sequentially can lead to undesirable delays as each action waits for all the preceding actions to complete before starting.

## Delays

You can introduce pauses in your automations using the[`delayFor`](https://developers.home.google.com/reference/kotlin/com/google/home/automation/DelayNodeDsl#delayFor(java.time.Duration))keyword, which takes a[`java.time.Duration`](https://developer.android.com/reference/java/time/Duration)argument representing how long to pause before continuing execution. The pause duration may be as short as five seconds or as long as 24 hours.

For example, to toggle a light four times with a five-second pause between each toggle:  

    sequential {
      action(light, OnOffLightDevice) { command(OnOff.toggle()) }
      delayFor(Duration.ofSeconds(5))
      action(light, OnOffLightDevice) { command(OnOff.toggle()) }
      delayFor(Duration.ofSeconds(5))
      action(light, OnOffLightDevice) { command(OnOff.toggle()) }
      delayFor(Duration.ofSeconds(5))
      action(light, OnOffLightDevice) { command(OnOff.toggle()) }
    }

| **Warning:** `delayFor`*must* be in a`sequential`flow. If a`delayFor`is nested within a`parallel`flow at any level, it is ignored.

## Trigger suppression

Trigger suppression is a capability that allows your automation to ignore a`starter`for a specified period of time after the initial triggering event. For example, if the automation has a`starter`that's triggered by motion detection, and if you specify a trigger suppression duration of five minutes, then when the`starter`triggers, it won't trigger again for the next five minutes. This prevents the automation from rapidly triggering over and over.

To apply trigger suppression to your automation, use the[`suppressFor`](https://developers.home.google.com/reference/kotlin/com/google/home/automation/SuppressionNodeDsl#suppressFor(java.time.Duration))keyword with a[`java.time.Duration`](https://developer.android.com/reference/java/time/Duration)argument representing how long to wait before responding to subsequent triggers. The suppression duration may be as short as five seconds or as long as 24 hours.  

    automation {
      sequential {
        val starterNode = starter<_>(device, OccupancySensor, MotionDetection)
        suppressFor(Duration.ofMinutes(30))
        action(light, OnOffLightDevice) { command(OnOff.toggle()) }
    }

Note that trigger suppression affects all`starters`in an automation that precede the`suppressFor`.

## Limit the number of executions

You can limit the number of times an automation is permitted to run.

For example, you might want to set up a one-time automation that runs the vacuum while you're away from home for the day.

To do this, set the automation's[`maxExecutionCount`](https://developers.home.google.com/reference/kotlin/com/google/home/automation/AutomationBuilder#maxExecutionCount(kotlin.Int))metadata field. The following example is an automation that can only execute once:  

```kotlin
automation {
  // The automation can only be executed once.
  maxExecutionCount = 1
  // When the door lock state changes
  sequential {
    val doorLockEvent = starter<_>(doorLock, DoorLockDevice, LockOperationEvent)
    // if the door is unlocked
    condition() {
      expression = (doorLockEvent.lockOperationType equals LockOperationTypeEnum.Unlock)
    }
    // turn the light on
    action(light, DimmableLightDevice) { command(OnOff.on()) }
  }
}
```

The automation is immediately deleted once it completes execution for the last time and`maxExecutionCount`is reached. The automation's history entry remains in theGoogle Home app (GHA)**Activity** tab, including the`automation_id`.

## Set trait attributes in an action

To set the value of a trait attribute:

1. Create an`update`node within an`action`node, including the relevant trait as an argument to the`update`node:  

       action(<var translate="no">deviceReference</var>, <var translate="no">deviceType</var>) {
         update(<var translate="no">trait</var>) {

         }
       }

2. Within the`update`node, for each attribute to be modified, use a mutator function, and pass it the new value. To form the name of the mutator function:
   1. Capitalize the name of the attribute
   2. Prefix it with the word`set`.

   For example, to update an attribute called`defaultMoveRate`, you'd use a mutator function called`setDefaultMoveRate`.

Note that an`update`node can have multiple mutator functions. Here's an example where two attributes are updated:  

    action(device, Fan) {
      update(FanControl) {
        setPercentSetting(50u)
        setRockSetting(FanControlCluster.RockBitmap.rockUpDown)
      }
    }

| **Important:** Only trait attributes with an access type of`write`can be updated. Attributes with an access type of`read`cannot be updated.