Examples / Bedtime house check

Bedtime house check

At 10:30 every night Murmurator reads every entity in Home Assistant through your tailnet, picks out the lights left on, the doors left unlocked and the windows left open, has your model decide what to switch off and lock, does it, and sends a one-line report to your phone. Home Assistant never has to be reachable from the internet.

Home AssistantTailscaleJavaScriptYour AI models

What you tell the assistant

Every night at 10:30, check Home Assistant for lights left on, unlocked doors and open windows. Turn off the lights except the porch, lock the doors, and send a short summary to my phone, saying which windows are still open.

Why it works

  • Home Assistant is reached at http://homeassistant:8123 through a tailscale connection, so nothing in the house is opened to the internet.
  • A JavaScript step narrows hundreds of entities to the few that matter before the model sees them, which keeps each night's run cheap.
  • The model only chooses from the entities it was shown, and the actions run only when there is something to switch off or lock.
Sign in to build this

What it builds

Trigger
Schedule
30 22 * * * · America/Toronto
tool
Read the house
home.list_states
javascript
Find loose ends
→ lights_on, unlocked, open
llm
Decide what to do
fast · structured
tool
Turn off lights
home.call_service
if size(decide.output.data.lights_off) > 0
tool
Lock the doors
home.call_service
if size(decide.output.data.lock) > 0
tool
Tell my phone
home.call_service
View the definition
trigger:
  kind: schedule
  cron: "30 22 * * *"
  timezone: America/Toronto
steps:
  - key: states
    name: Read the house
    kind: tool
    tool: home.list_states
  - key: loose_ends
    name: Find loose ends
    kind: javascript
    inputs: { states: "{{ steps.states.output }}" }
    outputs: { lights_on: array, unlocked: array, open: array }
    code: |
      function main({ states }) {
        const pick = (domain, state) => states
          .filter(s => s.entity_id.startsWith(domain + ".") && s.state === state)
          .map(s => ({ entity_id: s.entity_id, name: s.name }))
        return {
          lights_on: pick("light", "on"),
          unlocked: pick("lock", "unlocked"),
          open: pick("binary_sensor", "on").filter(s => /window|door/i.test(s.entity_id))
        }
      }
  - key: decide
    name: Decide what to do
    kind: llm
    model: fast
    system: You close up a family home for the night. Choose only from the entities you are given, and keep the phone message to one or two short sentences.
    prompt: |
      Lights on: {{ steps.loose_ends.output.lights_on }}
      Unlocked locks: {{ steps.loose_ends.output.unlocked }}
      Open doors and windows: {{ steps.loose_ends.output.open }}
      Turn off every light except the porch light. Lock every lock, unless the door it belongs to is open: then leave it and say so.
    schema:
      type: object
      properties:
        lights_off: { type: array, items: { type: string } }
        lock: { type: array, items: { type: string } }
        message: { type: string }
      required: [lights_off, lock, message]
  - key: lights
    name: Turn off lights
    kind: tool
    if: size(steps.decide.output.data.lights_off) > 0
    tool: home.call_service
    args:
      domain: light
      service: turn_off
      entity_id: "{{ steps.decide.output.data.lights_off }}"
  - key: locks
    name: Lock the doors
    kind: tool
    if: size(steps.decide.output.data.lock) > 0
    tool: home.call_service
    args:
      domain: lock
      service: lock
      entity_id: "{{ steps.decide.output.data.lock }}"
  - key: report
    name: Tell my phone
    kind: tool
    tool: home.call_service
    args:
      domain: notify
      service: mobile_app_pixel
      data:
        title: House closed up for the night
        message: "{{ steps.decide.output.data.message }}"

A sample run

What each step produces

Read the house tool

succeeded
Calling home.list_states
[
  {
    "entity_id": "light.kitchen",
    "state": "on",
    "name": "Kitchen"
  },
  {
    "entity_id": "light.living_room",
    "state": "on",
    "name": "Living room"
  },
  {
    "entity_id": "light.porch",
    "state": "on",
    "name": "Porch"
  },
  {
    "entity_id": "light.bedroom",
    "state": "off",
    "name": "Bedroom"
  },
  {
    "entity_id": "lock.front_door",
    "state": "unlocked",
    "name": "Front door"
  },
  {
    "entity_id": "lock.back_door",
    "state": "locked",
    "name": "Back door"
  },
  {
    "entity_id": "binary_sensor.office_window",
    "state": "on",
    "name": "Office window"
  },
  {
    "entity_id": "binary_sensor.front_door",
    "state": "off",
    "name": "Front door contact"
  },
  {
    "entity_id": "sensor.outdoor_temperature",
    "state": "4.5",
    "name": "Outdoor temperature",
    "unit": "°C"
  }
]

Find loose ends javascript

succeeded
{
  "lights_on": [
    {
      "entity_id": "light.kitchen",
      "name": "Kitchen"
    },
    {
      "entity_id": "light.living_room",
      "name": "Living room"
    },
    {
      "entity_id": "light.porch",
      "name": "Porch"
    }
  ],
  "unlocked": [
    {
      "entity_id": "lock.front_door",
      "name": "Front door"
    }
  ],
  "open": [
    {
      "entity_id": "binary_sensor.office_window",
      "name": "Office window"
    }
  ]
}

Decide what to do llm

succeeded
Using model fast (GLM-5.3 Air, Murmurator AI)
{
  "text": "",
  "data": {
    "lights_off": [
      "light.kitchen",
      "light.living_room"
    ],
    "lock": [
      "lock.front_door"
    ],
    "message": "Kitchen and living room lights off, front door locked, porch light left on. The office window is still open."
  }
}

Turn off lights tool

succeeded
Calling home.call_service
[
  {
    "entity_id": "light.kitchen",
    "state": "off"
  },
  {
    "entity_id": "light.living_room",
    "state": "off"
  }
]

Lock the doors tool

succeeded
Calling home.call_service
[
  {
    "entity_id": "lock.front_door",
    "state": "locked"
  }
]

Tell my phone tool

succeeded
Calling home.call_service
[]

Trigger payload

{
  "scheduled_at": "2026-10-31T02:30:00Z"
}

Turn one person's AI process into the company's.

Murmurator is invite-only. Already invited? Sign in and build something real.