Skip to content

Instantly share code, notes, and snippets.

@allenporter
Last active January 8, 2025 20:52
Show Gist options
  • Save allenporter/e70d9eb090c7dbdd593cf526e07b4abe to your computer and use it in GitHub Desktop.
Save allenporter/e70d9eb090c7dbdd593cf526e07b4abe to your computer and use it in GitHub Desktop.
Home Assistant Blueprint: Conversation agent Agenda Notification
---
blueprint:
name: Conversation agent Agenda Notification
description:
Conversation agent generates a notification based on the upcoming calendar
agenda, location, and weather information.
domain: automation
input:
notify_time:
name: Notification time
description: Time the automation is triggered to send the notification.
selector:
time: {}
default: 07:00:00
notify_service:
name: Notify service name
description:
The name of the notify service where the notification should be
sent.
selector:
text: {}
default: notify.notify
notify_target:
name: Notify target
description: The target of the notify service.
selector:
text: {}
default:
calendar_entity:
name: Calendar
description: The calendar entity to use for finding upcoming calendar events.
selector:
entity:
multiple: false
filter:
- domain:
- calendar
calendar_duration:
name: Calendar Event duration
description: How many hours ahead to look for upcoming calendar events.
selector:
duration:
default:
hours: 18
weather_entity:
name: Weather Entity
description: The weather entity to use for upcoming weather forecast.
selector:
entity:
multiple: false
filter:
- domain:
- weather
zone_entity:
name: Home Zone Entity
description:
The zone entity to use to determine approximate location for understanding
typical weather.
selector:
entity:
multiple: false
filter:
- domain:
- zone
conversation_agent:
name: Conversation Agent
selector:
conversation_agent:
prompt:
name: Conversation Agent Prompt
selector:
text:
multiline: true
type: text
default: |-
Please generate text for a notification that will be sent to the users
smartphone with helpful information.
You are a helpful personal agent that generates text for the user:
- Your answers are helpful, friendly, warm, insightful.
- Your answers are not technical, and do not include Home Assistant internal details such as entities in responses.
- Your messages help the user prepare for their day, for example:
- Making note of unusual weather for the location and time of year (but not mundane details like "0% chance of precipitation")
- How much time remaining until their first meeting
- Anything that may be special or unique, such as celebrating a birthday
trigger:
platform: time
at: !input notify_time
action:
- variables:
weather_entity: !input weather_entity
calendar_entity: !input calendar_entity
zone_entity: !input zone_entity
calendar_duration: !input calendar_duration
prompt: !input prompt
- alias: Fetch Weather Forecast
service: weather.get_forecasts
data:
type: hourly
target:
entity_id:
- "{{ weather_entity }}"
response_variable: daily_forecast
- variables:
forecast_entity: "{{ daily_forecast[weather_entity] }}"
forecast: "{{ forecast_entity.forecast[0] }}"
- alias: Fetch Calendar Agenda
service: calendar.get_events
data:
duration: !input calendar_duration
target:
entity_id: !input calendar_entity
response_variable: events_response
- alias: "Conversation Agent Notification Text"
service: conversation.process
data:
text: |-
Time: {{ now().strftime("%A %B %d %H:%M %p") }}
{%- if weather_entity is defined %}
{%- set temperature_unit = state_attr(weather_entity, 'temperature_unit') -%}
Forecast: {{ forecast.condition }} ({{ forecast.temperature }}{{ temperature_unit }}, {{ forecast.precipitation }}% precipitation)
{%- endif %}
Calendar "{{ state_attr(calendar_entity, 'friendly_name') }}" events for the next {{ calendar_duration.hours }}:
{%- set agenda = (events_response | items | first)[1] %}
{%- if agenda.events %}
{%- for event in agenda.events %}
- Summary: {{ event.summary }}
Start-End: {% if event.start is defined %}{{ event.start }} to {{ event.end }}{% else %}All Day{% endif %}
{%- if event.description is defined %}
Description: {{ event.description }}
{% endif -%}
{%- if event.location is defined %}
Location: {{ event.location }}
{% endif -%}
{%- endfor %}
{%- else %}
- No upcoming events.
{%- endif %}
{{ prompt }}
agent_id: !input conversation_agent
response_variable: agent
- alias: "Send notification"
service: !input notify_service
data:
target: !input notify_target
title: "{{ now().strftime('%A') }} Agenda"
message: "{{ agent.response.speech.plain.speech }}"
@purpleturtle1988
Copy link

That works wonderfully! Thank you for your quick reply and the revised blueprint! Do you happen to know why, despite the time zone being configured correctly in Home Assistant, it always shows one hour off? So instead of 12:00 - 11:00. My time zone is Central European Time Zone (CET), I've already written the prompt that way, but it still doesn't work :-D.

@Progaros
Copy link

Progaros commented Feb 17, 2024

Time {{ now() }} was always correct_time +1 (2024-02-17 16:16:00.283692+01:00)
{{ now().time().isoformat('minutes') }} seems to work (16:16)
you can test it here: https://{{yourHA.instance}}/developer-tools/template
Glad to help :)

@Anto79-ops
Copy link

looks like this will break on 2024.4 due to the depracation of to get weather forecasts:

{%- set forecast = state_attr(weather_entity, 'forecast')[0] %}

the line above wont work

@chlaa
Copy link

chlaa commented Apr 5, 2024

looks like this will break on 2024.4 due to the depracation of to get weather forecasts:

{%- set forecast = state_attr(weather_entity, 'forecast')[0] %}

the line above wont work

For those who want to replace forecast with weather.get_forecasts the following can to be added to the blueprint:
- alias: Get Weather Forecast
service: weather.get_forecasts
data:
type: daily
target:
entity_id: !input weather_entity
response_variable: weekly_weather_forecast

and the prompt text modified to include the following to take todays forecast from the response:
{%- if weather_entity is defined %}
{%- set temperature_unit = state_attr(weather_entity, 'temperature_unit') -%}
{%- set todays_forecast = weekly_weather_forecast[weather_entity]['forecast'][0] %}
Weather: {{ todays_forecast.condition }} ({{ todays_forecast.temperature }}{{ temperature_unit }}, {{ todays_forecast.precipitation }}% precipitation)
{%- endif %}

@allenporter
Copy link
Author

allenporter commented Apr 6, 2024

I updated with the current version I am using.

@Minius90
Copy link

I tried different calendars and weather entities but everytime I execute the automation it stops, showing the following error: Error rendering data template: UndefinedError: None has no element 0
Any idea how I could solve this?

@allenporter
Copy link
Author

I tried different calendars and weather entities but everytime I execute the automation it stops, showing the following error: Error rendering data template: UndefinedError: None has no element 0 Any idea how I could solve this?

Give another try. I may have had a stale version here without the weather updates.

@Minius90
Copy link

I tried different calendars and weather entities but everytime I execute the automation it stops, showing the following error: Error rendering data template: UndefinedError: None has no element 0 Any idea how I could solve this?

Give another try. I may have had a stale version here without the weather updates.

Perfect, thank you very much! works like a charm now

@Dreadmond
Copy link

Thank you for reviewing the weather entity issue - much appreciated! Would it be possible to have an option for multiple calenders?

@Progaros
Copy link

Thank you for reviewing the weather entity issue - much appreciated! Would it be possible to have an option for multiple calenders?

I added some features like multiple calendars:
https://gist.github.com/allenporter/e70d9eb090c7dbdd593cf526e07b4abe?permalink_comment_id=4796049#gistcomment-4796049

@Dreadmond
Copy link

This is perfect, thank you for sharing!

@Anto79-ops
Copy link

Hello @Progaros thanks for shaing your multi-calandar and and todo-list blueprint. I'm using your version but had a question: is there a way to avoivd messages like this?

      * Your "Anto's list" tasks for the day include [list specific tasks here].

      * Your "General to-do" tasks for the day are [list specific tasks here].

      * Your "Work to-do" tasks for the day are [list specific tasks here].

I'm not sure if its because I don't have anything on the to-do list. Maybe its and if-then could be added so that it does not read to the to-do list if its empty?

thanks

really cool blueprint! i added multiple calendars, tasks, output language & user name:

blueprint:
  name: Daily Conversation Agent Agenda Notification
  description: |
    Conversation agent generates a personalized notification based on the
    upcoming calendar agenda, tasks, birthday reminders, location, and weather information in your language.
  domain: automation
  input:
    language:
      name: Language
      description: Language of Assistant Response
      selector:
        language:
      default: "en"
    user:
      name: User
      description: User who is being addressed
      selector:
        entity:
          multiple: false
          filter:
            domain:
              - person
    notify_time:
      name: Notification time
      description: Time the automation is triggered to send the notification.
      selector:
        time: {}
      default: 07:00:00
    notify_service:
      name: Notify service name
      description: The name of the notify service where the notification should be sent.
      selector:
        text: {}
      default: notify.notify
    notify_target:
      name: Notify target
      description: The target of the notify service.
      selector:
        text: {}
      default:
    task_entities:
      name: Tasks
      description: The tasks entities to use for finding upcoming todos.
      selector:
        entity:
          multiple: true
          filter:
            domain:
              - todo
    calendar_entities:
      name: Calendar
      description: The calendar entities to use for finding upcoming calendar events.
      selector:
        entity:
          multiple: true
          filter:
            domain:
              - calendar
    calendar_duration:
      name: Calendar Event duration
      description: How many hours ahead to look for upcoming calendar events.
      selector:
        duration:
      default:
        hours: 18
    birthday_calendar:
      name: Birthday Calendar
      description: The calendar entity to use for finding upcoming birthdays.
      selector:
        entity:
          multiple: false
          filter:
            domain:
              - calendar
    birthday_duration:
      name: Birthday Reminder duration
      description: How many days ahead to look for upcoming birthdays.
      selector:
        duration:
          enable_day: true
      default:
        days: 7
    weather_entity:
      name: Weather Entity
      description: The weather entity to use for upcoming weather forecast.
      selector:
        entity:
          multiple: false
          filter:
            domain:
              - weather
    zone_entity:
      name: Home Zone Entity
      description: The zone entity to use to determine approximate location for understanding typical weather.
      selector:
        entity:
          multiple: false
          filter:
            domain:
              - zone
    conversation_agent:
      name: Conversation Agent
      selector:
        conversation_agent:
    user_prompt_task:
      name: Conversation Agent Task
      selector:
        text:
          multiline: true
          type: text
      default: |-
        Please generate a short text (~100 words, no newlines) for a notification for an android smartphone with helpful information.

trigger:
  platform: time
  at: !input notify_time

action:
  - variables:
      language: !input language
      user: !input user
      weather_entity: !input weather_entity
      task_entities: !input task_entities
      calendar_entities: !input calendar_entities
      zone_entity: !input zone_entity
      calendar_duration: !input calendar_duration
      birthday_calendar: !input birthday_calendar
      birthday_duration: !input birthday_duration
      user_prompt_task: !input user_prompt_task
  - alias: Fetch Tasks
    service: todo.get_items
    data:
      status:
        - needs_action
    target:
      entity_id: !input task_entities
    response_variable: tasks_responses
  - alias: Fetch Calendar Agenda
    service: calendar.get_events
    data:
      duration: !input calendar_duration
    target:
      entity_id: !input calendar_entities
    response_variable: events_responses
  - alias: Fetch Birthday Calendar
    service: calendar.get_events
    data:
      duration: !input birthday_duration
    target:
      entity_id: !input birthday_calendar
    response_variable: birthday_responses
  - alias: Get Weather Forecast
    service: weather.get_forecasts
    data:
      type: daily
    target:
      entity_id: !input weather_entity
    response_variable: weekly_weather_forecast
  - alias: "Prepare Prompt"
    variables:
      prompt: |-


        # You are a helpful personal agent that generates notifications for the user:

        - You should respond in the RFC 5646 language: "{{language}}"
        - Your answers are helpful, friendly, warm, insightful.
        - Your answers are not technical, and do not include Home Assistant internal details such as entities in responses.
        - Your messages help the user prepare for their day, for example:
        - Making note of unusual weather for the location and time of year (but not mundane details like "0% chance of precipitation"). 
        - Do not tell the user his location or the current time.
        - How much time remaining until their first meeting
        - Anything that may be special or unique, such as celebrating a birthday (but not that there are no birthdays)

        # Information to include in the notification:

        Name of User: {{ state_attr(user, "friendly_name") }}

        Time: {{ now().time().isoformat('minutes') }}

        {%- if zone_entity is defined %}
        Latitude: {{ state_attr(zone_entity, 'latitude') | round(1) }}
        Longitude: {{ state_attr(zone_entity, 'longitude') | round(1) }}
        {% endif %}

        {%- if weather_entity is defined %}
        {%- set temperature_unit = state_attr(weather_entity, 'temperature_unit') -%}
        {%- set todays_forecast = weekly_weather_forecast[weather_entity]['forecast'][0] %}
        Weather: {{ todays_forecast.condition }} ({{ todays_forecast.temperature }}{{ temperature_unit }}, {{ todays_forecast.precipitation }}% precipitation)
        {%- endif %}

        # Tasks Lists:
        {%- for task_entity in task_entities %}
          Upcoming tasks for today on list "{{ state_attr(task_entity, 'friendly_name') }}":
          {%- set tasks = tasks_responses[task_entities[loop.index0]] %}
          {%- for task in tasks['items'] %}
          {%- if 'due' in task and now().date() == as_datetime(task.due, "2222-11-11").date() %}
          - {{task['summary']}}
          {%- endif %}
          {%- endfor %}
        {%- endfor %}

        # Calendar Events:
        {%- for calendar_entity in calendar_entities %}
          Calendar "{{ state_attr(calendar_entity, 'friendly_name') }}" events for the next {{ calendar_duration.hours }} hours:
          {%- set agenda = events_responses[calendar_entities[loop.index0]] %}
          {%- if "events" in agenda and agenda.events %}
            {%- for event in agenda.events %}
            - Summary: {{ event.summary }}
              Start-End: {% if event.start is defined %}{{ event.start }} to {{ event.end }}{% else %}All Day{% endif %}
              {%- if event.descripton is defined %}
              Descripton: {{ event.descripton }}
              {% endif -%}
              {%- if event.location is defined %}
                Location: {{ event.location }}
              {% endif -%}
            {%- endfor %}
          {%- else %}
            - No upcoming events.
          {%- endif %}
        {%- endfor %}

        # Upcoming birthdays:
        {%- set birthdays = birthday_responses[birthday_calendar] %}
        {%- if "events" in birthdays and birthdays.events %}
          {%- for event in birthdays.events %}
          - Birthday Reminder: {{ event.summary }} on {{ event.start }}
          {%- endfor %}
        {%- else %}
          - No upcoming birthdays.
        {%- endif %}

        # Task:

        {{ user_prompt_task }}
  - alias: "Conversation Agent Notification Text"
    service: conversation.process
    data:
      text: "{{ prompt }}"
      agent_id: !input conversation_agent
    response_variable: agent
  - alias: "Send notification"
    service: !input notify_service
    data:
      target: !input notify_target
      title: "{{ now().strftime('%A') }} Agenda"
      message: "{{ agent.response.speech.plain.speech }}"

updated for HA 2024.4 - thanks @chlaa

added tasks

@Progaros
Copy link

Should be improved here @Anto79-ops :)

Let me know if works for you, otherwise I'll use your if-then solution

@Anto79-ops
Copy link

Anto79-ops commented May 28, 2024

thanks! I ended up using this for the task generation. This defines those with no due date, and with a due date, and no task and for each task list:

        # Tasks Lists:
        {%- for task_entity in task_entities %}
          Upcoming tasks for today on list "{{ state_attr(task_entity, 'friendly_name') }}":
          {%- for task in tasks_responses[task_entity]['items'] | selectattr('due', 'defined') | selectattr('due', 'eq', now().date() | string) | map(attribute='summary') | list or ['No Tasks'] %}
          - {{ task }}
          {%- endfor %}
          Upcoming tasks with no due date:
          {%- for task in tasks_responses[task_entity]['items'] | selectattr('due', 'undefined') | map(attribute='summary') | list or ['No Tasks'] %}
          - {{ task }}
          {%- endfor %}
        {%- endfor %}

and added this to the prompt

Do not mention tasks if No Tasks are listed.

@Christian197809
Copy link

Christian197809 commented Oct 1, 2024

Hi guys, hope someone can help me. I am basically not new to HA and did already do a lot of things, but I am totally lost with the notify service. I always do end up with the error "Action notify.tts_buero not found".
This is how I did setup the notify service in configuration.yaml:

`notify:

  • platform: tts
    name: tts_buero
    entity_id: tts.cloud_say
    media_player: media_player.buero`

Anyone can help, sure it is just a small thing.

thanks

@Progaros
Copy link

Progaros commented Oct 1, 2024

@abeclinger
Copy link

abeclinger commented Nov 23, 2024

This is a such a great blue print, thanks!

I'm struggling to get results for calendar events to show up in local time. I'm using the blueprint as is. I can see in the logs that the events are returned in UTC. Then they show up in the message like that as well.

I'm not sure if this is the correct place to post this but I can't find a solution by searching and ChatGPT isn't able to figure this one out although I spent a lot of time trying...

I can see here in the logs that HA has the correct date and time (at the top) and these events show up in my calendar with local time as well... Has anyone else had this problem or have any ideas for a solution?

image

@allenporter
Copy link
Author

There is a new way I do this now with this blueprint:
https://github.com/allenporter/home-assistant-config/blob/main/config/blueprints/automation/allenporter/notify_conversation.yaml

which instead of putting everything in the template up front uses the new tool calling feature to be able to call these intent scripts that get the weather or get todays agenda. This is nice because you can also just use these with the conversations when using voice or chat outside of this notification:

Here are the intent scripts: https://github.com/allenporter/home-assistant-config/tree/main/config/intent_scripts with the weather forecast and today's agenda.

@abeclinger
Copy link

Thanks Allen. Do I add these intent scripts directly to my configuration.yaml? I'm unfamiliar.

@allenporter
Copy link
Author

Check out https://www.home-assistant.io/integrations/intent_script/ for an example.

Don't worry about the fact that these are separate files -- I have these as standalone files in github where i write unit tests against them and manually keep them in sync between git and my home assistant config when i update something.

@abeclinger
Copy link

abeclinger commented Nov 23, 2024

Thanks Allen. I'm sure I'm missing something but I'm not sure what because I don't follow the instructions.

I've added these entries to my confirguration.yaml and tried the new blueprint and I'm not getting any reference to my calendar or the weather in the response from the blueprint. The blueprint works (even without the entries in configuration.yaml) so it's hard to say what's going wrong.

Like I said, about all I've done was add these 2 entries to my configuration.yaml with minor adjustments for my calendar and weather entities. Then I rebooted HA. Then I tried the blueprint. Maybe there's more to it or maybe there's a way to test this the intent script seperately. Maybe I'll look at it again tomorrow.

Thanks for all the help.

@allenporter
Copy link
Author

allenporter commented Nov 24, 2024

Maybe try getting the example intent script https://www.home-assistant.io/integrations/intent_script/ working first. Add that then ask the the LLM to get the temperature (make sure you don't have temperature entities exposed).

@abeclinger
Copy link

abeclinger commented Nov 24, 2024

Thanks Allen. I'm getting closer, maybe.

I did get the agenda example to work with a request in developer tools. I can see why you think this is so exciting!

It seems I needed to add a conversation section to my configuration.yaml with intents

conversation:
intents:
GetTodaysAgenda:
- "What's on my agenda?"
- "Do I have any events today?"
- "Tell me today's schedule."

The request also works fine in "Assist" if I'm using the default "Home Assistant" option. However, when I change to ChatGPT it doesn't have access. That's what I'm hoping to use to generate the message.

I don't see any settings in the assistants setup that could be related to this. I don't think it's related to exposed entities because those are all the same anyway (unless it's google assistant).

Any thoughts?

image

@allenporter
Copy link
Author

allenporter commented Nov 24, 2024

You may need to enable the "assist API" in the conversation agents integration settings? This gives the LLM access to control the home though. E g. If you expose lights, it can control lights.

@abeclinger
Copy link

abeclinger commented Nov 24, 2024

Thanks my friend :) It's so coooool! AND seems to be working for me now. I wasn't 100% on the weather at first but then I changed it to another entity and took a closer look at the trace and it's clearly working as it should I think :) thanks again :)

You can see these iterations in the trace log from the blueprint

Iteration 1
Executed: November 24, 2024 at 2:02:38 PM
Result:
params:
domain: weather
service: get_forecasts
service_data:
type: hourly
entity_id:
- weather.pirateweather_pikespeak
target:
entity_id:
- weather.pirateweather_pikespeak
running_script: false
0
Iteration 2
Executed: November 24, 2024 at 2:02:38 PM
Result:
params:
domain: calendar
service: get_events
service_data:
duration:
hours: 18
entity_id:
- calendar.calendar_alert
target:
entity_id:
- calendar.calendar_alert
running_script: false
1
Iteration 1
Executed: November 24, 2024 at 2:02:38 PM
1
Iteration 2
Executed: November 24, 2024 at 2:02:39 PM
Result:
stop: ''
error: false
2
Executed: November 24, 2024 at 2:02:38 PM
Result:
stop: ''
error: false

@abeclinger
Copy link

abeclinger commented Nov 24, 2024

Final note, I'm using this as tts announcement - just wanted to share the end result :)

Also, the intents I mentioned above weren't actually needed for ChatGPT. I tried removing them and it continues to function, of course the standard home assistant "assist" does seem to need the intents (it no longer has access but I didn't really need it to, yet..). Just thought I'd clear that up.

I think everything you've described worked great btw. It was just a matter of me understanding how this functions and then ultimately giving the "assistant" home control.

image

@allenporter
Copy link
Author

Awesome, what prompt did you use to get it the quote at the end?

@abeclinger
Copy link

abeclinger commented Nov 24, 2024 via email

@cjramseyer
Copy link

Has there been any consideration to incorporating the to-do list? (local to-do) in this?

@abeclinger
Copy link

abeclinger commented Jan 8, 2025

Has there been any consideration to incorporating the to-do list? (local to-do) in this?

I think it's likely pretty easy to add to the intent_scripts linked to above ( https://github.com/allenporter/home-assistant-config/tree/main/config/intent_scripts) to include local to-do. I tried to do it but wasn't successful, probably some kind of syntax issue that would be less daunting for someone that's more knowledge than simply copy/pasting with ChatGPT ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment