---
name: build-automation
description: Build a new Apilio automation from a plain-language description ("turn the heating down when nobody is home", "notify me at 7am on weekdays"). Use when the user wants to create, extend, or restructure a logicblock.
---

# Building an Apilio automation

An automation is a **logicblock**: a set of conditions combined by boolean logic, plus
actions that run when the result is true (`positive`) or false (`negative`).

Conditions and the logicblock are created separately, and conditions must exist first —
`create_logicblock` links them by UUID.

## Workflow

1. **Discover what exists.** `list_devices` (optionally `service:`), then
   `get_device_attributes` on the device you need — it returns the attribute IDs that
   conditions require and the `available_actions` that actions accept. Use
   `list_variables` for user-defined variables.

2. **Restate the automation as events + guards before creating anything.** Present the plan
   and wait for approval.

3. **Create the conditions.** `create_device_condition` for device state,
   `create_time_condition` for schedules and time windows. Keep each returned UUID.

4. **Create the logicblock.** `create_logicblock`, passing the UUIDs in the parameter
   matching each condition's type: `condition_uuids` (variable conditions),
   `timecondition_uuids`, `tuyacondition_uuids` (device conditions).

5. **Add the actions.** `add_tado_action`, `add_ewelink_action`, `add_apilio_action`,
   `add_alexa_action`, `add_ifttt_action`, or `add_action_to_logicblock` for an email
   notification. Each takes `action_group: "positive" | "negative"`.

6. **Read it back** with `get_logicblock` and summarise it for the user.

## Decisions that matter

**Mark every condition that is an event, and only those.** `triggering: true` means "when
this condition's *result* flips, re-evaluate the logicblock". Conditions that merely qualify
when the automation may act — guards — stay `triggering: false`.

- No triggering condition → the automation never fires on its own.
- A guard marked triggering → the automation fires on changes the user didn't ask about.
- An event left non-triggering → that event is silently missed.

For "turn on the fan when the temperature goes above 25°C but only in the evening", the
temperature condition is the event and the evening time frame is a guard. But for "notify me
when motion is detected or the door opens", **both** conditions are events and both must
trigger — otherwise one of them never fires the automation.

(`trigger_on_content_update` is a separate, noisier setting: it re-evaluates on every value
update rather than only when the condition's result changes.)

Time *events* (`timeevent_absolute`, `timeevent_at_sunrise`, `timeevent_at_sunset`) are
always triggering — that is what they are for. Time *frames* (`timeframe_*`) are usually
pre-conditions.

**Prefer one logicblock over several.** Combine conditions with
`condition_logic: "complex"` and a `condition_expression` using AND, OR, XOR, NOR, NAND —
e.g. `OR(motion_detected,AND(door_open,evening_hours))`, where the names are the condition
names. Nested expressions are a premium feature; the response reports
`complex_conditions_available`. Fall back to `condition_logic: "and"` when it isn't
available.

**Use the negative branch instead of an inverse logicblock.** "Heating on when home, off
when away" is one logicblock with a positive and a negative action, not two logicblocks.

## Limits and gaps

- Max 15 conditions and 20 actions per logicblock; condition and logicblock names are max
  50 characters and unique per user.
- Tuya, Philips Hue and HTTP actions cannot be created over MCP. Add an email notification
  action as a placeholder and tell the user to swap it in the Apilio web app.
- Variable conditions cannot be created over MCP either — only linked by UUID if they
  already exist.
