diff --git a/homeassistant/components/conversation/default_agent.py b/homeassistant/components/conversation/default_agent.py
index 2e8e78d6f38a641fcb4f5f3694489108a6b3a1a6..aba5aafd3782f0dc5a0e966d1ab6498b26eaf54f 100644
--- a/homeassistant/components/conversation/default_agent.py
+++ b/homeassistant/components/conversation/default_agent.py
@@ -1,36 +1,26 @@
 """Standard conversation implementation for Home Assistant."""
 from __future__ import annotations
 
+from dataclasses import dataclass
+import logging
 import re
+from typing import Any
+
+from hassil.intents import Intents, SlotList, TextSlotList
+from hassil.recognize import recognize
+from hassil.util import merge_dict
+from home_assistant_intents import get_intents
 
 from homeassistant import core, setup
-from homeassistant.components.cover.intent import INTENT_CLOSE_COVER, INTENT_OPEN_COVER
-from homeassistant.components.shopping_list.intent import (
-    INTENT_ADD_ITEM,
-    INTENT_LAST_ITEMS,
-)
-from homeassistant.const import EVENT_COMPONENT_LOADED
-from homeassistant.core import callback
-from homeassistant.helpers import intent
-from homeassistant.setup import ATTR_COMPONENT
+from homeassistant.helpers import area_registry, entity_registry, intent
 
 from .agent import AbstractConversationAgent, ConversationResult
 from .const import DOMAIN
 from .util import create_matcher
 
-REGEX_TURN_COMMAND = re.compile(r"turn (?P<name>(?: |\w)+) (?P<command>\w+)")
-REGEX_TYPE = type(re.compile(""))
+_LOGGER = logging.getLogger(__name__)
 
-UTTERANCES = {
-    "cover": {
-        INTENT_OPEN_COVER: ["Open [the] [a] [an] {name}[s]"],
-        INTENT_CLOSE_COVER: ["Close [the] [a] [an] {name}[s]"],
-    },
-    "shopping_list": {
-        INTENT_ADD_ITEM: ["Add [the] [a] [an] {item} to my shopping list"],
-        INTENT_LAST_ITEMS: ["What is on my shopping list"],
-    },
-}
+REGEX_TYPE = type(re.compile(""))
 
 
 @core.callback
@@ -50,12 +40,22 @@ def async_register(hass, intent_type, utterances):
             conf.append(create_matcher(utterance))
 
 
+@dataclass
+class LanguageIntents:
+    """Loaded intents for a language."""
+
+    intents: Intents
+    intents_dict: dict[str, Any]
+    loaded_components: set[str]
+
+
 class DefaultAgent(AbstractConversationAgent):
     """Default agent for conversation agent."""
 
     def __init__(self, hass: core.HomeAssistant) -> None:
         """Initialize the default agent."""
         self.hass = hass
+        self._lang_intents: dict[str, LanguageIntents] = {}
 
     async def async_initialize(self, config):
         """Initialize the default agent."""
@@ -63,80 +63,139 @@ class DefaultAgent(AbstractConversationAgent):
             await setup.async_setup_component(self.hass, "intent", {})
 
         config = config.get(DOMAIN, {})
-        intents = self.hass.data.setdefault(DOMAIN, {})
-
-        for intent_type, utterances in config.get("intents", {}).items():
-            if (conf := intents.get(intent_type)) is None:
-                conf = intents[intent_type] = []
+        self.hass.data.setdefault(DOMAIN, {})
 
-            conf.extend(create_matcher(utterance) for utterance in utterances)
+        if config:
+            _LOGGER.warning(
+                "Custom intent sentences have been moved to config/custom_sentences"
+            )
 
-        # We strip trailing 's' from name because our state matcher will fail
-        # if a letter is not there. By removing 's' we can match singular and
-        # plural names.
-
-        async_register(
-            self.hass,
-            intent.INTENT_TURN_ON,
-            ["Turn [the] [a] {name}[s] on", "Turn on [the] [a] [an] {name}[s]"],
-        )
-        async_register(
+    async def async_process(
+        self,
+        text: str,
+        context: core.Context,
+        conversation_id: str | None = None,
+        language: str | None = None,
+    ) -> ConversationResult | None:
+        """Process a sentence."""
+        language = language or self.hass.config.language
+        lang_intents = self._lang_intents.get(language)
+
+        # Reload intents if missing or new components
+        if lang_intents is None or (
+            lang_intents.loaded_components - self.hass.config.components
+        ):
+            # Load intents in executor
+            lang_intents = await self.hass.async_add_executor_job(
+                self.get_or_load_intents,
+                language,
+            )
+
+        if lang_intents is None:
+            # No intents loaded
+            _LOGGER.warning("No intents were loaded for language: %s", language)
+            return None
+
+        slot_lists: dict[str, SlotList] = {
+            "area": self._make_areas_list(),
+            "name": self._make_names_list(),
+        }
+
+        result = recognize(text, lang_intents.intents, slot_lists=slot_lists)
+        if result is None:
+            return None
+
+        intent_response = await intent.async_handle(
             self.hass,
-            intent.INTENT_TURN_OFF,
-            ["Turn [the] [a] [an] {name}[s] off", "Turn off [the] [a] [an] {name}[s]"],
+            DOMAIN,
+            result.intent.name,
+            {entity.name: {"value": entity.value} for entity in result.entities_list},
+            text,
+            context,
+            language,
         )
-        async_register(
-            self.hass,
-            intent.INTENT_TOGGLE,
-            ["Toggle [the] [a] [an] {name}[s]", "[the] [a] [an] {name}[s] toggle"],
+
+        return ConversationResult(
+            response=intent_response, conversation_id=conversation_id
         )
 
-        @callback
-        def component_loaded(event):
-            """Handle a new component loaded."""
-            self.register_utterances(event.data[ATTR_COMPONENT])
+    def get_or_load_intents(self, language: str) -> LanguageIntents | None:
+        """Load all intents for language."""
+        lang_intents = self._lang_intents.get(language)
 
-        self.hass.bus.async_listen(EVENT_COMPONENT_LOADED, component_loaded)
+        if lang_intents is None:
+            intents_dict: dict[str, Any] = {}
+            loaded_components: set[str] = set()
+        else:
+            intents_dict = lang_intents.intents_dict
+            loaded_components = lang_intents.loaded_components
 
-        # Check already loaded components.
+        # Check if any new components have been loaded
+        intents_changed = False
         for component in self.hass.config.components:
-            self.register_utterances(component)
+            if component in loaded_components:
+                continue
 
-    @callback
-    def register_utterances(self, component):
-        """Register utterances for a component."""
-        if component not in UTTERANCES:
-            return
-        for intent_type, sentences in UTTERANCES[component].items():
-            async_register(self.hass, intent_type, sentences)
+            # Don't check component again
+            loaded_components.add(component)
 
-    async def async_process(
-        self,
-        text: str,
-        context: core.Context,
-        conversation_id: str | None = None,
-        language: str | None = None,
-    ) -> ConversationResult | None:
-        """Process a sentence."""
-        intents = self.hass.data[DOMAIN]
+            # Check for intents for this component with the target language
+            component_intents = get_intents(component, language)
+            if component_intents:
+                # Merge sentences into existing dictionary
+                merge_dict(intents_dict, component_intents)
+
+                # Will need to recreate graph
+                intents_changed = True
+
+        if not intents_dict:
+            return None
+
+        if not intents_changed and lang_intents is not None:
+            return lang_intents
 
-        for intent_type, matchers in intents.items():
-            for matcher in matchers:
-                if not (match := matcher.match(text)):
+        # This can be made faster by not re-parsing existing sentences.
+        # But it will likely only be called once anyways, unless new
+        # components with sentences are often being loaded.
+        intents = Intents.from_dict(intents_dict)
+
+        if lang_intents is None:
+            lang_intents = LanguageIntents(intents, intents_dict, loaded_components)
+            self._lang_intents[language] = lang_intents
+        else:
+            lang_intents.intents = intents
+
+        return lang_intents
+
+    def _make_areas_list(self) -> TextSlotList:
+        """Create slot list mapping area names/aliases to area ids."""
+        registry = area_registry.async_get(self.hass)
+        areas = []
+        for entry in registry.async_list_areas():
+            areas.append((entry.name, entry.id))
+            if entry.aliases:
+                for alias in entry.aliases:
+                    areas.append((alias, entry.id))
+
+        return TextSlotList.from_tuples(areas)
+
+    def _make_names_list(self) -> TextSlotList:
+        """Create slot list mapping entity names/aliases to entity ids."""
+        states = self.hass.states.async_all()
+        registry = entity_registry.async_get(self.hass)
+        names = []
+        for state in states:
+            entry = registry.async_get(state.entity_id)
+            if entry is not None:
+                if entry.entity_category:
+                    # Skip configuration/diagnostic entities
                     continue
 
-                intent_response = await intent.async_handle(
-                    self.hass,
-                    DOMAIN,
-                    intent_type,
-                    {key: {"value": value} for key, value in match.groupdict().items()},
-                    text,
-                    context,
-                    language,
-                )
-
-                return ConversationResult(
-                    response=intent_response, conversation_id=conversation_id
-                )
-
-        return None
+                if entry.aliases:
+                    for alias in entry.aliases:
+                        names.append((alias, state.entity_id))
+
+            # Default name
+            names.append((state.name, state.entity_id))
+
+        return TextSlotList.from_tuples(names)
diff --git a/homeassistant/components/conversation/manifest.json b/homeassistant/components/conversation/manifest.json
index 54265bfcb833966dc624c1693e2915a113abf0d7..b83dfe431d595ba39a0ba8c42ce6334bbab6bf0f 100644
--- a/homeassistant/components/conversation/manifest.json
+++ b/homeassistant/components/conversation/manifest.json
@@ -2,6 +2,7 @@
   "domain": "conversation",
   "name": "Conversation",
   "documentation": "https://www.home-assistant.io/integrations/conversation",
+  "requirements": ["hassil==0.2.3", "home-assistant-intents==0.0.1"],
   "dependencies": ["http"],
   "codeowners": ["@home-assistant/core"],
   "quality_scale": "internal",
diff --git a/homeassistant/helpers/intent.py b/homeassistant/helpers/intent.py
index 100d64c8fb64539bd157e28724e278ac1674f435..ba6461e1d604330be9e9bcc39dbbc52b5b307913 100644
--- a/homeassistant/helpers/intent.py
+++ b/homeassistant/helpers/intent.py
@@ -1,12 +1,12 @@
 """Module to coordinate user intentions."""
 from __future__ import annotations
 
-from collections.abc import Callable, Iterable
+import asyncio
+from collections.abc import Iterable
 import dataclasses
 from dataclasses import dataclass
 from enum import Enum
 import logging
-import re
 from typing import Any, TypeVar
 
 import voluptuous as vol
@@ -16,7 +16,7 @@ from homeassistant.core import Context, HomeAssistant, State, callback
 from homeassistant.exceptions import HomeAssistantError
 from homeassistant.loader import bind_hass
 
-from . import config_validation as cv
+from . import area_registry, config_validation as cv, entity_registry
 
 _LOGGER = logging.getLogger(__name__)
 _SlotsType = dict[str, Any]
@@ -119,7 +119,25 @@ def async_match_state(
     if states is None:
         states = hass.states.async_all()
 
-    state = _fuzzymatch(name, states, lambda state: state.name)
+    name = name.casefold()
+    state: State | None = None
+    registry = entity_registry.async_get(hass)
+
+    for maybe_state in states:
+        # Check entity id and name
+        if name in (maybe_state.entity_id, maybe_state.name.casefold()):
+            state = maybe_state
+        else:
+            # Check aliases
+            entry = registry.async_get(maybe_state.entity_id)
+            if (entry is not None) and entry.aliases:
+                for alias in entry.aliases:
+                    if name == alias.casefold():
+                        state = maybe_state
+                        break
+
+        if state is not None:
+            break
 
     if state is None:
         raise IntentHandleError(f"Unable to find an entity called {name}")
@@ -127,6 +145,18 @@ def async_match_state(
     return state
 
 
+@callback
+@bind_hass
+def async_match_area(
+    hass: HomeAssistant, area_name: str
+) -> area_registry.AreaEntry | None:
+    """Find an area that matches the name."""
+    registry = area_registry.async_get(hass)
+    return registry.async_get_area(area_name) or registry.async_get_area_by_name(
+        area_name
+    )
+
+
 @callback
 def async_test_feature(state: State, feature: int, feature_name: str) -> None:
     """Test if state supports a feature."""
@@ -173,29 +203,17 @@ class IntentHandler:
         return f"<{self.__class__.__name__} - {self.intent_type}>"
 
 
-def _fuzzymatch(name: str, items: Iterable[_T], key: Callable[[_T], str]) -> _T | None:
-    """Fuzzy matching function."""
-    matches = []
-    pattern = ".*?".join(name)
-    regex = re.compile(pattern, re.IGNORECASE)
-    for idx, item in enumerate(items):
-        if match := regex.search(key(item)):
-            # Add key length so we prefer shorter keys with the same group and start.
-            # Add index so we pick first match in case same group, start, and key length.
-            matches.append(
-                (len(match.group()), match.start(), len(key(item)), idx, item)
-            )
-
-    return sorted(matches)[0][4] if matches else None
-
-
 class ServiceIntentHandler(IntentHandler):
     """Service Intent handler registration.
 
     Service specific intent handler that calls a service by name/entity_id.
     """
 
-    slot_schema = {vol.Required("name"): cv.string}
+    slot_schema = {
+        vol.Any("name", "area"): cv.string,
+        vol.Optional("domain"): vol.All(cv.ensure_list, [cv.string]),
+        vol.Optional("device_class"): vol.All(cv.ensure_list, [cv.string]),
+    }
 
     def __init__(
         self, intent_type: str, domain: str, service: str, speech: str
@@ -210,26 +228,101 @@ class ServiceIntentHandler(IntentHandler):
         """Handle the hass intent."""
         hass = intent_obj.hass
         slots = self.async_validate_slots(intent_obj.slots)
-        state = async_match_state(hass, slots["name"]["value"])
 
-        await hass.services.async_call(
-            self.domain,
-            self.service,
-            {ATTR_ENTITY_ID: state.entity_id},
-            context=intent_obj.context,
-        )
+        if "area" in slots:
+            # Entities in an area
+            area_name = slots["area"]["value"]
+            area = async_match_area(hass, area_name)
+            assert area is not None
+            assert area.id is not None
+
+            # Optional domain filter
+            domains: set[str] | None = None
+            if "domain" in slots:
+                domains = set(slots["domain"]["value"])
+
+            # Optional device class filter
+            device_classes: set[str] | None = None
+            if "device_class" in slots:
+                device_classes = set(slots["device_class"]["value"])
 
-        response = intent_obj.create_response()
-        response.async_set_speech(self.speech.format(state.name))
-        response.async_set_results(
-            success_results=[
+            success_results = [
                 IntentResponseTarget(
-                    type=IntentResponseTargetType.ENTITY,
-                    name=state.name,
-                    id=state.entity_id,
-                ),
-            ],
-        )
+                    type=IntentResponseTargetType.AREA, name=area.name, id=area.id
+                )
+            ]
+            service_coros = []
+            registry = entity_registry.async_get(hass)
+            for entity_entry in entity_registry.async_entries_for_area(
+                registry, area.id
+            ):
+                if entity_entry.entity_category:
+                    # Skip diagnostic entities
+                    continue
+
+                if domains and (entity_entry.domain not in domains):
+                    # Skip entity not in the domain
+                    continue
+
+                if device_classes and (entity_entry.device_class not in device_classes):
+                    # Skip entity with wrong device class
+                    continue
+
+                service_coros.append(
+                    hass.services.async_call(
+                        self.domain,
+                        self.service,
+                        {ATTR_ENTITY_ID: entity_entry.entity_id},
+                        context=intent_obj.context,
+                    )
+                )
+
+                state = hass.states.get(entity_entry.entity_id)
+                assert state is not None
+
+                success_results.append(
+                    IntentResponseTarget(
+                        type=IntentResponseTargetType.ENTITY,
+                        name=state.name,
+                        id=entity_entry.entity_id,
+                    ),
+                )
+
+            if not service_coros:
+                raise IntentHandleError("No entities matched")
+
+            # Handle service calls in parallel.
+            # We will need to handle partial failures here.
+            await asyncio.gather(*service_coros)
+
+            response = intent_obj.create_response()
+            response.async_set_speech(self.speech.format(area.name))
+            response.async_set_results(
+                success_results=success_results,
+            )
+        else:
+            # Single entity
+            state = async_match_state(hass, slots["name"]["value"])
+
+            await hass.services.async_call(
+                self.domain,
+                self.service,
+                {ATTR_ENTITY_ID: state.entity_id},
+                context=intent_obj.context,
+            )
+
+            response = intent_obj.create_response()
+            response.async_set_speech(self.speech.format(state.name))
+            response.async_set_results(
+                success_results=[
+                    IntentResponseTarget(
+                        type=IntentResponseTargetType.ENTITY,
+                        name=state.name,
+                        id=state.entity_id,
+                    ),
+                ],
+            )
+
         return response
 
 
diff --git a/requirements_all.txt b/requirements_all.txt
index f19a630aa18b8ea552a0da91d5bb9a2bb604e9bf..db802fdd5175e0b62de7d98f4d918566ca77c977 100644
--- a/requirements_all.txt
+++ b/requirements_all.txt
@@ -867,6 +867,9 @@ hass-nabucasa==0.61.0
 # homeassistant.components.splunk
 hass_splunk==0.1.1
 
+# homeassistant.components.conversation
+hassil==0.2.3
+
 # homeassistant.components.tasmota
 hatasmota==0.6.2
 
@@ -900,6 +903,9 @@ holidays==0.18.0
 # homeassistant.components.frontend
 home-assistant-frontend==20230104.0
 
+# homeassistant.components.conversation
+home-assistant-intents==0.0.1
+
 # homeassistant.components.home_connect
 homeconnect==0.7.2
 
diff --git a/requirements_test_all.txt b/requirements_test_all.txt
index 52ac74d670cbe17cbc01138640939635016bf886..ab0b26afb9df5849be6c90c0cc14f3aaf53f6ecf 100644
--- a/requirements_test_all.txt
+++ b/requirements_test_all.txt
@@ -656,6 +656,9 @@ habitipy==0.2.0
 # homeassistant.components.cloud
 hass-nabucasa==0.61.0
 
+# homeassistant.components.conversation
+hassil==0.2.3
+
 # homeassistant.components.tasmota
 hatasmota==0.6.2
 
@@ -680,6 +683,9 @@ holidays==0.18.0
 # homeassistant.components.frontend
 home-assistant-frontend==20230104.0
 
+# homeassistant.components.conversation
+home-assistant-intents==0.0.1
+
 # homeassistant.components.home_connect
 homeconnect==0.7.2
 
diff --git a/tests/components/conversation/test_init.py b/tests/components/conversation/test_init.py
index c25df45ce783f81d78bdb3109ab29fb829636609..ffb7894cd00acfee5b6d9aa4a79e3ba8e3a2d032 100644
--- a/tests/components/conversation/test_init.py
+++ b/tests/components/conversation/test_init.py
@@ -5,11 +5,11 @@ from unittest.mock import ANY, patch
 import pytest
 
 from homeassistant.components import conversation
-from homeassistant.core import DOMAIN as HASS_DOMAIN, Context
+from homeassistant.core import DOMAIN as HASS_DOMAIN
 from homeassistant.helpers import intent
 from homeassistant.setup import async_setup_component
 
-from tests.common import async_mock_intent, async_mock_service
+from tests.common import async_mock_service
 
 
 @pytest.fixture
@@ -20,111 +20,14 @@ async def init_components(hass):
     assert await async_setup_component(hass, "intent", {})
 
 
-async def test_calling_intent(hass):
-    """Test calling an intent from a conversation."""
-    intents = async_mock_intent(hass, "OrderBeer")
-
-    result = await async_setup_component(hass, "homeassistant", {})
-    assert result
-
-    result = await async_setup_component(
-        hass,
-        "conversation",
-        {"conversation": {"intents": {"OrderBeer": ["I would like the {type} beer"]}}},
-    )
-    assert result
-
-    context = Context()
-
-    await hass.services.async_call(
-        "conversation",
-        "process",
-        {conversation.ATTR_TEXT: "I would like the Grolsch beer"},
-        context=context,
-    )
-    await hass.async_block_till_done()
-
-    assert len(intents) == 1
-    intent = intents[0]
-    assert intent.platform == "conversation"
-    assert intent.intent_type == "OrderBeer"
-    assert intent.slots == {"type": {"value": "Grolsch"}}
-    assert intent.text_input == "I would like the Grolsch beer"
-    assert intent.context is context
-
-
-async def test_register_before_setup(hass):
-    """Test calling an intent from a conversation."""
-    intents = async_mock_intent(hass, "OrderBeer")
-
-    hass.components.conversation.async_register("OrderBeer", ["A {type} beer, please"])
-
-    result = await async_setup_component(
-        hass,
-        "conversation",
-        {"conversation": {"intents": {"OrderBeer": ["I would like the {type} beer"]}}},
-    )
-    assert result
-
-    await hass.services.async_call(
-        "conversation", "process", {conversation.ATTR_TEXT: "A Grolsch beer, please"}
-    )
-    await hass.async_block_till_done()
-
-    assert len(intents) == 1
-    intent = intents[0]
-    assert intent.platform == "conversation"
-    assert intent.intent_type == "OrderBeer"
-    assert intent.slots == {"type": {"value": "Grolsch"}}
-    assert intent.text_input == "A Grolsch beer, please"
-
-    await hass.services.async_call(
-        "conversation",
-        "process",
-        {conversation.ATTR_TEXT: "I would like the Grolsch beer"},
-    )
-    await hass.async_block_till_done()
-
-    assert len(intents) == 2
-    intent = intents[1]
-    assert intent.platform == "conversation"
-    assert intent.intent_type == "OrderBeer"
-    assert intent.slots == {"type": {"value": "Grolsch"}}
-    assert intent.text_input == "I would like the Grolsch beer"
-
-
-async def test_http_processing_intent(hass, hass_client, hass_admin_user):
+async def test_http_processing_intent(
+    hass, init_components, hass_client, hass_admin_user
+):
     """Test processing intent via HTTP API."""
-
-    class TestIntentHandler(intent.IntentHandler):
-        """Test Intent Handler."""
-
-        intent_type = "OrderBeer"
-
-        async def async_handle(self, intent):
-            """Handle the intent."""
-            assert intent.context.user_id == hass_admin_user.id
-            response = intent.create_response()
-            response.async_set_speech(
-                "I've ordered a {}!".format(intent.slots["type"]["value"])
-            )
-            response.async_set_card(
-                "Beer ordered", "You chose a {}.".format(intent.slots["type"]["value"])
-            )
-            return response
-
-    intent.async_register(hass, TestIntentHandler())
-
-    result = await async_setup_component(
-        hass,
-        "conversation",
-        {"conversation": {"intents": {"OrderBeer": ["I would like the {type} beer"]}}},
-    )
-    assert result
-
+    hass.states.async_set("light.kitchen", "on")
     client = await hass_client()
     resp = await client.post(
-        "/api/conversation/process", json={"text": "I would like the Grolsch beer"}
+        "/api/conversation/process", json={"text": "turn on kitchen"}
     )
 
     assert resp.status == HTTPStatus.OK
@@ -133,93 +36,20 @@ async def test_http_processing_intent(hass, hass_client, hass_admin_user):
     assert data == {
         "response": {
             "response_type": "action_done",
-            "card": {
-                "simple": {"content": "You chose a Grolsch.", "title": "Beer ordered"}
-            },
+            "card": {},
             "speech": {
                 "plain": {
                     "extra_data": None,
-                    "speech": "I've ordered a Grolsch!",
+                    "speech": "Turned kitchen on",
                 }
             },
             "language": hass.config.language,
-            "data": {"targets": [], "success": [], "failed": []},
-        },
-        "conversation_id": None,
-    }
-
-
-async def test_http_failed_action(hass, hass_client, hass_admin_user):
-    """Test processing intent via HTTP API with a partial completion."""
-
-    class TestIntentHandler(intent.IntentHandler):
-        """Test Intent Handler."""
-
-        intent_type = "TurnOffLights"
-
-        async def async_handle(self, handle_intent: intent.Intent):
-            """Handle the intent."""
-            response = handle_intent.create_response()
-            area = handle_intent.slots["area"]["value"]
-
-            # Mark some targets as successful, others as failed
-            response.async_set_targets(
-                intent_targets=[
-                    intent.IntentResponseTarget(
-                        type=intent.IntentResponseTargetType.AREA, name=area, id=area
-                    )
-                ]
-            )
-            response.async_set_results(
-                success_results=[
-                    intent.IntentResponseTarget(
-                        type=intent.IntentResponseTargetType.ENTITY,
-                        name="light1",
-                        id="light.light1",
-                    )
-                ],
-                failed_results=[
-                    intent.IntentResponseTarget(
-                        type=intent.IntentResponseTargetType.ENTITY,
-                        name="light2",
-                        id="light.light2",
-                    )
-                ],
-            )
-
-            return response
-
-    intent.async_register(hass, TestIntentHandler())
-
-    result = await async_setup_component(
-        hass,
-        "conversation",
-        {
-            "conversation": {
-                "intents": {"TurnOffLights": ["turn off the lights in the {area}"]}
-            }
-        },
-    )
-    assert result
-
-    client = await hass_client()
-    resp = await client.post(
-        "/api/conversation/process", json={"text": "Turn off the lights in the kitchen"}
-    )
-
-    assert resp.status == HTTPStatus.OK
-    data = await resp.json()
-
-    assert data == {
-        "response": {
-            "response_type": "action_done",
-            "card": {},
-            "speech": {},
-            "language": hass.config.language,
             "data": {
-                "targets": [{"type": "area", "id": "kitchen", "name": "kitchen"}],
-                "success": [{"type": "entity", "id": "light.light1", "name": "light1"}],
-                "failed": [{"type": "entity", "id": "light.light2", "name": "light2"}],
+                "targets": [],
+                "success": [
+                    {"id": "light.kitchen", "name": "kitchen", "type": "entity"}
+                ],
+                "failed": [],
             },
         },
         "conversation_id": None,
@@ -262,24 +92,6 @@ async def test_turn_off_intent(hass, init_components, sentence):
     assert call.data == {"entity_id": "light.kitchen"}
 
 
-@pytest.mark.parametrize("sentence", ("toggle kitchen", "kitchen toggle"))
-async def test_toggle_intent(hass, init_components, sentence):
-    """Test calling the turn on intent."""
-    hass.states.async_set("light.kitchen", "on")
-    calls = async_mock_service(hass, HASS_DOMAIN, "toggle")
-
-    await hass.services.async_call(
-        "conversation", "process", {conversation.ATTR_TEXT: sentence}
-    )
-    await hass.async_block_till_done()
-
-    assert len(calls) == 1
-    call = calls[0]
-    assert call.domain == HASS_DOMAIN
-    assert call.service == "toggle"
-    assert call.data == {"entity_id": "light.kitchen"}
-
-
 async def test_http_api(hass, init_components, hass_client):
     """Test the HTTP conversation API."""
     client = await hass_client()
@@ -324,38 +136,9 @@ async def test_http_api_no_match(hass, init_components, hass_client):
     """Test the HTTP conversation API with an intent match failure."""
     client = await hass_client()
 
-    # Sentence should not match any intents
+    # Shouldn't match any intents
     resp = await client.post("/api/conversation/process", json={"text": "do something"})
-    assert resp.status == HTTPStatus.OK
-    data = await resp.json()
 
-    assert data == {
-        "response": {
-            "card": {},
-            "speech": {
-                "plain": {
-                    "extra_data": None,
-                    "speech": "Sorry, I didn't understand that",
-                },
-            },
-            "language": hass.config.language,
-            "response_type": "error",
-            "data": {
-                "code": "no_intent_match",
-            },
-        },
-        "conversation_id": None,
-    }
-
-
-async def test_http_api_no_valid_targets(hass, init_components, hass_client):
-    """Test the HTTP conversation API with no valid targets."""
-    client = await hass_client()
-
-    # No kitchen light
-    resp = await client.post(
-        "/api/conversation/process", json={"text": "turn on the kitchen"}
-    )
     assert resp.status == HTTPStatus.OK
     data = await resp.json()
 
@@ -365,14 +148,12 @@ async def test_http_api_no_valid_targets(hass, init_components, hass_client):
             "card": {},
             "speech": {
                 "plain": {
+                    "speech": "Sorry, I didn't understand that",
                     "extra_data": None,
-                    "speech": "Unable to find an entity called kitchen",
                 },
             },
             "language": hass.config.language,
-            "data": {
-                "code": "no_valid_targets",
-            },
+            "data": {"code": "no_intent_match"},
         },
         "conversation_id": None,
     }
diff --git a/tests/components/intent/test_init.py b/tests/components/intent/test_init.py
index a936c11d0fafcb63564ff9e50e8d0ebe5e53a16e..40bf79e1c45657c7bc3888abbe38d0390734e9e3 100644
--- a/tests/components/intent/test_init.py
+++ b/tests/components/intent/test_init.py
@@ -168,7 +168,7 @@ async def test_turn_on_multiple_intent(hass):
     calls = async_mock_service(hass, "light", SERVICE_TURN_ON)
 
     response = await intent.async_handle(
-        hass, "test", "HassTurnOn", {"name": {"value": "test lights"}}
+        hass, "test", "HassTurnOn", {"name": {"value": "test lights 2"}}
     )
     await hass.async_block_till_done()
 
diff --git a/tests/components/light/test_intent.py b/tests/components/light/test_intent.py
index 0c837a49c42d94b29b0893fd3c21dc789f34e0ef..458e27bc6c6976d26db2702bc3cfd3bb0cdee09f 100644
--- a/tests/components/light/test_intent.py
+++ b/tests/components/light/test_intent.py
@@ -20,7 +20,7 @@ async def test_intent_set_color(hass):
         hass,
         "test",
         intent.INTENT_SET,
-        {"name": {"value": "Hello"}, "color": {"value": "blue"}},
+        {"name": {"value": "Hello 2"}, "color": {"value": "blue"}},
     )
     await hass.async_block_till_done()
 
@@ -68,7 +68,7 @@ async def test_intent_set_color_and_brightness(hass):
         "test",
         intent.INTENT_SET,
         {
-            "name": {"value": "Hello"},
+            "name": {"value": "Hello 2"},
             "color": {"value": "blue"},
             "brightness": {"value": "20"},
         },
diff --git a/tests/helpers/test_intent.py b/tests/helpers/test_intent.py
index e328d30ab7ad0f29f687735bc6268402ebd280b5..1d7aaeba3667b0754e7e6e6bafafbba520c1868b 100644
--- a/tests/helpers/test_intent.py
+++ b/tests/helpers/test_intent.py
@@ -3,8 +3,9 @@
 import pytest
 import voluptuous as vol
 
+from homeassistant.const import ATTR_FRIENDLY_NAME
 from homeassistant.core import State
-from homeassistant.helpers import config_validation as cv, intent
+from homeassistant.helpers import config_validation as cv, entity_registry, intent
 
 
 class MockIntentHandler(intent.IntentHandler):
@@ -15,14 +16,26 @@ class MockIntentHandler(intent.IntentHandler):
         self.slot_schema = slot_schema
 
 
-def test_async_match_state():
+async def test_async_match_state(hass):
     """Test async_match_state helper."""
-    state1 = State("light.kitchen", "on")
-    state2 = State("switch.kitchen", "on")
+    state1 = State(
+        "light.kitchen", "on", attributes={ATTR_FRIENDLY_NAME: "kitchen light"}
+    )
+    state2 = State(
+        "switch.kitchen", "on", attributes={ATTR_FRIENDLY_NAME: "kitchen switch"}
+    )
+    registry = entity_registry.async_get(hass)
+    registry.async_get_or_create(
+        "switch", "demo", "1234", suggested_object_id="kitchen"
+    )
+    registry.async_update_entity(state2.entity_id, aliases={"kill switch"})
 
-    state = intent.async_match_state(None, "kitch", [state1, state2])
+    state = intent.async_match_state(hass, "kitchen light", [state1, state2])
     assert state is state1
 
+    state = intent.async_match_state(hass, "kill switch", [state1, state2])
+    assert state is state2
+
 
 def test_async_validate_slots():
     """Test async_validate_slots of IntentHandler."""
@@ -38,21 +51,3 @@ def test_async_validate_slots():
     handler1.async_validate_slots(
         {"name": {"value": "kitchen"}, "probability": {"value": "0.5"}}
     )
-
-
-def test_fuzzy_match():
-    """Test _fuzzymatch."""
-    state1 = State("light.living_room_northwest", "off")
-    state2 = State("light.living_room_north", "off")
-    state3 = State("light.living_room_northeast", "off")
-    state4 = State("light.living_room_west", "off")
-    state5 = State("light.living_room", "off")
-    states = [state1, state2, state3, state4, state5]
-
-    state = intent._fuzzymatch("Living Room", states, lambda state: state.name)
-    assert state == state5
-
-    state = intent._fuzzymatch(
-        "Living Room Northwest", states, lambda state: state.name
-    )
-    assert state == state1