Skip to main content
Composite functions execute a sequence of different function types, passing data between them. They’re ideal for complex workflows that require multiple steps with different capabilities.

Configuration

function:
  type: composite
  sequence:
    - type: function_type_1
      # Configuration for first function
      response_variable: result1
    - type: function_type_2
      # Configuration for second function (can use {{ result1 }})
sequence
array
required
List of functions to execute in order. Each can be any function type.
response_variable
string
Variable name to store this step’s result for use in subsequent steps

Data Flow

Data flows between sequence steps using response_variable:
1

Step 1 executes

First function runs and produces a result
- type: rest
  resource: https://api.example.com/data
  response_variable: api_data
2

Result stored

Result is stored in the variable name specified by response_variable
3

Step 2 accesses data

Subsequent steps can use the variable in templates
- type: template
  value_template: "Received: {{ api_data.count }} items"
4

Final result

The last step’s output becomes the function’s final result

Use Cases

Data Processing

Fetch raw data and format it for presentation

Multi-step Workflows

Execute complex sequences requiring different function types

Service + Template

Call services and format their responses

Conditional Logic

Use templates to process results conditionally

Best Practices

Use descriptive names for response_variable:
response_variable: weather_data  # Good
response_variable: result        # Too generic
response_variable: r1            # Not descriptive
Each composite function should accomplish one logical task. If you need many steps, consider breaking into multiple functions.✅ Good: 2-4 steps for a single purpose❌ Bad: 10+ steps doing unrelated things
Add error handling in templates:
{% if api_data is defined and api_data.success %}
  {{ api_data.result }}
{% else %}
  Error: Could not fetch data
{% endif %}
Test each step individually before combining:
  1. Create individual functions for each step
  2. Verify each works correctly
  3. Combine into composite function
  4. Test the complete sequence

Common Patterns

Pattern 1: API + Format

sequence:
  - type: rest
    resource: https://api.example.com/data
    response_variable: raw_data
  - type: template
    value_template: "{{ raw_data | format_nicely }}"

Pattern 2: Service + Extract

sequence:
  - type: script
    sequence:
      - service: domain.service
        response_variable: service_result
  - type: template
    value_template: "{{ service_result.important_field }}"

Pattern 3: Multi-source Aggregation

sequence:
  - type: rest
    resource: https://api1.example.com
    response_variable: data1
  - type: rest
    resource: https://api2.example.com
    response_variable: data2
  - type: template
    value_template: >-
      Combined data:
      Source 1: {{ data1.value }}
      Source 2: {{ data2.value }}

Pattern 4: Scrape + Process

sequence:
  - type: scrape
    resource: https://example.com
    response_variable: scraped
    sensor:
      - name: price
        select: ".price"
  - type: template
    value_template: >-
      {% set clean_price = scraped.price | replace('$', '') | float %}
      Price: ${{ "%.2f" | format(clean_price) }}

Debugging

Enable detailed logging:
logger:
  logs:
    custom_components.extended_openai_conversation: debug
Logs will show:
  • Each step’s input parameters
  • Each step’s output result
  • Variable assignments
  • Template rendering

Examples

Search and Play Music

Search for music, then play the first result:
- spec:
    name: search_music
    description: Use this function to search music
    parameters:
      type: object
      properties:
        query:
          type: string
          description: The search query
      required:
      - query
  function:
    type: composite
    sequence:
    - type: script
      sequence:
      - service: ytube_music_player.search
        data:
          entity_id: media_player.ytube_music_player
          query: "{{ query }}"
    - type: template
      value_template: >-
        media_content_type,media_content_id,title
        {% for media in state_attr('sensor.ytube_music_player_extra', 'search') -%}
          {{media.type}},{{media.id}},{{media.title}}
        {% endfor%}
Music Search

Get History with Formatting

Combine native get_history with template formatting:
- spec:
    name: get_history
    description: Retrieve historical data of specified entities.
    parameters:
      type: object
      properties:
        entity_ids:
          type: array
          items:
            type: string
            description: The entity id to filter.
        start_time:
          type: string
          description: Start of the history period in "%Y-%m-%dT%H:%M:%S%z".
        end_time:
          type: string
          description: End of the history period in "%Y-%m-%dT%H:%M:%S%z".
      required:
      - entity_ids
  function:
    type: composite
    sequence:
      - type: native
        name: get_history
        response_variable: history_result
      - type: template
        value_template: >-
          {% set ns = namespace(result = [], list = []) %}
          {% for item_list in history_result %}
              {% set ns.list = [] %}
              {% for item in item_list %}
                  {% set last_changed = item.last_changed | as_timestamp | timestamp_local if item.last_changed else None %}
                  {% set new_item = dict(item, last_changed=last_changed) %}
                  {% set ns.list = ns.list + [new_item] %}
              {% endfor %}
              {% set ns.result = ns.result + [ns.list] %}
          {% endfor %}
          {{ ns.result }}

Fetch and Process External Data

Get data from API and format it:
- spec:
    name: get_weather_detailed
    description: Get detailed weather information
    parameters:
      type: object
      properties:
        city:
          type: string
          description: City name
      required:
      - city
  function:
    type: composite
    sequence:
      - type: rest
        resource: "https://wttr.in/{{ city }}?format=j1"
        response_variable: weather_data
      - type: template
        value_template: >-
          Weather in {{ city }}:
          Current: {{ weather_data.current_condition[0].temp_C }}°C, {{ weather_data.current_condition[0].weatherDesc[0].value }}
          Humidity: {{ weather_data.current_condition[0].humidity }}%
          Wind: {{ weather_data.current_condition[0].windspeedKmph }} km/h

          3-Day Forecast:
          {% for day in weather_data.weather[:3] %}
          {{ day.date }}: {{ day.mintempC }}-{{ day.maxtempC }}°C
          {% endfor %}

Next Steps