Intent configuration

I’ve just installed Assist satellite and i’m wanting her to tell me my water tank levels when i ask for them. I’m having trouble getting my head around setting it up correctly and after some guideance please.

In configuration.yaml i have

conversation:
  intents: !include_dir_merge_named custom_sentences/en

intent_script:
  CheckTankLevel:
    action:
      - service: input_text.set_value
        data_template:
          entity_id: input_text.last_tank_query
          value: >
            {% if states('sensor.' ~ trigger.event.data.tank) %}
              Your {{ trigger.event.data.tank.replace('_', ' ') }} tank is {{ states('sensor.' ~ trigger.event.data.tank) }}.
            {% else %}
              I'm not sure about the level of your {{ trigger.event.data.tank.replace('_', ' ') }} tank.
            {% endif %}
    speech:
      text: "{{ states('input_text.last_tank_query') }}"

and in config/custom_sentences/en/tanklevels.yaml i have this

# config/custom_sentences/en/tank_levels.yaml
language: "en"
intents:
  CheckTankLevel:
    data:
      - sentences:
          - "How full is the {tank} water tank?"
          - "What's the {tank} water tank level?"
          - "Check the {tank} water tank level"

slot_type:
  tank:
    values:
      - grey
      - fresh1
      - fresh2
      - rain

The warning i get when checking the yaml before a restart is

Configuration warnings
Invalid config for 'conversation' at custom_sentences/en/tank_levels.yaml, line 11: value should be a string 'conversation->intents->slot_type->0', got None
Invalid config for 'conversation' at custom_sentences/en/tank_levels.yaml, line 3: value should be a string 'conversation->intents->intents->0', got None

What am i doing wrong please ?

the end goal is to ask assist " how full is the rain water tank" and she will respond with a value from my tank sensors, such as "your rain water tank is at least 1/4 full

i just changed tank_levels.yaml to this following code but that didnt help either

# config/custom_sentences/en/intents/tank_levels.yaml
language: "en"
intents:
  CheckTankLevel:
    data:
      - sentences:
          - "How full is the {tank} water tank?"
          - "What's the {tank} water tank level?"
          - "Check the {tank} water tank level"
        slots:
          tank:
            type: tank_type

slot_types:
  tank_type:
    values:
      - id: grey
        synonyms:
          - grey
      - id: fresh1
        synonyms:
          - fresh water tank one
      - id: fresh2
        synonyms:
          - fresh water tank two
      - id: rain
        synonyms:
          - rain

Where you have ‘slot_type’ in your original config should instead be ‘lists’:

# config/custom_sentences/en/tank_levels.yaml
language: "en"
intents:
  CheckTankLevel:
    data:
      - sentences:
          - "How full is the {tank} water tank?"
          - "What's the {tank} water tank level?"
          - "Check the {tank} water tank level"

lists:
  tank:
    values:
      - grey
      - fresh1
      - fresh2
      - rain

It’s not you, the documentation for Assist is scattered all over the place.

You don’t use trigger for intent scripts, that variable is used in automations. In intent scripts, IIRC, you should be using the list name.

Thanks for the Tips so far. I’ve made some modifications but it didn’t seem to help unfortunately.

This is my updated code

#configuration.yaml

        ########## CONVERSATION AND INTENTS ##############
conversation:
  
intent_script:
  CheckTankLevel:
    action:
      - service: input_text.set_value
        data_template:
          entity_id: input_text.last_tank_query
          value: >
            {% set tank_sensor = "sensor." ~ tank ~ "_water_level" %}
            {% if states(tank_sensor) %}
              Your {{ tank.replace('_', ' ') }} water tank is {{ states(tank_sensor) }}.
            {% else %}
              I'm not sure about the level of your {{ tank.replace('_', ' ') }} water tank.
            {% endif %}
    speech:
      text: "{{ states('input_text.last_tank_query') }}"
      
input_text:
  last_tank_query:
    name: "Last Tank Query"
    initial: "No queries yet."
# config/custom_sentences/en/intents/tank_levels.yaml
language: "en"
intents:
  CheckTankLevel:
    data:
      - sentences:
          - "How full is the {tank} water tank?"
          - "What's the {tank} water tank level?"
          - "Check the {tank} water tank level"
        slots:
          tank:
            type: tank_type
# config/custom_sentences/en/slot_types.yaml
lists:
  tank_type:
    values:
      - id: grey
        synonyms:
          - grey
      - id: fresh1
        synonyms:
          - fresh1
      - id: fresh2
        synonyms:
          - fresh2
      - id: rain_water_level
        synonyms:
          - rain
#config/input_text.yaml
input_text:
  last_tank_query:
    name: "Last Tank Query"
    initial: "No queries yet."

Do i need to !include the files in the /config/custome_sentences/en directory somewhere ? or do they get automatically recognised by HA ?

If you only need to get an answer, then do not use the action block. All logic can be written in the speech block. This will simplify the code

ahh, yes that makes it cleaner thanks :slight_smile: Still not working but certainly simpler

        ########## CONVERSATION AND INTENTS ##############
conversation:
  
intent_script:
  CheckTankLevel:
    description: Vocally speak the water tank level if requested 
    speech:
      text: >
        {% set tank_sensor = "sensor." ~ tank %}
        {% if states(tank_sensor) %}
          Your {{ tank.replace('_', ' ') }} is {{ states(tank_sensor) }}.
        {% else %}
          I'm not sure about the level of your {{ tank.replace('_', ' ') }}.
        {% endif %}

Should there not be a service i can call for intents so i can test whats going on ? if i look in “developer > services” all i see is “intent_script.reload” regarding a intent related service

There is a debug tool in the Developer Tools under Assist.

I will suggest using a list with a replacement for device IDs.

lists:
  tank_type:
    values:
      - in: grey
        out: sensor.grey_water_level 
      - in: ...

And in the response, you can return the usual name when needed:

state_attr("tank_type", "friendly_name")

thanks, i have implemented that also.

I’ve actually just stunbled across this error , not sure what it means but at least i found a error :slight_smile:

Logger: homeassistant.components.websocket_api.http.connection
Source: components/conversation/default_agent.py:744
integration: Home Assistant WebSocket API (documentation, issues)
First occurred: 7:43:12 AM (2 occurrences)
Last logged: 7:43:21 AM

[546929601856] Error handling message: Unknown error (unknown_error) Larry from 192.168.1.190 (Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36)
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/websocket_api/decorators.py", line 27, in _handle_async_response
    await func(hass, connection, msg)
  File "/usr/src/homeassistant/homeassistant/components/conversation/http.py", line 184, in websocket_hass_agent_debug
    await agent.async_recognize(
  File "/usr/src/homeassistant/homeassistant/components/conversation/default_agent.py", line 227, in async_recognize
    lang_intents = await self.async_get_or_load_intents(language)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/conversation/default_agent.py", line 614, in async_get_or_load_intents
    return await self.hass.async_add_executor_job(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/conversation/default_agent.py", line 744, in _get_or_load_intents
    intents = Intents.from_dict(intents_dict)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/hassil/intents.py", line 335, in from_dict
    list_name: _parse_list(list_dict)
               ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/hassil/intents.py", line 370, in _parse_list
    text_in=_maybe_parse_template(value["in"], allow_template),
                                  ~~~~~^^^^^^
KeyError: 'in'

extra quotes
I quickly sketched out a working version.
Sentence

  ledstate:
    data:
      - sentences:
          - "светит ли {led}"
lists:
  led:
    values:
      - in: "основной свет"
        out: "light.dimmer_01"
      - in: "стена"
        out: "light.dimmerrgb"

and script

ledstate:
  speech:
    text: >-
        {% if states(led) %}
          Your {{ state_attr(led, 'friendly_name') }} is {{ states(led) }}
        {% else %}
          I'm not sure about the state of your {{ led }}.
        {% endif %}

But I don’t fully understand what you are checking with this condition. I would modify it so that it responds to the state of unavailability

Thanks, i did refine it some more and here’s what ive noticed …

  • If i use “developer >> assist” screen and enter the phrase “how full is the rain water tank” then i get this result
intent:
  name: CheckTankLevel
slots:
  tank: rain water tank
details:
  tank:
    name: tank
    value: sensor.rain_water_level
    text: rain water tank
targets: {}
match: true
sentence_template: How full is the {tank}
unmatched_slots: {}
source: custom
file: en/tank_levels.yaml

so to me that indicates that the intent code is now working as expected ?

However, If i also ask the exact same sentence via the lovelace “assist” chat icon, she has no idea what im talking about

Also if i verbally ask the satellite “how full is the rain water tank” she has no idea what im talking about either and responds with " i cant check the rain water sensor you dont have one, try sticking your head in the tank" (nice touch openAI hehe).

neither of which makes sense to me if “developer >> assist” is processing the sentence correctly. If anything the chat icon should process it properly also as its typed not spoken. But it’s doing my head in.

I added a conversation logger to the config yaml but during the last tests i don’t see any errors for this currently.

is this a Bug or am i missing something ?

latest Code:

########## CONVERSATION AND INTENTS in configuration.yaml ##############

conversation:
  
intent_script:
  CheckTankLevel:
    description: Vocally speak the water tank level if requested
    speech:
      text: >-
        {% set tank_sensor = "slots.tank.value" %}
        {% if states(tank_sensor) %}
          Your {{ state_attr(tank_sensor, 'friendly_name') }} is {{ states(tank_sensor) }}.
        {% else %}
          I'm not sure about the level of your {{ tank_sensor }}.
        {% endif %}

logger:
  default: info
  logs:
    homeassistant.components.conversation: debug

and

#config/custom_sentences/en/tank_levels.yaml
language: "en"
intents:
  CheckTankLevel:
    data:
      - sentences:
          - "How full is the {tank}"
          - "What's the {tank} level"
          - "Check the {tank} level"

lists:
  tank:
    values:
      - in: "grey water tank"
        out: "sensor.grey_water_level"
      - in: "fresh water tank 1"
        out: "sensor.fresh_water_level_1"
      - in: "fresh water tank 2"
        out: "sensor.fresh_water_level_2"
      - in: "rain water tank"
        out: "sensor.rain_water_level"

You have added a line

{% set tank_sensor = "slots.tank.value" %}

this is an error for this syntax. The system passes the Value field ( in your case {{ tank }} = sensor.rain_water_level ), there is no need to request it additionally. It is necessary to either replace the variable or completely remove this reassignment.

{% set tank_sensor = tank %}

thanks how ever that resulted in

2024-06-30 06:56:10.730 ERROR (Thread-7) [pychromecast.socket_client] [2K SMART TV(192.168.1.44):8009] Failed to connect to service MDNSServiceInfo(name='2K-SMART-TV-250f4d5ad9e3f87de2ea303a1e7fb944._googlecast._tcp.local.'), retrying in 5.0s
2024-06-30 06:56:30.780 ERROR (MainThread) [homeassistant.helpers.template] Template variable error: 'tank' is undefined when rendering '{% set tank_sensor = tank %} {% if states(tank_sensor) %}
Your {{ state_attr(tank_sensor, 'friendly_name') }} is {{ states(tank_sensor) }}.
{% else %}
I'm not sure about the level of your {{ tank_sensor }}.
{% endif %}'
2024-06-30 06:56:30.784 ERROR (MainThread) [homeassistant.helpers.script.intent_script_checktanklevel] Intent Script CheckTankLevel: Error executing script. Error for call_service at pos 2: Error rendering data template: UndefinedError: 'tank' is undefined

I’ve also tried

{% set tank_sensor = "details.tank.value" %}
{% set tank_sensor = "sensor.rain_water_level" %}
{% set tank_sensor = "tank" %}
and 
{% set tank_sensor = tank %}

None of which work however {% set tank_sensor = tank %} gave me the above error, the rest don’t give a error.

I’m expecting by hardcoding the sensor into the script “sensor.water_tank_level” it should work i would of thought but it doesnt. shrug

It remains to try this code

        {% if states(tank) %}
          Your {{ state_attr(tank, 'friendly_name') }} is {{ states(tank) }}.
        {% else %}
          I'm not sure about the level of your {{ tank }}.
        {% endif %}

It works for me, as I said before.
image

Your parsing works the same way as mine. There is no mistake in this part.

intent:
  name: ledstate
slots:
  led: стена
details:
  led:
    name: led
    value: light.dimmerrgb
    text: стена
targets: {}
match: true
sentence_template: светит ли {led}
unmatched_slots: {}
source: custom
file: ru/addon.yaml

So here is my embarrassing outcome for any other Noob that gets stuck.

I spent three days, well no, i actually spent 4 days trying to get intents working so i can ask my assist satellite how full my water tanks are and for the life of me i couldnt get it working. Assist would understand the intent code and action most of it but would always tell me “i cant read your rain water sensor” or try sticking your head in the tank cause i cant check that" etc …

The simple answer in the end was : It turns out despite adding sensor data to the configuration.yaml and rebooting, home assistant wont automatically expose those new entities to assist. You have to manually go into “settings >> voice assistant >> name of assistant >> expose entities” and manually add the new sensor or what ever you have added to the yaml.
After doing that i didnt even need to make the intent script at all, so i’ve deleted that script and can now ask “what’s the level of the rain water tank” and she tells me correctly. super embarrassing that i over looked this.

However, i have learnt new things along the way for anyone else just starting out. So here’s some tips

When working with assist…

  1. You can view what she/he “thinks you say” by going to system logs and looking up the logs for “whisper”.

  2. go to “developer >> assist” and type in a sentence for your intent to get info on if the intent you created is functional and being actioned as you expect

  3. use brackets and such as per docs to structure your sentences more universally as per below. The below is in the docs, i just didn’t find it super clear so will clarify here

  CheckTankLevel:
    data:
      - sentences:
          - "(check|How full is) the {tank} [tank]?"
          - "What's the {tank} [tank] level?"

the use of () brackets such as (check|how full is) tells assist to trigger using either of those phrases " check the tank" or “how full is the tank”,

The use of {} is a wild card and in this case {tank} will account for various tanks based on your list. such as “check the rain water tank” and “check the fresh water tank” will both work

The use of brackets is a optional word, so in the above example “check the rain water” and “check the rain water tank” will both work.

Anyway… thanks to those that helped and hopefully this thread helps someone else in the future :slight_smile:

1 Like