Warning
This project is a prototype and is not production-ready.
An external replacement for the default conversation agent in Home Assistant.
Run with Docker:
docker run -it \
-p 10500:10500 \
-v /etc/localtime:/etc/localtime:ro \
-v /etc/timezone:/etc/timezone:ro \
'ghcr.io/ohf-voice/default-agent' \
--hass-api 'http://homeassistant.local:8123/api' \
--hass-token '<long-lived HA access token>'Or manually install with:
pip install 'default-agent@https://github.com/OHF-Voice/default-agent/archive/refs/heads/main.tar.gz'and then run with:
python -m default_agent \
--uri 'tcp://0.0.0.0:10500' \
--hass-api 'http://homeassistant.local:8123/api' \
--hass-token '<long-lived HA access token>'You can now go to Home Assistant and add a Wyoming integration with the host/port of the default agent server (port 10500 was used in the example).
Create a voice assistant pipeline with the discovered conversation agent, and ensure that "Prefer local intents" is off.
Add --debug for more logging.
This project replicates the behavior of the default Assist agent in Home Assistant. When a new command comes in, this agent:
- Fetches information about exposed entities, areas, and floors from Home Assistant
- Finds the best intent match for the command text using hassil
- Command sentences come from the home-assistant-intents package, custom sentences, or a development version of the intents repository
- Matches names with entities/areas/floors in
async_match_targets - Locates an intent handler for the matched intent
- Executes the appropriate actions in the intent handler
- Returns a response to the user
For timers to work, you will need to install a HACS integration that adds the appropriate websocket commands.
Just like in Home Assistant, custom sentences can be used by passing --custom-sentences /path/to/custom_sentences to the server. This should contain <language>/<sentences>.yaml files, such as en/my_sentences.yaml.
If you just want to use custom sentences, the --no-builtin-intents option will disable loading the built-in intents.
Responses can also be overridden in a custom sentences file. For example, adding this YAML to a file like en/my_sentences.yaml will override the response for when lights are turned on in a specific area:
language: en
responses:
intents:
HassTurnOn:
lights_area: "Turn on the lights in the {{ slots.area }}"See the responses directory of the intents repository for a list of available responses.
You can work on a development version of the intents repo by passing --intents-repo /path/to/intents to the server. This will load intents from the repo instead of using the built-in home-assistant-intents package.
You may disable specific intents by using --disable-intent <intent>. These intents will not be loaded (either from built-in intents or your custom sentences), and therefore cannot be matched.
Ideas for the future of this project:
- A web interface that allows users to:
- Test and debug sentences and intent handlers
- Enable/disable intents (per area or satellite?)
- Enable/disable specific intent slot combinations. For example, users could allow the lights to be turned on/off in the current area, but not other areas by name.
- The addition of fuzzy command matching via sentence transformers
- Make entity exposure more fine-grained, so some entities are only exposed to specific satellites
- Add both long and short responses, and allow users to configure which are used and when
- Allow custom intents that can use parts of Home Assistant's script syntax to execute their actions (no Python needed)
- Make name matching more customizable. For example, having "turn on kitchen lights" match "turn on {area} lights" before "turn on {name}"