Todo - Set Task Completed / Needs Action (with optional due date & description update)

This blueprint allows you to manage Todo list items in Home Assistant. It was mainly written to allow for automations to set certain tasks as done or not done.

Features:

  • Mark tasks as completed or needing action
  • Create task automatically if missing
  • Set due date (date or datetime)
  • Update task description

Works with:

  • Any Home Assistant todo.* integration (Local To-do, Google Tasks, etc.)

Use cases:

  • Automations that complete recurring tasks
  • Voice assistants marking tasks done
  • Smart reminders with deadlines

Blueprint:

blueprint:
  name: Todo - Set Task State
  description: >
    Finds a task by name in a Todo list and updates its state.
    Can mark as completed or needs action, optionally create the task
    if missing, and update due date or description.
  domain: script
  input:
    todo_entity:
      name: Todo list
      description: Select the todo list entity
      selector:
        entity:
          domain: todo

    task_name:
      name: Task name
      description: Name of the task to update
      default: Take garbage out
      selector:
        text: {}

    is_done:
      name: Mark as completed
      description: true = completed, false = needs action
      default: true
      selector:
        boolean: {}

    create_if_missing:
      name: Create if missing
      description: Create the task if it doesn't exist
      default: true
      selector:
        boolean: {}

    new_due_date:
      name: Due date (optional)
      description: >
        Format: YYYY-MM-DD or YYYY-MM-DD HH:MM:SS
      default: ""
      selector:
        text: {}

    new_description:
      name: Description (optional)
      default: ""
      selector:
        text: {}

mode: queued

sequence:
  - action: todo.get_items
    target:
      entity_id: !input todo_entity
    response_variable: tasks

  - variables:
      todo_entity: !input todo_entity
      task_name: !input task_name
      is_done: !input is_done
      create_if_missing: !input create_if_missing
      new_due_date: !input new_due_date
      new_description: !input new_description

      tasks_list: "{{ tasks[todo_entity]['items'] }}"

      uid: >
        {{
          (
            tasks_list
            | selectattr('summary', 'eq', task_name)
            | map(attribute='uid')
            | list
            | first
          )
          if (
            tasks_list
            | selectattr('summary', 'eq', task_name)
            | list
            | count > 0
          )
          else -1
        }}

  - if:
      - condition: template
        value_template: "{{ uid == -1 and create_if_missing }}"
    then:
      - action: todo.add_item
        target:
          entity_id: "{{ todo_entity }}"
        data:
          item: "{{ task_name }}"

      - action: todo.get_items
        target:
          entity_id: "{{ todo_entity }}"
        response_variable: tasks

      - variables:
          tasks_list: "{{ tasks[todo_entity]['items'] }}"
          uid: >
            {{
              (
                tasks_list
                | selectattr('summary', 'eq', task_name)
                | map(attribute='uid')
                | list
                | first
              )
              if (
                tasks_list
                | selectattr('summary', 'eq', task_name)
                | list
                | count > 0
              )
              else -1
            }}

  - variables:
      update_data: >
        {% set data = dict(
          item=uid,
          status='completed' if is_done else 'needs_action'
        ) %}

        {% if new_due_date | length > 0 %}
          {% if ':' in new_due_date %}
            {% set data = data | combine({'due_datetime': new_due_date}) %}
          {% else %}
            {% set data = data | combine({'due_date': new_due_date}) %}
          {% endif %}
        {% endif %}

        {% if new_description | length > 0 %}
          {% set data = data | combine({'description': new_description}) %}
        {% endif %}

        {{ data }}

  - if:
      - condition: template
        value_template: "{{ uid != -1 }}"
    then:
      - action: todo.update_item
        target:
          entity_id: "{{ todo_entity }}"
        data: "{{ update_data }}"

Open your Home Assistant instance and show the blueprint import dialog with a specific blueprint pre-filled.

User Interface:

1 Like

I can think of a bunch of uses for this. Thank you for sharing!

1 Like

Just a quick update: it turns out the todo.update_item action already supports using the task name directly (not just the UID).

I had assumed a UID was required when I created this, which led me to build this blueprint. But that’s not actually the case.

So for most use cases, this can be done more simply with the native action todo.update_item.

1 Like