Querying Multiple Calendars

I have several local calendars that are working fine. I can query each calendar individually using the following code.
(5 min time is just for testing!!)

- trigger:
    platform: time_pattern
    minutes: /5
  action:
  - service: calendar.get_events
    target:
      entity_id: calendar.recurring_events
    data:
      start_date_time: "{{ now().strftime('%Y-%m-%d 00:00:00') }}"
      end_date_time: "{{ (now() + timedelta(days=5)).strftime('%Y-%m-%d 00:00:00') }}"
    response_variable: calendar_events_response
  sensor:
  - name: Recurring Events Sensor
    unique_id: recurring_events_sensor
    state: "{{ calendar_events_response['calendar.recurring_events'].events | count() }}"
    attributes:
      calendar_events_response: "{{ calendar_events_response['calendar.recurring_events'].events }}"
    icon: mdi:calendar

This gets me the following response

calendar.recurring_events:
  events:
    - start: "2025-05-14"
      end: "2025-05-15"
      summary: Trash Pick-up
      description: Trash Pick-up
    - start: "2025-05-18"
      end: "2025-05-19"
      summary: Recycling Pick-up
      description: Recycling Pick-up

All fine and good. Now, in the Actions tab of the Developer Tools I can query multiple calendars at once using

action: calendar.get_events
data:
  duration:
    hours: 120
    minutes: 0
    seconds: 0
target:
  entity_id:
    - calendar.recurring_events
    - calendar.local_events_2025
    - calendar.school_2025

and getting this response

calendar.recurring_events:
  events:
    - start: "2025-05-14"
      end: "2025-05-15"
      summary: Trash Pick-up
      description: Trash Pick-up
    - start: "2025-05-18"
      end: "2025-05-19"
      summary: Recycling Pick-up
      description: Recycling Pick-up
calendar.local_events_2025:
  events:
    - start: "2025-05-16T14:00:00-04:00"
      end: "2025-05-16T16:00:00-04:00"
      summary: Test Summary
      description: Test Description
      location: Test Location
    - start: "2025-05-16T14:00:00-04:00"
      end: "2025-05-16T16:00:00-04:00"
      summary: Test Summary 2
      description: Test Description 2
      location: Test Location 2
calendar.school_2025:
  events: []

Where I need help is with the response, particularly how to get all calendars instead of just one.

  - name: Recurring Events Sensor
    unique_id: recurring_events_sensor
>> THIS LINE
    state: "{{ calendar_events_response['calendar.recurring_events'].events | count() }"
>> ----------
    attributes:
>> AND THIS LINE
      calendar_events_response: "{{ calendar_events_response['calendar.recurring_events'].events }}"
>> ----------
    icon: mdi:calendar

I have tried
calendar_events_response['calendar.recurring_events','calendar.local_events_2025','calendar.school_2025'].events|count()
calendar_events_response.events|count()
and
calendar_events_response[].events|count()

None work. There must be a solution to this if it can be done in the Developer tab, but I can’t find an answer.
If there’s a better way to get all the calendar data for several upcoming days into a sensor attribute I’m willing to give it a try.
Note: None of the cards out there do exactly what Im trying to accomplish, and as an alternative I know could create 3 separate template sensors. My brain makes me want to stuff it all into one sensor if it’s possible. :rofl:

Original Answer
- trigger:
    platform: time_pattern
    minutes: /5
  action:
    - action: calendar.get_events
      data:
        duration:
          hours: 120
      target:
        entity_id:
          - calendar.recurring_events
          - calendar.local_events_2025
          - calendar.school_2025
      response_variable: agenda
    - variables:
        combined_events: |
          {{ agenda['calendar.recurring_events'].events 
          + agenda['calendar.local_events_2025'].events 
          + agenda['calendar.school_2025'].events }}
  sensor:
    - name: Recurring Events Sensor
      unique_id: recurring_events_sensor
      state: "{{ combined_events | count }}"
      attributes:
        calendar_events_response: "{{ combined_events }}"
      icon: mdi:calendar

It’s also possible to define combined_events using templates to loop through whatever calendars are present.

    - variables:
        combined_events: |
          {% set ns = namespace(events=[])%}
          {% for c in agenda %}
            {% set ns.events = ns.events + agenda[c].events %}
          {% endfor %}
          {{ ns.events }}

It’s a little more complicated and less efficient than just adding the lists, but it can be necessary if you need to manipulate the event data; especially if you need to be able to reference the source calendar.

EDIT: The addition of the merge_response function makes this a little bit cleaner and provides additional functionality in the long run.

- trigger:
    platform: time_pattern
    minutes: /5
  action:
    - action: calendar.get_events
      data:
        duration:
          hours: 120
      target:
        entity_id:
          - calendar.recurring_events
          - calendar.local_events_2025
          - calendar.school_2025
      response_variable: agenda
    - variables:
        combined_events: "{{ merge_response(agenda) }}"
  sensor:
    - name: Recurring Events Sensor
      unique_id: recurring_events_sensor
      state: "{{ combined_events | count }}"
      attributes:
        calendar_events_response: "{{ combined_events }}"
      icon: mdi:calendar

@Didgeridrew
Thank you! This works perfectly, and after seeing how it’s done, makes perfect sense. I’m always appreciative of the support I this forum and the vast skill set of its members.